diff options
Diffstat (limited to 'megapixels/commands/demo/face_3ddfa.py')
| -rw-r--r-- | megapixels/commands/demo/face_3ddfa.py | 85 |
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() |
