summaryrefslogtreecommitdiff
path: root/megapixels/commands/demo
diff options
context:
space:
mode:
authoradamhrv <adam@ahprojects.com>2019-01-16 13:30:16 +0100
committeradamhrv <adam@ahprojects.com>2019-01-16 13:30:16 +0100
commit65cb506ca182272e2701136097fd00c55dc6bd69 (patch)
treecc5be8e61a8d5173745be1d331b210e967e146b5 /megapixels/commands/demo
parentfceeb3b7adbc8d522e9fe1c40e12e9a529199068 (diff)
change bbox to norm, refine face extractor
Diffstat (limited to 'megapixels/commands/demo')
-rw-r--r--megapixels/commands/demo/face_3ddfa.py85
-rw-r--r--megapixels/commands/demo/face_age_gender.py31
-rw-r--r--megapixels/commands/demo/face_beauty.py12
-rw-r--r--megapixels/commands/demo/face_detect.py (renamed from megapixels/commands/demo/face_detection.py)57
-rw-r--r--megapixels/commands/demo/face_landmarks_2d.py155
-rw-r--r--megapixels/commands/demo/face_landmarks_3d.py82
-rw-r--r--megapixels/commands/demo/face_pose.py25
-rw-r--r--megapixels/commands/demo/face_search.py40
-rw-r--r--megapixels/commands/demo/face_vector.py28
9 files changed, 148 insertions, 367 deletions
diff --git a/megapixels/commands/demo/face_3ddfa.py b/megapixels/commands/demo/face_3ddfa.py
index 6182aeb6..90359159 100644
--- a/megapixels/commands/demo/face_3ddfa.py
+++ b/megapixels/commands/demo/face_3ddfa.py
@@ -1,7 +1,7 @@
'''
Combines 3D face mode + rendering
-https://github.com/cleardusk/3DDFA
-https://github.com/YadiraF/face3d
+https://github.com/cleardusk/3DDFA --> 3d landmarks
+https://github.com/YadiraF/face3d --> render 3D with lighting as 2.5d image
'''
import click
@@ -13,8 +13,8 @@ from app.settings import app_cfg as cfg
@click.command()
@click.option('-i', '--input', 'opt_fp_in', default=None, required=True,
help='Image filepath')
-@click.option('-o', '--output', 'opt_fp_out', default=None,
- help='GIF output path')
+@click.option('-o', '--output', 'opt_dir_out', default=None,
+ help='Directory for output files')
@click.option('--size', 'opt_size',
type=(int, int), default=(300, 300),
help='Output image size')
@@ -27,11 +27,13 @@ from app.settings import app_cfg as cfg
@click.option('--size', 'opt_render_dim',
type=(int, int), default=(512, 512),
help='2.5D render image size')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
+@click.option('--save/--no-save', 'opt_save', is_flag=True, default=True,
+ help='Save output images/files')
@click.pass_context
-def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
- opt_size, opt_render_dim, opt_force, opt_display):
+def cli(ctx, opt_fp_in, opt_dir_out, opt_gpu, opt_bbox_init,
+ opt_size, opt_render_dim, opt_force, opt_display, opt_save):
"""3D face demo"""
import sys
@@ -58,6 +60,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
import scipy.io as sio
sys.path.append(join(Path.cwd().parent, '3rdparty'))
+ # git clone https://github.com/cleardusk/3DDFA 3rdparty/d3ddfa
# change name of 3DDFA to d3DDFA because can't start with number
from d3DDFA import mobilenet_v1
from d3DDFA.utils.ddfa import ToTensorGjz, NormalizeGjz, str2bool
@@ -70,7 +73,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
from d3DDFA.utils.render import get_depths_image, cget_depths_image, cpncc
from d3DDFA.utils import paf as d3dfa_paf_utils
- # https://github.com/YadiraF/face3d
+ # git clone https://github.com/YadiraF/face3d 3rdparty/face3d
# compile cython module in face3d/mesh/cython/ python setup.py build_ext -i
from face3d.face3d import mesh as face3d_mesh
@@ -82,13 +85,11 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
fpp_in = Path(opt_fp_in)
im = cv.imread(opt_fp_in)
- #im = im_utils.resize(im_orig, width=opt_size[0], height=opt_size[1])
- # im = im_orig.copy()
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN() # -1 for CPU
bboxes = face_detector.detect(im, largest=True)
bbox = bboxes[0]
dim = im.shape[:2][::-1]
@@ -165,7 +166,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
# dense face 3d vertices
vertices = d3dfa_utils.predict_dense(param, roi_box)
vertices_lst.append(vertices)
-
log.info(f'generated 3d data in: {(time.time() - st):.2f}s')
# filepath helper function
@@ -183,28 +183,20 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
sio.savemat(fp_mat_3df, {'vertices': vertices, 'colors': colors, 'triangles': triangles})
# save PAF
- #fp_paf = to_fp(fpp_in, 'jpg', suffix='paf')
- #opt_paf_size = 3 # PAF feature kernel size
- #im_paf = d3dfa_paf_utils.gen_img_paf(img_crop=im_crop, param=param, kernel_size=opt_paf_size)
- #cv.imwrite(fp_paf, im_paf)
+ im_paf = d3dfa_paf_utils.gen_img_paf(img_crop=im_crop, param=param, kernel_size=3)
# save pose image
# P, pose = parse_pose(param) # Camera matrix (without scale), and pose (yaw, pitch, roll, to verify)
- img_pose = draw_utils.plot_pose_box(im, Ps, pts_res)
- fp_pose = to_fp(fpp_in, 'jpg', suffix='pose')
- cv.imwrite(fp_pose, img_pose)
+ im_pose = draw_utils.plot_pose_box(im, Ps, pts_res)
# save depth image
- fp_depth = to_fp(fpp_in, 'png', suffix='depth')
# depths_img = get_depths_image(im, vertices_lst, tri-1) # python version
im_depth = cget_depths_image(im, vertices_lst, triangles - 1) # cython version
- cv.imwrite(fp_depth, im_depth)
# save pncc image
- fp_pose = to_fp(fpp_in, 'png', suffix='pncc')
pncc_feature = cpncc(im, vertices_lst, triangles - 1) # cython version
- cv.imwrite(fp_pose, pncc_feature[:, :, ::-1]) # cv.imwrite will swap RGB -> BGR
+ im_pncc = pncc_feature[:, :, ::-1] # swap BGR
# save .ply
#fp_ply = to_fp(fpp_in, 'ply')
@@ -228,8 +220,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
# save obj
colors = d3dfa_utils.get_colors(im, vertices_orig)
- fp_obj = to_fp(fpp_in, 'obj')
- write_obj_with_colors(fp_obj, vertices_orig, triangles, colors)
#fp_landmarks = to_fp(fpp_in, 'jpg', suffix='3DDFA')
# show_flg?
@@ -276,30 +266,39 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
vertices_proj = face3d_mesh.transform.orthographic_project(vertices_cam)
# -------------------------------------------------------------------------
- # render 2D image
+ # render 2D images
w = h = max(opt_render_dim)
vertices_im = face3d_mesh.transform.to_image(vertices_proj, h, w)
- rendering = face3d_mesh.render.render_colors(vertices_im, triangles, colors_lit, h, w)
-
- cv.imshow('', rendering)
- display_utils.handle_keyboard()
+ im_render = face3d_mesh.render.render_colors(vertices_im, triangles, colors_lit, h, w)
+ im_render = (255* im_render).astype(np.uint8)
+ im_pncc = im_pncc.astype(np.uint8)
+ im_depth = im_depth.astype(np.uint8)
+ im_paf = im_paf.astype(np.uint8)
# ----------------------------------------------------------------------------
# save
- if opt_fp_out:
- # save pose only
- fpp_out = Path(opt_fp_out)
+ if opt_save:
+ fpp_out = Path(opt_dir_out) if opt_dir_out is not None else Path(opt_fp_in).parent
+ fpp_in = Path(opt_fp_in)
+ fp_out = join(fpp_out, f'{fpp_in.stem}_render.png')
+ cv.imwrite(fp_out, im_render)
+
+ fp_out = join(fpp_out, f'{fpp_in.stem}_pose.png')
+ cv.imwrite(fp_out, im_pose)
- fp_out = join(fpp_out.parent, f'{fpp_out.stem}_real{fpp_out.suffix}')
- cv.imwrite(fp_out, im_age_real)
+ fp_out = join(fpp_out, f'{fpp_in.stem}_depth.png')
+ cv.imwrite(fp_out, im_depth)
+
+ fp_out = join(fpp_out, f'{fpp_in.stem}_pncc.png')
+ cv.imwrite(fp_out, im_pncc)
- fp_out = join(fpp_out.parent, f'{fpp_out.stem}_apparent{fpp_out.suffix}')
- cv.imwrite(fp_out, im_age_apparent)
+ fp_out = join(fpp_out, f'{fpp_in.stem}_paf.png')
+ cv.imwrite(fp_out, im_paf)
- fp_out = join(fpp_out.parent, f'{fpp_out.stem}_gender{fpp_out.suffix}')
- cv.imwrite(fp_out, im_age_apparent)
+ fp_out = join(fpp_out, f'{fpp_in.stem}.obj')
+ write_obj_with_colors(fp_out, vertices_orig, triangles, colors)
# ----------------------------------------------------------------------------
@@ -307,8 +306,10 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_bbox_init,
if opt_display:
# show all images here
- cv.imshow('real', im_age_real)
- cv.imshow('apparent', im_age_apparent)
- cv.imshow('gender', im_gender)
+ cv.imshow('3d', im_render)
+ cv.imshow('depth', im_depth)
+ cv.imshow('pncc', im_pncc)
+ cv.imshow('pose', im_pose)
+ cv.imshow('paf', im_paf)
display_utils.handle_keyboard()
diff --git a/megapixels/commands/demo/face_age_gender.py b/megapixels/commands/demo/face_age_gender.py
index c74f1e45..c4f09c13 100644
--- a/megapixels/commands/demo/face_age_gender.py
+++ b/megapixels/commands/demo/face_age_gender.py
@@ -17,7 +17,7 @@ from app.settings import app_cfg as cfg
help='GPU index')
@click.option('-f', '--force', 'opt_force', is_flag=True,
help='Force overwrite file')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
@click.pass_context
def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
@@ -52,12 +52,12 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN()
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
else:
@@ -70,21 +70,24 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# real
age_real_predictor = face_age_gender.FaceAgeReal()
st = time.time()
- age_real = age_real_predictor.predict(im_resized, bbox_dim)
+ age_real = age_real_predictor.predict(im_resized, bbox_norm)
log.info(f'age real took: {(time.time()-st)/1000:.5f}s')
# apparent
age_apparent_predictor = face_age_gender.FaceAgeApparent()
st = time.time()
- age_apparent = age_apparent_predictor.predict(im_resized, bbox_dim)
+ age_apparent = age_apparent_predictor.predict(im_resized, bbox_norm)
log.info(f'age apparent took: {(time.time()-st)/1000:.5f}s')
# gender
gender_predictor = face_age_gender.FaceGender()
st = time.time()
- gender = gender_predictor.predict(im_resized, bbox_dim)
+ gender = gender_predictor.predict(im_resized, bbox_norm)
log.info(f'gender took: {(time.time()-st)/1000:.5f}s')
+ # ethnicity
+ # TODO
+
# ----------------------------------------------------------------------------
# output
@@ -99,21 +102,21 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# draw real age
im_age_real = im_resized.copy()
- draw_utils.draw_bbox(im_age_real, bbox_dim)
+ im_age_real = draw_utils.draw_bbox(im_age_real, bbox_norm)
txt = f'{(age_real):.2f}'
- draw_utils.draw_text(im_age_real, bbox_dim.pt_tl, txt)
+ im_age_real = draw_utils.draw_text(im_age_real, bbox_norm.pt_tl, txt)
# apparent age
im_age_apparent = im_resized.copy()
- draw_utils.draw_bbox(im_age_apparent, bbox_dim)
+ im_age_apparent = draw_utils.draw_bbox(im_age_apparent, bbox_norm)
txt = f'{(age_apparent):.2f}'
- draw_utils.draw_text(im_age_apparent, bbox_dim.pt_tl, txt)
+ im_age_apparent = draw_utils.draw_text(im_age_apparent, bbox_norm.pt_tl, txt)
# gender
im_gender = im_resized.copy()
- draw_utils.draw_bbox(im_age_apparent, bbox_dim)
+ im_gender = draw_utils.draw_bbox(im_gender, bbox_norm)
txt = f"M: {gender['m']:.2f}, F: {gender['f']:.2f}"
- draw_utils.draw_text(im_gender, (10, dim[1]-20), txt)
+ im_gender = draw_utils.draw_text(im_gender, (.1, .9), txt)
# ----------------------------------------------------------------------------
diff --git a/megapixels/commands/demo/face_beauty.py b/megapixels/commands/demo/face_beauty.py
index d31c5cee..45643c61 100644
--- a/megapixels/commands/demo/face_beauty.py
+++ b/megapixels/commands/demo/face_beauty.py
@@ -66,10 +66,10 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
else:
@@ -78,7 +78,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# ----------------------------------------------------------------------------
# beauty
- beauty_score = beauty_predictor.beauty(im_resized, bbox_dim)
+ beauty_score = beauty_predictor.beauty(im_resized, bbox_norm)
# ----------------------------------------------------------------------------
@@ -93,9 +93,9 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# draw 2d landmarks
im_beauty = im_resized.copy()
- draw_utils.draw_bbox(im_beauty, bbox_dim)
+ im_beauty = draw_utils.draw_bbox(im_beauty, bbox_dim)
txt = f'Beauty score: {(100*beauty_score):.2f}'
- draw_utils.draw_text(im_beauty, bbox_dim.pt_tl, txt)
+ im_beauty = draw_utils.draw_text(im_beauty, bbox_dim.pt_tl, txt)
# ----------------------------------------------------------------------------
diff --git a/megapixels/commands/demo/face_detection.py b/megapixels/commands/demo/face_detect.py
index 488cc80d..b92db7cb 100644
--- a/megapixels/commands/demo/face_detection.py
+++ b/megapixels/commands/demo/face_detect.py
@@ -59,68 +59,27 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN()
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
- dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ if not bboxes:
log.error('no face detected')
return
-
-
- # ----------------------------------------------------------------------------
- # generate 68 point landmarks using dlib
-
- from app.processors import face_landmarks
- landmark_detector_2d_68 = face_landmarks.Dlib2D_68()
- points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_dim)
-
-
- # ----------------------------------------------------------------------------
- # generate pose from 68 point 2D landmarks
-
- from app.processors import face_pose
- pose_detector = face_pose.FacePoseDLIB()
- pose_data = pose_detector.pose(points_2d_68, dim)
-
- # ----------------------------------------------------------------------------
- # output
-
- log.info(f'Face coords: {bbox_dim} face')
- log.info(f'pitch: {pose_data["pitch"]}, roll: {pose_data["roll"]}, yaw: {pose_data["yaw"]}')
+ bbox_norm = bboxes[0]
+ dim = im_resized.shape[:2][::-1]
+ bbox_dim = bbox_norm.to_dim(dim)
# ----------------------------------------------------------------------------
# draw
- # draw 2d landmarks
- im_landmarks_2d_68 = im_resized.copy()
- draw_utils.draw_landmarks2D(im_landmarks_2d_68, points_2d_68)
- draw_utils.draw_bbox(im_landmarks_2d_68, bbox_dim)
-
- # draw pose
- im_pose = im_resized.copy()
- draw_utils.draw_pose(im_pose, pose_data['point_nose'], pose_data['points'])
- draw_utils.draw_degrees(im_pose, pose_data)
-
-
- # ----------------------------------------------------------------------------
- # save
-
- if opt_fp_out:
- # save pose only
- cv.imwrite(opt_fp_out, im_pose)
-
+ im_face = im_resized.copy()
+ im_face = draw_utils.draw_bbox(im_face, bbox_norm)
# ----------------------------------------------------------------------------
# display
if opt_display:
-
# show all images here
- cv.imshow('Original', im_resized)
- cv.imshow('2D 68PT Landmarks', im_landmarks_2d_68)
- cv.imshow('Pose', im_pose)
+ cv.imshow('Face', im_face)
display_utils.handle_keyboard() \ No newline at end of file
diff --git a/megapixels/commands/demo/face_landmarks_2d.py b/megapixels/commands/demo/face_landmarks_2d.py
index 22e09297..145a12a6 100644
--- a/megapixels/commands/demo/face_landmarks_2d.py
+++ b/megapixels/commands/demo/face_landmarks_2d.py
@@ -3,7 +3,6 @@ Crop images to prepare for training
"""
import click
-# from PIL import Image, ImageOps, ImageFilter, ImageDraw
from app.settings import types
from app.utils import click_utils
@@ -13,26 +12,14 @@ from app.settings import app_cfg as cfg
@click.command()
@click.option('-i', '--input', 'opt_fp_in', default=None, required=True,
help='Image filepath')
-@click.option('-o', '--output', 'opt_fp_out', default=None,
- help='GIF output path')
@click.option('--size', 'opt_size',
type=(int, int), default=(300, 300),
help='Output image size')
-@click.option('--gif-size', 'opt_gif_size',
- type=(int, int), default=(480, 480),
- help='GIF output size')
-@click.option('--gif-frames', 'opt_gif_frames', default=15,
- help='GIF frames')
-@click.option('-g', '--gpu', 'opt_gpu', default=0,
- help='GPU index')
-@click.option('-f', '--force', 'opt_force', is_flag=True,
- help='Force overwrite file')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
@click.pass_context
-def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
- opt_size, opt_gif_size, opt_force, opt_display):
- """Generates 3D landmark animations from CSV files"""
+def cli(ctx, opt_fp_in, opt_size, opt_display):
+ """2D 68-point landmarks"""
import sys
import os
@@ -52,12 +39,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
from app.utils import plot_utils
from app.processors import face_detector, face_landmarks
from app.models.data_store import DataStore
-
- # TOOD add selective testing
- opt_run_pose = True
- opt_run_2d_68 = True
- opt_run_3d_68 = True
- opt_run_3d_68 = True
# -------------------------------------------------
@@ -66,7 +47,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
log = logger_utils.Logger.getLogger()
- # load image
im = cv.imread(opt_fp_in)
im_resized = im_utils.resize(im, width=opt_size[0], height=opt_size[1])
@@ -74,146 +54,41 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN()
log.info('detecting face...')
st = time.time()
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
else:
log.info(f'Detected face in {(time.time() - st):.2f}s')
- log.info('')
-
-
- # ----------------------------------------------------------------------------
- # detect 3D landmarks
-
- log.info('loading 3D landmark generator files...')
- landmark_detector_3d_68 = face_landmarks.FaceAlignment3D_68(gpu=opt_gpu) # -1 for CPU
- log.info('generating 3D landmarks...')
- st = time.time()
- points_3d_68 = landmark_detector_3d_68.landmarks(im_resized, bbox_dim.to_xyxy())
- log.info(f'generated 3D landmarks in {(time.time() - st):.2f}s')
- log.info('')
-
-
- # ----------------------------------------------------------------------------
- # generate 3D GIF animation
- log.info('generating 3D animation...')
- if not opt_fp_out:
- fpp_im = Path(opt_fp_in)
- fp_out = join(fpp_im.parent, f'{fpp_im.stem}_anim.gif')
- else:
- fp_out = opt_fp_out
- st = time.time()
- plot_utils.generate_3d_landmark_anim(np.array(points_3d_68), fp_out,
- size=opt_gif_size, num_frames=opt_gif_frames)
- log.info(f'Generated animation in {(time.time() - st):.2f}s')
- log.info(f'Saved to: {fp_out}')
- log.info('')
-
-
- # ----------------------------------------------------------------------------
- # generate face vectors, only to test if feature extraction works
-
- log.info('initialize face recognition model...')
- from app.processors import face_recognition
- face_rec = face_recognition.RecognitionDLIB()
- st = time.time()
- log.info('generating face vector...')
- vec = face_rec.vec(im_resized, bbox_dim)
- log.info(f'generated face vector in {(time.time() - st):.2f}s')
- log.info('')
-
# ----------------------------------------------------------------------------
# generate 68 point landmarks using dlib
log.info('initializing face landmarks 68 dlib...')
- from app.processors import face_landmarks
landmark_detector_2d_68 = face_landmarks.Dlib2D_68()
log.info('generating 2D 68PT landmarks...')
st = time.time()
- points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_dim)
+ points_norm = landmark_detector_2d_68.landmarks(im_resized, bbox_norm)
log.info(f'generated 2D 68PT face landmarks in {(time.time() - st):.2f}s')
- log.info('')
# ----------------------------------------------------------------------------
- # generate pose from 68 point 2D landmarks
-
- if opt_run_pose:
- log.info('initialize pose...')
- from app.processors import face_pose
- pose_detector = face_pose.FacePoseDLIB()
- log.info('generating pose...')
- st = time.time()
- pose_data = pose_detector.pose(points_2d_68, dim)
- log.info(f'generated pose {(time.time() - st):.2f}s')
- log.info('')
-
-
- # x
-
-
-
# display
+
if opt_display:
-
- # draw bbox
-
- # draw 3d landmarks
- im_landmarks_3d_68 = im_resized.copy()
- draw_utils.draw_landmarks3D(im_landmarks_3d_68, points_3d_68)
- draw_utils.draw_bbox(im_landmarks_3d_68, bbox_dim)
# draw 2d landmarks
- im_landmarks_2d_68 = im_resized.copy()
- draw_utils.draw_landmarks2D(im_landmarks_2d_68, points_2d_68)
- draw_utils.draw_bbox(im_landmarks_2d_68, bbox_dim)
-
- # draw pose
- if opt_run_pose:
- im_pose = im_resized.copy()
- draw_utils.draw_pose(im_pose, pose_data['point_nose'], pose_data['points'])
- draw_utils.draw_degrees(im_pose, pose_data)
-
- # draw animated GIF
- im = Image.open(opt_fp_out)
- im_frames = []
- duration = im.info['duration']
- try:
- while True:
- im.seek(len(im_frames))
- mypalette = im.getpalette()
- im.putpalette(mypalette)
- im_jpg = Image.new("RGB", im.size)
- im_jpg.paste(im)
- im_np = im_utils.pil2np(im_jpg.copy())
- im_frames.append(im_np)
- except EOFError:
- pass # end of GIF sequence
-
- n_frames = len(im_frames)
- frame_number = 0
+ im_lmarks = im_resized.copy()
+ im_lmarks = draw_utils.draw_bbox(im_lmarks, bbox_norm)
+ im_lmarks = draw_utils.draw_landmarks2D(im_lmarks, points_norm)
- while True:
- # show all images here
- cv.imshow('Original', im_resized)
- cv.imshow('2D 68PT Landmarks', im_landmarks_2d_68)
- cv.imshow('3D 68PT Landmarks', im_landmarks_3d_68)
- cv.imshow('Pose', im_pose)
- cv.imshow('3D 68pt GIF', im_frames[frame_number])
- frame_number = (frame_number + 1) % n_frames
- k = cv.waitKey(duration) & 0xFF
- if k == 27 or k == ord('q'): # ESC
- cv.destroyAllWindows()
- sys.exit()
- elif k != 255:
- # any key to continue
- break \ No newline at end of file
+ # show all images here
+ cv.imshow('2D 68PT Landmarks', im_lmarks)
+ display_utils.handle_keyboard() \ No newline at end of file
diff --git a/megapixels/commands/demo/face_landmarks_3d.py b/megapixels/commands/demo/face_landmarks_3d.py
index 22e09297..ed5a00d5 100644
--- a/megapixels/commands/demo/face_landmarks_3d.py
+++ b/megapixels/commands/demo/face_landmarks_3d.py
@@ -3,7 +3,6 @@ Crop images to prepare for training
"""
import click
-# from PIL import Image, ImageOps, ImageFilter, ImageDraw
from app.settings import types
from app.utils import click_utils
@@ -27,7 +26,7 @@ from app.settings import app_cfg as cfg
help='GPU index')
@click.option('-f', '--force', 'opt_force', is_flag=True,
help='Force overwrite file')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
@click.pass_context
def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
@@ -52,12 +51,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
from app.utils import plot_utils
from app.processors import face_detector, face_landmarks
from app.models.data_store import DataStore
-
- # TOOD add selective testing
- opt_run_pose = True
- opt_run_2d_68 = True
- opt_run_3d_68 = True
- opt_run_3d_68 = True
# -------------------------------------------------
@@ -74,14 +67,14 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN()
log.info('detecting face...')
st = time.time()
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
else:
@@ -96,7 +89,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
landmark_detector_3d_68 = face_landmarks.FaceAlignment3D_68(gpu=opt_gpu) # -1 for CPU
log.info('generating 3D landmarks...')
st = time.time()
- points_3d_68 = landmark_detector_3d_68.landmarks(im_resized, bbox_dim.to_xyxy())
+ points_3d_68 = landmark_detector_3d_68.landmarks(im_resized, bbox_norm)
log.info(f'generated 3D landmarks in {(time.time() - st):.2f}s')
log.info('')
@@ -119,19 +112,6 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
# ----------------------------------------------------------------------------
- # generate face vectors, only to test if feature extraction works
-
- log.info('initialize face recognition model...')
- from app.processors import face_recognition
- face_rec = face_recognition.RecognitionDLIB()
- st = time.time()
- log.info('generating face vector...')
- vec = face_rec.vec(im_resized, bbox_dim)
- log.info(f'generated face vector in {(time.time() - st):.2f}s')
- log.info('')
-
-
- # ----------------------------------------------------------------------------
# generate 68 point landmarks using dlib
log.info('initializing face landmarks 68 dlib...')
@@ -139,54 +119,25 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
landmark_detector_2d_68 = face_landmarks.Dlib2D_68()
log.info('generating 2D 68PT landmarks...')
st = time.time()
- points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_dim)
+ points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_norm)
log.info(f'generated 2D 68PT face landmarks in {(time.time() - st):.2f}s')
log.info('')
- # ----------------------------------------------------------------------------
- # generate pose from 68 point 2D landmarks
-
- if opt_run_pose:
- log.info('initialize pose...')
- from app.processors import face_pose
- pose_detector = face_pose.FacePoseDLIB()
- log.info('generating pose...')
- st = time.time()
- pose_data = pose_detector.pose(points_2d_68, dim)
- log.info(f'generated pose {(time.time() - st):.2f}s')
- log.info('')
-
-
- # x
-
-
-
# display
if opt_display:
- # draw bbox
-
- # draw 3d landmarks
- im_landmarks_3d_68 = im_resized.copy()
- draw_utils.draw_landmarks3D(im_landmarks_3d_68, points_3d_68)
- draw_utils.draw_bbox(im_landmarks_3d_68, bbox_dim)
-
- # draw 2d landmarks
- im_landmarks_2d_68 = im_resized.copy()
- draw_utils.draw_landmarks2D(im_landmarks_2d_68, points_2d_68)
- draw_utils.draw_bbox(im_landmarks_2d_68, bbox_dim)
-
- # draw pose
- if opt_run_pose:
- im_pose = im_resized.copy()
- draw_utils.draw_pose(im_pose, pose_data['point_nose'], pose_data['points'])
- draw_utils.draw_degrees(im_pose, pose_data)
+ # draw landmarks
+ im_lmarks = im_resized.copy()
+ im_lmarks = draw_utils.draw_bbox(im_lmarks, bbox_norm)
+ im_lmarks = draw_utils.draw_landmarks2D(im_lmarks, points_2d_68, radius=1, color=(0,0,255))
+ im_lmarks = draw_utils.draw_landmarks3D(im_lmarks, points_3d_68, radius=3, color=(0,255,0))
# draw animated GIF
- im = Image.open(opt_fp_out)
+ im = Image.open(fp_out)
im_frames = []
duration = im.info['duration']
+
try:
while True:
im.seek(len(im_frames))
@@ -204,10 +155,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_gif_frames,
while True:
# show all images here
- cv.imshow('Original', im_resized)
- cv.imshow('2D 68PT Landmarks', im_landmarks_2d_68)
- cv.imshow('3D 68PT Landmarks', im_landmarks_3d_68)
- cv.imshow('Pose', im_pose)
+ cv.imshow('2D/3D 68PT Landmarks', im_lmarks)
cv.imshow('3D 68pt GIF', im_frames[frame_number])
frame_number = (frame_number + 1) % n_frames
k = cv.waitKey(duration) & 0xFF
diff --git a/megapixels/commands/demo/face_pose.py b/megapixels/commands/demo/face_pose.py
index 3918adac..48214e0d 100644
--- a/megapixels/commands/demo/face_pose.py
+++ b/megapixels/commands/demo/face_pose.py
@@ -22,7 +22,7 @@ from app.settings import app_cfg as cfg
help='GPU index')
@click.option('-f', '--force', 'opt_force', is_flag=True,
help='Force overwrite file')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
@click.pass_context
def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
@@ -61,12 +61,12 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN()
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
@@ -76,7 +76,7 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
from app.processors import face_landmarks
landmark_detector_2d_68 = face_landmarks.Dlib2D_68()
- points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_dim)
+ points_2d_68 = landmark_detector_2d_68.landmarks(im_resized, bbox_norm)
# ----------------------------------------------------------------------------
@@ -97,14 +97,14 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
# draw
# draw 2d landmarks
- im_landmarks_2d_68 = im_resized.copy()
- draw_utils.draw_landmarks2D(im_landmarks_2d_68, points_2d_68)
- draw_utils.draw_bbox(im_landmarks_2d_68, bbox_dim)
+ im_landmarks = im_resized.copy()
+ im_landmarks = draw_utils.draw_landmarks2D(im_landmarks, points_2d_68)
+ im_landmarks = draw_utils.draw_bbox(im_landmarks, bbox_norm)
# draw pose
im_pose = im_resized.copy()
- draw_utils.draw_pose(im_pose, pose_data['point_nose'], pose_data['points'])
- draw_utils.draw_degrees(im_pose, pose_data)
+ im_pose = draw_utils.draw_pose(im_pose, pose_data['point_nose'], pose_data['points'])
+ im_pose = draw_utils.draw_degrees(im_pose, pose_data)
# ----------------------------------------------------------------------------
@@ -120,9 +120,8 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_gpu, opt_size, opt_force, opt_display):
if opt_display:
-
# show all images here
cv.imshow('Original', im_resized)
- cv.imshow('2D 68PT Landmarks', im_landmarks_2d_68)
+ cv.imshow('2D 68PT Landmarks', im_landmarks)
cv.imshow('Pose', im_pose)
display_utils.handle_keyboard() \ No newline at end of file
diff --git a/megapixels/commands/demo/face_search.py b/megapixels/commands/demo/face_search.py
index ca0b8016..d50f5c73 100644
--- a/megapixels/commands/demo/face_search.py
+++ b/megapixels/commands/demo/face_search.py
@@ -13,7 +13,7 @@ log = Logger.getLogger()
help='File to lookup')
@click.option('--data_store', 'opt_data_store',
type=cfg.DataStoreVar,
- default=click_utils.get_default(types.DataStore.SSD),
+ default=click_utils.get_default(types.DataStore.HDD),
show_default=True,
help=click_utils.show_help(types.DataStore))
@click.option('--dataset', 'opt_dataset',
@@ -40,44 +40,47 @@ def cli(ctx, opt_fp_in, opt_data_store, opt_dataset, opt_results, opt_gpu):
from tqdm import tqdm
import imutils
- from app.utils import file_utils, im_utils
+ from app.utils import file_utils, im_utils, display_utils, draw_utils
from app.models.data_store import DataStore
from app.processors import face_detector
- from app.processors import face_recognition
+ from app.processors import face_extractor
log = Logger.getLogger()
+
# init dataset
dataset = Dataset(opt_data_store, opt_dataset)
dataset.load_face_vectors()
dataset.load_records()
- dataset.load_identities()
+ # dataset.load_identities()
# init face detection
- detector = face_detector.DetectorDLIBHOG()
+ detector = face_detector.DetectorCVDNN()
- # init face recognition
- recognition = face_recognition.RecognitionDLIB(gpu=opt_gpu)
+ # init face extractor
+ extractor = face_extractor.ExtractorVGG()
# load query image
im_query = cv.imread(opt_fp_in)
# get detection as BBox object
bboxes = detector.detect(im_query, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_query.shape[:2][::-1]
- bbox = bbox.to_dim(dim) # convert back to real dimensions
+ bbox_dim = bbox_norm.to_dim(dim) # convert back to real dimensions
- if not bbox:
+ if not bbox_norm:
log.error('No face detected. Exiting')
return
# extract the face vectors
- vec_query = recognition.vec(im_query, bbox)
+ vec_query = extractor.extract(im_query, bbox_norm)
+ log.debug(f'len query: {len(vec_query)}')
# find matches
image_records = dataset.find_matches(vec_query, n_results=opt_results)
# summary
+ im_query = draw_utils.draw_bbox(im_query, bbox_norm, stroke_weight=8)
ims_match = [im_query]
for image_record in image_records:
image_record.summarize()
@@ -85,16 +88,11 @@ def cli(ctx, opt_fp_in, opt_data_store, opt_dataset, opt_results, opt_gpu):
im_match = cv.imread(image_record.filepath)
ims_match.append(im_match)
+ # make montages of most similar faces
montages = imutils.build_montages(ims_match, (256, 256), (3,2))
+ # display
for i, montage in enumerate(montages):
- cv.imshow(f'{i}', montage)
- # cv gui
- while True:
- k = cv.waitKey(1) & 0xFF
- if k == 27 or k == ord('q'): # ESC
- cv.destroyAllWindows()
- sys.exit()
- elif k != 255:
- # any key to continue
- break
+ cv.imshow(f'{opt_dataset.name.upper()}: page {i}', montage)
+
+ display_utils.handle_keyboard()
diff --git a/megapixels/commands/demo/face_vector.py b/megapixels/commands/demo/face_vector.py
index 3ff68001..c7b5ef2e 100644
--- a/megapixels/commands/demo/face_vector.py
+++ b/megapixels/commands/demo/face_vector.py
@@ -1,9 +1,8 @@
"""
-Crop images to prepare for training
+Tests if the feature vector generator works
"""
import click
-# from PIL import Image, ImageOps, ImageFilter, ImageDraw
from app.settings import types
from app.utils import click_utils
@@ -14,11 +13,11 @@ from app.settings import app_cfg as cfg
@click.option('-i', '--input', 'opt_fp_in', default=None, required=True,
help='Image filepath')
@click.option('--size', 'opt_size',
- type=(int, int), default=(300, 300),
+ type=(int, int), default=cfg.DEFAULT_SIZE_FACE_DETECT,
help='Output image size')
@click.option('-g', '--gpu', 'opt_gpu', default=0,
help='GPU index')
-@click.option('--display/--no-display', 'opt_display', is_flag=True, default=False,
+@click.option('--display/--no-display', 'opt_display', is_flag=True, default=True,
help='Display detections to debug')
@click.pass_context
def cli(ctx, opt_fp_in, opt_gpu, opt_size, opt_display):
@@ -54,12 +53,12 @@ def cli(ctx, opt_fp_in, opt_gpu, opt_size, opt_display):
# ----------------------------------------------------------------------------
# detect face
- face_detector = face_detector.DetectorDLIBCNN(gpu=opt_gpu) # -1 for CPU
+ face_detector = face_detector.DetectorCVDNN() # -1 for CPU
bboxes = face_detector.detect(im_resized, largest=True)
- bbox = bboxes[0]
+ bbox_norm = bboxes[0]
dim = im_resized.shape[:2][::-1]
- bbox_dim = bbox.to_dim(dim)
- if not bbox:
+ bbox_dim = bbox_norm.to_dim(dim)
+ if not bbox_norm:
log.error('no face detected')
return
@@ -67,14 +66,13 @@ def cli(ctx, opt_fp_in, opt_gpu, opt_size, opt_display):
# ----------------------------------------------------------------------------
# generate face vectors, only to test if feature extraction works
- from app.processors import face_recognition
- facerec = face_recognition.RecognitionDLIB()
- vec = facerec.vec(im_resized, bbox_dim)
- vec_flat = facerec.flatten(vec)
- log.info(f'generated vector. showing vec[0:10]:')
- log.info(f'\n{vec_flat}')
+ from app.processors import face_extractor
+ extractor = face_extractor.ExtractorVGG()
+ vec = extractor.extract(im_resized, bbox_norm)
+ vec_str = extractor.to_str(vec)
+ log.info(f'\n{vec_str}')
if opt_display:
- draw_utils.draw_bbox(im_resized, bbox_dim)
+ im_resized = draw_utils.draw_bbox(im_resized, bbox_dim)
cv.imshow('Original', im_resized)
display_utils.handle_keyboard() \ No newline at end of file