diff options
Diffstat (limited to 'megapixels/app')
| -rw-r--r-- | megapixels/app/processors/face_age.py | 8 | ||||
| -rw-r--r-- | megapixels/app/processors/face_beauty.py | 6 | ||||
| -rw-r--r-- | megapixels/app/processors/face_detector.py | 11 | ||||
| -rw-r--r-- | megapixels/app/processors/face_emotion.py | 10 | ||||
| -rw-r--r-- | megapixels/app/processors/face_gender.py | 9 | ||||
| -rw-r--r-- | megapixels/app/processors/face_landmarks_3d.py | 99 | ||||
| -rw-r--r-- | megapixels/app/processors/face_recognition.py | 9 | ||||
| -rw-r--r-- | megapixels/app/settings/app_cfg.py | 1 | ||||
| -rw-r--r-- | megapixels/app/utils/draw_utils.py | 8 |
9 files changed, 42 insertions, 119 deletions
diff --git a/megapixels/app/processors/face_age.py b/megapixels/app/processors/face_age.py index 222858a5..35174628 100644 --- a/megapixels/app/processors/face_age.py +++ b/megapixels/app/processors/face_age.py @@ -18,11 +18,11 @@ class FaceAge: # Estimates face age - def __init__(self): + def __init__(self, gpu=0): self.log = logger_utils.Logger.getLogger() pass - def age(self): - # use enum typed emotions - return {'age': types.Age.ADULT, 'confidence': 0.5}
\ No newline at end of file + def age(self, im, bbox_dim): + self.log.warn('not yet implemented') + return 0.0
\ No newline at end of file diff --git a/megapixels/app/processors/face_beauty.py b/megapixels/app/processors/face_beauty.py index 2e8221b7..a01c6834 100644 --- a/megapixels/app/processors/face_beauty.py +++ b/megapixels/app/processors/face_beauty.py @@ -9,12 +9,10 @@ import numpy as np import imutils import pickle -os.environ['CUDA_VISIBLE_DEVICES'] = '' import keras from keras.layers import Conv2D, Input, MaxPool2D,Flatten, Dense, Permute, GlobalAveragePooling2D from keras.models import Model from keras.optimizers import adam -import os.path from keras.models import Sequential from keras.applications.resnet50 import ResNet50 #from keras.applications.resnet50 import Dense @@ -33,7 +31,9 @@ class FaceBeauty: # Estimates beauty using CNN - def __init__(self, gpu=-1): + def __init__(self): + # ensure Keras uses CPU (no GPU, it takes up all memory) + os.environ['CUDA_VISIBLE_DEVICES'] = '' # don't really need GPU, CPU is quick enough self.log = logger_utils.Logger.getLogger() resnet = ResNet50(include_top=False, pooling='avg') diff --git a/megapixels/app/processors/face_detector.py b/megapixels/app/processors/face_detector.py index c0762564..0e194f7d 100644 --- a/megapixels/app/processors/face_detector.py +++ b/megapixels/app/processors/face_detector.py @@ -21,9 +21,14 @@ class DetectorMTCNN: dnn_size = (300, 300) - def __init__(self, size=(400,400)): + def __init__(self, size=(400,400), gpu=0): + self.log = logger_utils.Logger.getLogger() + device_cur = os.getenv('CUDA_VISIBLE_DEVICES', '') + self.log.info(f'Change CUDA_VISIBLE_DEVICES from "{device_cur}" to "{gpu}"') + os.environ['CUDA_VISIBLE_DEVICES'] = str(gpu) from mtcnn.mtcnn import MTCNN self.detector = MTCNN() + os.environ['CUDA_VISIBLE_DEVICES'] = device_cur # reset def detect(self, im, size=(400,400), conf_thresh=None, pyramids=None, largest=False, zone=None): '''Detects face using MTCNN and returns (list) of BBox @@ -70,14 +75,14 @@ class DetectorDLIBCNN: def __init__(self, gpu=0): import dlib self.log = logger_utils.Logger.getLogger() - cuda_visible_devices = os.getenv('CUDA_VISIBLE_DEVICES', '') + device_cur = os.getenv('CUDA_VISIBLE_DEVICES', '') if dlib.DLIB_USE_CUDA and gpu < 0: self.log.error('dlib was compiled with CUDA but you selected CPU. Use GPU >= 0 if dlib.DLIB_USE_CUDA') sys.exit() os.environ['CUDA_VISIBLE_DEVICES'] = str(gpu) self.log.info('load model: {}'.format(cfg.DIR_MODELS_DLIB_CNN)) self.detector = dlib.cnn_face_detection_model_v1(cfg.DIR_MODELS_DLIB_CNN) - os.environ['CUDA_VISIBLE_DEVICES'] = cuda_visible_devices # reset + os.environ['CUDA_VISIBLE_DEVICES'] = device_cur # reset def detect(self, im, conf_thresh=None, pyramids=None, largest=False, zone=None): bboxes = [] diff --git a/megapixels/app/processors/face_emotion.py b/megapixels/app/processors/face_emotion.py index c45da9ba..a04d7afd 100644 --- a/megapixels/app/processors/face_emotion.py +++ b/megapixels/app/processors/face_emotion.py @@ -16,13 +16,13 @@ from app.settings import types class FaceEmotion: - # Estimates face emotion + # Estimates face age - def __init__(self): + def __init__(self, gpu=0): self.log = logger_utils.Logger.getLogger() pass - def emotion(self): - # use enum typed emotions - return {'emotion': types.Emotion.NEUTRAL, 'confidence': 0.5}
\ No newline at end of file + def emotion(self, im, bbox_dim): + self.log.warn('not yet implemented') + return 0.0
\ No newline at end of file diff --git a/megapixels/app/processors/face_gender.py b/megapixels/app/processors/face_gender.py index ee152098..ea64b828 100644 --- a/megapixels/app/processors/face_gender.py +++ b/megapixels/app/processors/face_gender.py @@ -16,12 +16,13 @@ from app.settings import types class FaceGender: - # Estimates gender using CNN + # Estimates face age - def __init__(self): + def __init__(self, gpu=0): self.log = logger_utils.Logger.getLogger() pass - def gender(self): - return 'm'
\ No newline at end of file + def gender(self, im, bbox_dim): + self.log.warn('not yet implemented') + return 0.0
\ No newline at end of file diff --git a/megapixels/app/processors/face_landmarks_3d.py b/megapixels/app/processors/face_landmarks_3d.py deleted file mode 100644 index 5a0d6097..00000000 --- a/megapixels/app/processors/face_landmarks_3d.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -from os.path import join -from pathlib import Path -import math - -import cv2 as cv -import numpy as np -import imutils - -from app.utils import im_utils, logger_utils -from app.models.bbox import BBox -from app.settings import app_cfg as cfg -from app.settings import types - -class Landmarks3D: - - def __init__(self): - self.log = logger_utils.Logger.getLogger() - - def landmarks(self, im, bbox): - pass - - -class FaceAlignment3D(Landmarks3D): - - # Estimates 3D facial landmarks - import face_alignment - - def __init__(self, gpu=0, flip_input=True): - super().__init__() - device = f'cuda:{gpu}' if gpu > -1 else 'cpu' - self.fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._3D, device=device, flip_input=flip_input) - - def landmarks(self, im, bbox, as_type=str): - '''Calculates the 3D facial landmarks - :param im: (numpy.ndarray) image - :param bbox: (BBox) dimensioned to real (int) sizes - :param as_type: (str) or (list) type to return data - ''' - preds = self.fa.get_landmarks(im) - # convert to comma separated ints - # storing data as "[1,2], [3,4]" is larger file size than storing as "1,2,3,4" - # storing a list object in Pandas seems to result in 30% larger CSV files - # TODO optimize this - preds_int = [list(map(int, x)) for x in preds[0]] # list of ints - if as_type is str: - return ','.join([','.join(list(map(str,[x,y]))) for x,y in preds_int]) - else - return preds_int - - - def draw(self, im): - '''draws landmarks in 3d scene''' - - # TODO - ''' - import face_alignment - import numpy as np - from mpl_toolkits.mplot3d import Axes3D - import matplotlib.pyplot as plt - from skimage import io - - # Run the 3D face alignment on a test image, without CUDA. - fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._3D, device='cuda:0', flip_input=True) - - input = io.imread('../test/assets/aflw-test.jpg') - preds = fa.get_landmarks(input)[-1] - - #TODO: Make this nice - fig = plt.figure(figsize=plt.figaspect(.5)) - ax = fig.add_subplot(1, 2, 1) - ax.imshow(input) - ax.plot(preds[0:17,0],preds[0:17,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[17:22,0],preds[17:22,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[22:27,0],preds[22:27,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[27:31,0],preds[27:31,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[31:36,0],preds[31:36,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[36:42,0],preds[36:42,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[42:48,0],preds[42:48,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[48:60,0],preds[48:60,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.plot(preds[60:68,0],preds[60:68,1],marker='o',markersize=6,linestyle='-',color='w',lw=2) - ax.axis('off') - - ax = fig.add_subplot(1, 2, 2, projection='3d') - surf = ax.scatter(preds[:,0]*1.2,preds[:,1],preds[:,2],c="cyan", alpha=1.0, edgecolor='b') - ax.plot3D(preds[:17,0]*1.2,preds[:17,1], preds[:17,2], color='blue' ) - ax.plot3D(preds[17:22,0]*1.2,preds[17:22,1],preds[17:22,2], color='blue') - ax.plot3D(preds[22:27,0]*1.2,preds[22:27,1],preds[22:27,2], color='blue') - ax.plot3D(preds[27:31,0]*1.2,preds[27:31,1],preds[27:31,2], color='blue') - ax.plot3D(preds[31:36,0]*1.2,preds[31:36,1],preds[31:36,2], color='blue') - ax.plot3D(preds[36:42,0]*1.2,preds[36:42,1],preds[36:42,2], color='blue') - ax.plot3D(preds[42:48,0]*1.2,preds[42:48,1],preds[42:48,2], color='blue') - ax.plot3D(preds[48:,0]*1.2,preds[48:,1],preds[48:,2], color='blue' ) - - ax.view_init(elev=90., azim=90.) - ax.set_xlim(ax.get_xlim()[::-1]) - plt.show() - ''' - return im
\ No newline at end of file diff --git a/megapixels/app/processors/face_recognition.py b/megapixels/app/processors/face_recognition.py index a56b1634..76f00aa1 100644 --- a/megapixels/app/processors/face_recognition.py +++ b/megapixels/app/processors/face_recognition.py @@ -54,6 +54,15 @@ class RecognitionDLIB: #vec = self.facerec.compute_face_descriptor(im, face_shape) return vec + def flatten(self, vec): + '''Converts 128D vector into a flattened list for CSV + :param points: (list) a feature vector as list of floats + :returns dict item for each point (eg {'d1':0.28442156, 'd1': 0.1868632}) + ''' + vec_flat = {} + for idx, val in enumerate(vec, 1): + vec_flat[f'd{idx}'] = val + return vec_flat def similarity(self, query_enc, known_enc): return np.linalg.norm(query_enc - known_enc, axis=1) diff --git a/megapixels/app/settings/app_cfg.py b/megapixels/app/settings/app_cfg.py index d206f40b..2d51a607 100644 --- a/megapixels/app/settings/app_cfg.py +++ b/megapixels/app/settings/app_cfg.py @@ -44,6 +44,7 @@ DIR_MODELS_DARKNET_PJREDDIE = join(DIR_MODELS_DARKNET, 'pjreddie') DIR_MODELS_PYTORCH = join(DIR_MODELS,'pytorch') DIR_MODELS_TORCH = join(DIR_MODELS,'torch') DIR_MODELS_MXNET = join(DIR_MODELS,'mxnet') +DIR_MODELS_KERAS = join(DIR_MODELS,'keras') DIR_MODELS_TF = join(DIR_MODELS,'tensorflow') DIR_MODELS_DLIB = join(DIR_MODELS,'dlib') DIR_MODELS_DLIB_CNN = join(DIR_MODELS_DLIB, 'mmod_human_face_detector.dat') diff --git a/megapixels/app/utils/draw_utils.py b/megapixels/app/utils/draw_utils.py index 47bb7978..cafac5a5 100644 --- a/megapixels/app/utils/draw_utils.py +++ b/megapixels/app/utils/draw_utils.py @@ -34,12 +34,18 @@ def draw_bbox(im, bbox, color=(0,255,0), stroke_weight=2): def draw_pose(im, pt_nose, image_pts): '''Draws 3-axis pose over image - ''' + ''' cv.line(im, pt_nose, tuple(image_pts['pitch'].ravel()), pose_types['pitch'], 3) cv.line(im, pt_nose, tuple(image_pts['yaw'].ravel()), pose_types['yaw'], 3) cv.line(im, pt_nose, tuple(image_pts['roll'].ravel()), pose_types['roll'], 3) +def draw_text(im, pt, text, color=(0,255,0)): + '''Draws degrees as text over image + ''' + cv.putText(im, text, pt, cv.FONT_HERSHEY_SIMPLEX, 0.5, color, thickness=2, lineType=2) + + def draw_degrees(im, pose_data, color=(0,255,0)): '''Draws degrees as text over image ''' |
