diff options
| author | adamhrv <adam@ahprojects.com> | 2019-01-06 17:16:18 +0100 |
|---|---|---|
| committer | adamhrv <adam@ahprojects.com> | 2019-01-06 17:16:18 +0100 |
| commit | 4bcb82c0f295d79d3d247252e7e98b2d986ae821 (patch) | |
| tree | a51105698c46ecfcb0a09c5ba294f9d9ffa43e7a /megapixels/commands/cv/face_pose.py | |
| parent | 2efde746810a0264ad2cf09dc9b003bfcd17a4d5 (diff) | |
externalize drawing, cleanup
Diffstat (limited to 'megapixels/commands/cv/face_pose.py')
| -rw-r--r-- | megapixels/commands/cv/face_pose.py | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/megapixels/commands/cv/face_pose.py b/megapixels/commands/cv/face_pose.py index 4e35210c..70ea1f30 100644 --- a/megapixels/commands/cv/face_pose.py +++ b/megapixels/commands/cv/face_pose.py @@ -1,4 +1,6 @@ """ +NB: This only works with the DLIB 68-point landmarks. + Converts ROIs to pose: yaw, roll, pitch pitch: looking down or up in yes gesture roll: tilting head towards shoulder @@ -6,6 +8,13 @@ yaw: twisting head left to right in no gesture """ +""" +TODO +- check compatibility with MTCNN 68 point detector +- improve accuracy by using MTCNN 5-point +- refer to https://github.com/jerryhouuu/Face-Yaw-Roll-Pitch-from-Pose-Estimation-using-OpenCV/ +""" + import click from app.settings import types @@ -19,7 +28,7 @@ from app.settings import app_cfg as cfg help='Override enum output filename CSV') @click.option('-m', '--media', 'opt_dir_media', default=None, help='Override enum media directory') -@click.option('--data_store', 'opt_data_store', +@click.option('--store', 'opt_data_store', type=cfg.DataStoreVar, default=click_utils.get_default(types.DataStore.HDD), show_default=True, @@ -56,8 +65,8 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_dir_media, opt_data_store, opt_dataset, import pandas as pd from app.models.bbox import BBox - from app.utils import logger_utils, file_utils, im_utils - from app.processors.face_landmarks_2d import LandmarksDLIB + from app.utils import logger_utils, file_utils, im_utils, display_utils, draw_utils + from app.processors.face_landmarks import Dlib2D_68 from app.processors.face_pose import FacePoseDLIB from app.models.data_store import DataStore @@ -77,9 +86,11 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_dir_media, opt_data_store, opt_dataset, # init face processors face_pose = FacePoseDLIB() - face_landmarks = LandmarksDLIB() + face_landmarks = Dlib2D_68() + + # ------------------------------------------------- + # load data - # load filepath data fp_record = data_store.metadata(types.Metadata.FILE_RECORD) df_record = pd.read_csv(fp_record).set_index('index') # load ROI data @@ -93,59 +104,60 @@ def cli(ctx, opt_fp_in, opt_fp_out, opt_dir_media, opt_data_store, opt_dataset, log.debug('processing {:,} groups'.format(len(df_img_groups))) # store poses and convert to DataFrame - poses = [] + results = [] + # ------------------------------------------------- # iterate groups with file/record index as key for record_index, df_img_group in tqdm(df_img_groups): - # make fp - ds_record = df_record.iloc[record_index] - fp_im = data_store.face(ds_record.subdir, ds_record.fn, ds_record.ext) + + # access the file_record + file_record = df_record.iloc[record_index] # pands.DataSeries + + # load image + fp_im = data_store.face(file_record.subdir, file_record.fn, file_record.ext) im = cv.imread(fp_im) + im_resized = im_utils.resize(im, width=opt_size[0], height=opt_size[1]) + # iterate image group dataframe with roi index as key for roi_index, df_img in df_img_group.iterrows(): + # get bbox x, y, w, h = df_img.x, df_img.y, df_img.w, df_img.h - dim = (ds_record.width, ds_record.height) - #dim = im.shape[:2][::-1] + #dim = (file_record.width, file_record.height) + dim = im_resized.shape[:2][::-1] bbox = BBox.from_xywh(x, y, w, h).to_dim(dim) + # get pose - landmarks = face_landmarks.landmarks(im, bbox) + landmarks = face_landmarks.landmarks(im_resized, bbox) pose_data = face_pose.pose(landmarks, dim) #pose_degrees = pose_data['degrees'] # only keep the degrees data #pose_degrees['points_nose'] = pose_data - # use the project point data if display flag set + + # draw landmarks if optioned if opt_display: - dst = im.copy() - face_pose.draw_pose(dst, pose_data['point_nose'], pose_data['points']) - face_pose.draw_degrees(dst, pose_data) - # display to cv window - cv.imshow('', dst) - 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 + draw_utils.draw_pose(im_resized, pose_data['point_nose'], pose_data['points']) + draw_utils.draw_degrees(im_resized, pose_data) + cv.imshow('', im_resized) + display_utils.handle_keyboard() # add image index and append to result CSV data pose_data['roi_index'] = roi_index for k, v in pose_data['points'].items(): pose_data[f'point_{k}_x'] = v[0][0] / dim[0] pose_data[f'point_{k}_y'] = v[0][1] / dim[1] + + # rearrange data structure for DataFrame pose_data.pop('points') pose_data['point_nose_x'] = pose_data['point_nose'][0] / dim[0] pose_data['point_nose_y'] = pose_data['point_nose'][1] / dim[1] pose_data.pop('point_nose') - poses.append(pose_data) + results.append(pose_data) - # create dataframe + # create DataFrame and save to CSV file_utils.mkdirs(fp_out) - df = pd.DataFrame.from_dict(poses) - # save date + df = pd.DataFrame.from_dict(results) df.index.name = 'index' df.to_csv(fp_out) + # save script - cmd_line = ' '.join(sys.argv) - file_utils.write_text(cmd_line, '{}.sh'.format(fp_out))
\ No newline at end of file + file_utils.write_text(' '.join(sys.argv), '{}.sh'.format(fp_out))
\ No newline at end of file |
