diff options
Diffstat (limited to 'megapixels/app')
| -rw-r--r-- | megapixels/app/models/bbox.py | 57 | ||||
| -rw-r--r-- | megapixels/app/processors/face_detector.py | 15 | ||||
| -rw-r--r-- | megapixels/app/settings/app_cfg.py | 13 | ||||
| -rw-r--r-- | megapixels/app/settings/types.py | 4 | ||||
| -rw-r--r-- | megapixels/app/utils/file_utils.py | 6 | ||||
| -rw-r--r-- | megapixels/app/utils/im_utils.py | 37 |
6 files changed, 103 insertions, 29 deletions
diff --git a/megapixels/app/models/bbox.py b/megapixels/app/models/bbox.py index 41b67416..ccdf229e 100644 --- a/megapixels/app/models/bbox.py +++ b/megapixels/app/models/bbox.py @@ -1,6 +1,9 @@ +import math + from dlib import rectangle as dlib_rectangle import numpy as np + class BBoxPoint: def __init__(self, x, y): @@ -105,7 +108,12 @@ class BBox: # # Utils # def constrain(self, dim): - + def distance(self, b): + a = self + dcx = self._cx - b.cx + dcy = self._cy - b.cy + d = int(math.sqrt(math.pow(dcx, 2) + math.pow(dcy, 2))) + return d # ----------------------------------------------------------------- # Modify @@ -117,26 +125,40 @@ class BBox: :returns (BBox) in pixel dimensions """ # expand - rect_exp = list( (np.array(self._rect) + np.array([-amt, -amt, amt, amt])).astype('int')) + r = list( (np.array(self._rect) + np.array([-amt, -amt, amt, amt])).astype('int')) # outliers oob = list(range(4)) - oob[0] = min(rect_exp[0], 0) - oob[1] = min(rect_exp[1], 0) - oob[2] = dim[0] - max(rect_exp[2], 2) - oob[3] = dim[1] - max(rect_exp[3], 3) + oob[0] = min(r[0], 0) + oob[1] = min(r[1], 0) + oob[2] = dim[0] - r[2] + oob[3] = dim[1] - r[3] oob = np.array(oob) oob[oob > 0] = 0 - # amount + # absolute amount oob = np.absolute(oob) - # threshold - rect_exp[0] = max(rect_exp[0], 0) - rect_exp[1] = max(rect_exp[1], 0) - rect_exp[2] = min(rect_exp[2], dim[0]) - rect_exp[3] = min(rect_exp[3], dim[1]) + # threshold expanded rectangle + r[0] = max(r[0], 0) + r[1] = max(r[1], 0) + r[2] = min(r[2], dim[0]) + r[3] = min(r[3], dim[1]) # redistribute oob amounts oob = np.array([-oob[2], -oob[3], oob[0], oob[1]]) - rect_exp = np.add(np.array(rect_exp), oob) - return BBox(*rect_exp) + r = np.add(np.array(r), oob) + # find overage + oob[0] = min(r[0], 0) + oob[1] = min(r[1], 0) + oob[2] = dim[0] - r[2] + oob[3] = dim[1] - r[3] + oob = np.array(oob) + oob[oob > 0] = 0 + oob = np.absolute(oob) + if np.array(oob).any(): + m = np.max(oob) + adj = np.array([m, m, -m, -m]) + # print(adj) + r = np.add(np.array(r), adj) + + return BBox(*r) # ----------------------------------------------------------------- @@ -199,6 +221,13 @@ class BBox: return cls(*rect) @classmethod + def from_xyxy(cls, x1, y1, x2, y2): + """Converts x1, y1, x2, y2 to BBox + same as constructure but zprovided for conveniene + """ + return cls(x1, y1, x2, y2) + + @classmethod def from_xywh(cls, x, y, w, h): """Converts x1, y1, w, h to BBox :param rect: (list) x1, y1, w, h diff --git a/megapixels/app/processors/face_detector.py b/megapixels/app/processors/face_detector.py index 02d068dc..747e057b 100644 --- a/megapixels/app/processors/face_detector.py +++ b/megapixels/app/processors/face_detector.py @@ -11,13 +11,26 @@ from app.utils import im_utils, logger_utils from app.models.bbox import BBox from app.settings import app_cfg as cfg + +class DetectorHaar: + + im_size = (400, 400) + cascade_name = types.HaarCascade.FRONTAL + + def __init__(self, cascade=types.HaarCascade.FRONTAL): + self.log = logger_utils.Logger.getLogger() + + def detect(self, im, scale_factor=1.05, overlaps=5): + return + + class DetectorDLIBCNN: dnn_size = (300, 300) pyramids = 0 conf_thresh = 0.85 - def __init__(self, opt_gpu): + def __init__(self, opt_gpu=0): self.log = logger_utils.Logger.getLogger() cuda_visible_devices = os.getenv('CUDA_VISIBLE_DEVICES', '') os.environ['CUDA_VISIBLE_DEVICES'] = str(opt_gpu) diff --git a/megapixels/app/settings/app_cfg.py b/megapixels/app/settings/app_cfg.py index 739ddce2..3e60a9b4 100644 --- a/megapixels/app/settings/app_cfg.py +++ b/megapixels/app/settings/app_cfg.py @@ -14,11 +14,14 @@ from app.utils import click_utils # ----------------------------------------------------------------------------- FaceDetectNetVar = click_utils.ParamVar(types.FaceDetectNet) - +HaarCascadeVar = click_utils.ParamVar(types.HaarCascade) LogLevelVar = click_utils.ParamVar(types.LogLevel) # # data_store DATA_STORE = '/data_store_hdd/' +DATA_STORE_NAS = '/data_store_nas/' +DATA_STORE_HDD = '/data_store_hdd/' +DATA_STORE_SSD = '/data_store_ssd/' DIR_DATASETS = join(DATA_STORE,'datasets') DIR_APPS = join(DATA_STORE,'apps') DIR_APP = join(DIR_APPS,'megapixels') @@ -38,6 +41,8 @@ DIR_MODELS_DLIB_5PT = join(DIR_MODELS_DLIB, 'shape_predictor_5_face_landmarks.da DIR_MODELS_DLIB_68PT = join(DIR_MODELS_DLIB, 'shape_predictor_68_face_landmarks.dat') +types.HaarCascade.FRONTAL + # Test images DIR_TEST_IMAGES = join(DIR_APP, 'test', 'images') @@ -51,8 +56,10 @@ FP_FONT = join(DIR_ASSETS, 'font') # ----------------------------------------------------------------------------- # click chair settings # ----------------------------------------------------------------------------- -DIR_COMMANDS_PROCESSOR_ADMIN = 'admin/commands' -DIR_COMMANDS_PROCESSOR_DATASETS = 'datasets/commands' +DIR_COMMANDS_CV = 'commands/cv' +DIR_COMMANDS_ADMIN = 'commands/admin' +DIR_COMMANDS_DATASETS = 'commands/datasets' +DIR_COMMANDS_MISC = 'commands/misc' # ----------------------------------------------------------------------------- # Filesystem settings diff --git a/megapixels/app/settings/types.py b/megapixels/app/settings/types.py index 0c3d7942..52470034 100644 --- a/megapixels/app/settings/types.py +++ b/megapixels/app/settings/types.py @@ -20,6 +20,10 @@ class CVTarget(Enum): """OpenCV 3.4.2+ DNN backend processor type""" CPU, OPENCL, OPENCL_FP16, MYRIAD = range(4) +class HaarCascade(Enum): + FRONTAL, ALT, ALT2, PROFILE = range(4) + + # --------------------------------------------------------------------- # Logger, monitoring # -------------------------------------------------------------------- diff --git a/megapixels/app/utils/file_utils.py b/megapixels/app/utils/file_utils.py index 773667b1..99282bd0 100644 --- a/megapixels/app/utils/file_utils.py +++ b/megapixels/app/utils/file_utils.py @@ -175,7 +175,7 @@ def write_pickle(data, fp_out, ensure_path=True): pickle.dump(data, fp) -def write_json(data, fp_out, minify=True, ensure_path=True, sort_keys=True): +def write_json(data, fp_out, minify=True, ensure_path=True, sort_keys=True, verbose=False): """ """ if ensure_path: @@ -185,6 +185,8 @@ def write_json(data, fp_out, minify=True, ensure_path=True, sort_keys=True): json.dump(data, fp, separators=(',',':'), sort_keys=sort_keys) else: json.dump(data, fp, indent=2, sort_keys=sort_keys) + if verbose: + log.info('Wrote JSON: {}'.format(fp_out)) def write_csv(data, fp_out, header=None): """ """ @@ -277,7 +279,7 @@ def sha256(fp_in, block_size=65536): """ sha256 = hashlib.sha256() with open(fp_in, 'rb') as fp: - for block in iter(lambda: f.read(block_size), b''): + for block in iter(lambda: fp.read(block_size), b''): sha256.update(block) return sha256.hexdigest() diff --git a/megapixels/app/utils/im_utils.py b/megapixels/app/utils/im_utils.py index a0f23cd2..d5e92aa3 100644 --- a/megapixels/app/utils/im_utils.py +++ b/megapixels/app/utils/im_utils.py @@ -22,6 +22,16 @@ import datetime +def is_grayscale(im, threshold=5): + """Returns True if image is grayscale + :param im: (numpy.array) image + :return (bool) of if image is grayscale""" + b = im[:,:,0] + g = im[:,:,1] + mean = np.mean(np.abs(g - b)) + return mean < threshold + + def compute_features(fe,frames,phashes,phash_thresh=1): """ Get vector embedding using FeatureExtractor @@ -40,7 +50,7 @@ def compute_features(fe,frames,phashes,phash_thresh=1): return vals -def ensure_pil(im, bgr2rgb=False): +def np2pil(im, swap=True): """Ensure image is Pillow format :param im: image in numpy or PIL.Image format :returns: image in Pillow RGB format @@ -49,35 +59,44 @@ def ensure_pil(im, bgr2rgb=False): im.verify() return im except: - if bgr2rgb: + if swap: im = cv.cvtColor(im,cv.COLOR_BGR2RGB) return Image.fromarray(im.astype('uint8'), 'RGB') -def ensure_np(im): +def pil2np(im, swap=True): """Ensure image is Numpy.ndarry format :param im: image in numpy or PIL.Image format :returns: image in Numpy uint8 format """ if type(im) == np.ndarray: - return im - return np.asarray(im, np.uint8) + return im + im = np.asarray(im, np.uint8) + if swap: + im = cv.cvtColor(im, cv.COLOR_RGB2BGR) + return im -def resize(im,width=0,height=0): +def resize(im, width=0, height=0): """resize image using imutils. Use w/h=[0 || None] to prioritize other edge size :param im: a Numpy.ndarray image :param wh: a tuple of (width, height) """ + # TODO change to cv.resize and add algorithm choices w = width h = height if w is 0 and h is 0: return im elif w > 0 and h > 0: - return imutils.resize(im,width=w,height=h) + ws = im.shape[1] / w + hs = im.shape[0] / h + if ws > hs: + return imutils.resize(im, width=w) + else: + return imutils.resize(im, height=h) elif w > 0 and h is 0: - return imutils.resize(im,width=w) + return imutils.resize(im, width=w) elif w is 0 and h > 0: - return imutils.resize(im,height=h) + return imutils.resize(im, height=h) else: return im |
