def main(args): cfg = yaml.load(open(args.config), Loader=yaml.SafeLoader) gpu_mode = args.mode == 'gpu' tddfa = TDDFA(gpu_mode=gpu_mode, **cfg) # Initialize FaceBoxes face_boxes = FaceBoxes() # Given a camera # before run this line, make sure you have installed `imageio-ffmpeg` reader = imageio.get_reader("<video0>") # the simple implementation of average smoothing by looking ahead by n_next frames # assert the frames of the video >= n n_pre, n_next = args.n_pre, args.n_next n = n_pre + n_next + 1 queue_ver = deque() queue_frame = deque() # run dense_flag = args.opt in ('2d_dense', '3d') pre_ver = None for i, frame in tqdm(enumerate(reader)): frame_bgr = frame[..., ::-1] # RGB->BGR if i == 0: # the first frame, detect face, here we only use the first face, you can change depending on your need boxes = face_boxes(frame_bgr) boxes = [boxes[0]] param_lst, roi_box_lst = tddfa(frame_bgr, boxes) ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] # refine param_lst, roi_box_lst = tddfa(frame_bgr, [ver], crop_policy='landmark') ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] # padding queue for _ in range(n_pre): queue_ver.append(ver.copy()) queue_ver.append(ver.copy()) for _ in range(n_pre): queue_frame.append(frame_bgr.copy()) queue_frame.append(frame_bgr.copy()) else: param_lst, roi_box_lst = tddfa(frame_bgr, [pre_ver], crop_policy='landmark') roi_box = roi_box_lst[0] # todo: add confidence threshold to judge the tracking is failed if abs(roi_box[2] - roi_box[0]) * abs(roi_box[3] - roi_box[1]) < 2020: boxes = face_boxes(frame_bgr) boxes = [boxes[0]] param_lst, roi_box_lst = tddfa(frame_bgr, boxes) ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] queue_ver.append(ver.copy()) queue_frame.append(frame_bgr.copy()) pre_ver = ver # for tracking # smoothing: enqueue and dequeue ops if len(queue_ver) >= n: ver_ave = np.mean(queue_ver, axis=0) if args.opt == '2d_sparse': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave) # since we use padding elif args.opt == '2d_dense': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave, size=1) elif args.opt == '3d': img_draw = render(queue_frame[n_pre], [ver_ave], alpha=0.7) else: raise ValueError(f'Unknown opt {args.opt}') cv2.imshow('image', img_draw) k = cv2.waitKey(20) if (k & 0xff == ord('q')): break queue_ver.popleft() queue_frame.popleft()
def main(args): cfg = yaml.load(open(args.config), Loader=yaml.SafeLoader) gpu_mode = args.mode == 'gpu' tddfa = TDDFA(gpu_mode=gpu_mode, **cfg) # Initialize FaceBoxes face_boxes = FaceBoxes() # Given a video path fn = args.video_fp.split('/')[-1] reader = imageio.get_reader(args.video_fp) fps = reader.get_meta_data()['fps'] suffix = get_suffix(args.video_fp) video_wfp = f'examples/results/videos/{fn.replace(suffix, "")}_{args.opt}_smooth.mp4' writer = imageio.get_writer(video_wfp, fps=fps) # the simple implementation of average smoothing by looking ahead by n_next frames # assert the frames of the video >= n n_pre, n_next = args.n_pre, args.n_next n = n_pre + n_next + 1 queue_ver = deque() queue_frame = deque() # run dense_flag = args.opt in ( '2d_dense', '3d', ) pre_ver = None for i, frame in tqdm(enumerate(reader)): if args.start > 0 and i < args.start: continue if args.end > 0 and i > args.end: break frame_bgr = frame[..., ::-1] # RGB->BGR if i == 0: # detect boxes = face_boxes(frame_bgr) boxes = [boxes[0]] param_lst, roi_box_lst = tddfa(frame_bgr, boxes) ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] # refine param_lst, roi_box_lst = tddfa(frame_bgr, [ver], crop_policy='landmark') ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] # padding queue for j in range(n_pre): queue_ver.append(ver.copy()) queue_ver.append(ver.copy()) for j in range(n_pre): queue_frame.append(frame_bgr.copy()) queue_frame.append(frame_bgr.copy()) else: param_lst, roi_box_lst = tddfa(frame_bgr, [pre_ver], crop_policy='landmark') roi_box = roi_box_lst[0] # todo: add confidence threshold to judge the tracking is failed if abs(roi_box[2] - roi_box[0]) * abs(roi_box[3] - roi_box[1]) < 2020: boxes = face_boxes(frame_bgr) boxes = [boxes[0]] param_lst, roi_box_lst = tddfa(frame_bgr, boxes) ver = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag)[0] queue_ver.append(ver.copy()) queue_frame.append(frame_bgr.copy()) pre_ver = ver # for tracking # smoothing: enqueue and dequeue ops if len(queue_ver) >= n: ver_ave = np.mean(queue_ver, axis=0) if args.opt == '2d_sparse': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave) # since we use padding elif args.opt == '2d_dense': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave, size=1) elif args.opt == '3d': img_draw = render(queue_frame[n_pre], [ver_ave], alpha=0.7) writer.append_data(img_draw[:, :, ::-1]) # BGR->RGB queue_ver.popleft() queue_frame.popleft() # we will lost the last n_next frames, still padding for j in range(n_next): queue_ver.append(ver.copy()) queue_frame.append(frame_bgr.copy()) # the last frame ver_ave = np.mean(queue_ver, axis=0) if args.opt == '2d_sparse': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave) # since we use padding elif args.opt == '2d_dense': img_draw = cv_draw_landmark(queue_frame[n_pre], ver_ave, size=1) elif args.opt == '3d': img_draw = render(queue_frame[n_pre], [ver_ave], alpha=0.7) writer.append_data(img_draw[..., ::-1]) # BGR->RGB queue_ver.popleft() queue_frame.popleft() writer.close() print(f'Dump to {video_wfp}')
def main(args): cfg = yaml.load(open(args.config), Loader=yaml.SafeLoader) # Init FaceBoxes and TDDFA, recommend using onnx flag if args.onnx: import os os.environ['KMP_DUPLICATE_LIB_OK'] = 'True' os.environ['OMP_NUM_THREADS'] = '4' from FaceBoxes.FaceBoxes_ONNX import FaceBoxes_ONNX from TDDFA_ONNX import TDDFA_ONNX face_boxes = FaceBoxes_ONNX() tddfa = TDDFA_ONNX(**cfg) else: gpu_mode = args.mode == 'gpu' tddfa = TDDFA(gpu_mode=gpu_mode, **cfg) face_boxes = FaceBoxes() # Given a still image path and load to BGR channel img = cv2.imread(args.img_fp) # Detect faces, get 3DMM params and roi boxes boxes = face_boxes(img) n = len(boxes) if n == 0: print(f'No face detected, exit') sys.exit(-1) print(f'Detect {n} faces') param_lst, roi_box_lst = tddfa(img, boxes) # Visualization and serialization dense_flag = args.opt in ('2d_dense', '3d', 'depth', 'pncc', 'uv_tex', 'ply', 'obj') old_suffix = get_suffix(args.img_fp) new_suffix = f'.{args.opt}' if args.opt in ('ply', 'obj') else '.jpg' wfp = f'examples/results/{args.img_fp.split("/")[-1].replace(old_suffix, "")}_{args.opt}' + new_suffix ver_lst = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag) if args.opt == '2d_sparse': draw_landmarks(img, ver_lst, show_flag=args.show_flag, dense_flag=dense_flag, wfp=wfp) elif args.opt == '2d_dense': draw_landmarks(img, ver_lst, show_flag=args.show_flag, dense_flag=dense_flag, wfp=wfp) elif args.opt == '3d': render(img, ver_lst, tddfa.tri, alpha=0.6, show_flag=args.show_flag, wfp=wfp) elif args.opt == 'depth': # if `with_bf_flag` is False, the background is black depth(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp, with_bg_flag=True) elif args.opt == 'pncc': pncc(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp, with_bg_flag=True) elif args.opt == 'uv_tex': uv_tex(img, ver_lst, tddfa.tri, show_flag=args.show_flag, wfp=wfp) elif args.opt == 'pose': viz_pose(img, param_lst, ver_lst, show_flag=args.show_flag, wfp=wfp) elif args.opt == 'ply': ser_to_ply(ver_lst, tddfa.tri, height=img.shape[0], wfp=wfp) elif args.opt == 'obj': ser_to_obj(img, ver_lst, tddfa.tri, height=img.shape[0], wfp=wfp) else: raise ValueError(f'Unknown opt {args.opt}')
def main(args): # input and output folder image_path = "G:\\BU-3DFE\\Extracted" save_path = "G:\\bu3dfe_3ddfa_proc" if not os.path.exists(save_path): os.makedirs(save_path) cfg = yaml.load(open(args.config), Loader=yaml.SafeLoader) # Init FaceBoxes and TDDFA, recommend using onnx flag gpu_mode = args.mode == 'gpu' tddfa = TDDFA(gpu_mode=gpu_mode, **cfg) face_boxes = FaceBoxes() img_list = sorted( [str(x) for x in pathlib.Path(image_path).rglob("*_F2D.bmp")]) print("Reconstructing:\n") for file in img_list: out_file = save_path + file[len(image_path):-4] + ".pickle" if os.path.isfile(out_file): continue out_dir = str(pathlib.Path(out_file).parent) if not os.path.isdir(out_dir): os.makedirs(out_dir) # Given a still image path and load to BGR channel img = cv2.imread(file) # Detect faces, get 3DMM params and roi boxes boxes = face_boxes(img) n = len(boxes) if n == 0: print(f'No face detected, skipping \"' + file + '\".') continue #print(f'Detect {n} faces') param_lst, roi_box_lst = tddfa(img, boxes) # Visualization and serialization dense_flag = True ver_lst = tddfa.recon_vers(param_lst, roi_box_lst, dense_flag=dense_flag) # repair all the bs because of the matrices' axis alignment... lm68 = np.reshape( np.reshape(ver_lst[0].T, (-1, 1))[tddfa.bfm.keypoints], (-1, 3)) for i in range(lm68.shape[0]): lm68[i, 1] = img.shape[0] - lm68[i, 1] for i in range(ver_lst[0].shape[1]): ver_lst[0][1, i] = img.shape[0] - ver_lst[0][1, i] vertices = ver_lst[0].T useful_tri = np.copy(tddfa.tri) for i in range(useful_tri.shape[0]): tmp = useful_tri[i, 2] useful_tri[i, 2] = useful_tri[i, 0] useful_tri[i, 0] = tmp #useful_tri = useful_tri + 1 # save mesh = dict() mesh["vertices"] = vertices mesh["faces"] = useful_tri mesh["lm68"] = lm68 with open(out_file, "wb+") as f: _pickle.dump(mesh, f) print(out_file)