summaryrefslogtreecommitdiff
path: root/megapixels/app
diff options
context:
space:
mode:
authoradamhrv <adam@ahprojects.com>2018-12-05 12:00:15 +0100
committeradamhrv <adam@ahprojects.com>2018-12-05 12:00:15 +0100
commit90abf459d1df1f21960c1d653a1f936d1ec30256 (patch)
treefacab8e9bac6c56e69c369c2140cdbea218a01df /megapixels/app
parent0529d4cd1618016319e995c37aa118bf8c2d501b (diff)
.
Diffstat (limited to 'megapixels/app')
-rw-r--r--megapixels/app/models/bbox.py57
-rw-r--r--megapixels/app/processors/face_detector.py15
-rw-r--r--megapixels/app/settings/app_cfg.py13
-rw-r--r--megapixels/app/settings/types.py4
-rw-r--r--megapixels/app/utils/file_utils.py6
-rw-r--r--megapixels/app/utils/im_utils.py37
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