summaryrefslogtreecommitdiff
path: root/megapixels/commands/demo/face_3ddfa.py
diff options
context:
space:
mode:
Diffstat (limited to 'megapixels/commands/demo/face_3ddfa.py')
-rw-r--r--megapixels/commands/demo/face_3ddfa.py85
1 files changed, 43 insertions, 42 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()