summaryrefslogtreecommitdiff
path: root/megapixels/commands/cv/face_landmark.py
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2019-01-05 12:35:01 +0100
committerJules Laplace <julescarbon@gmail.com>2019-01-05 12:35:01 +0100
commit374dc54d049766fce225ca84d31fdf51f40f292c (patch)
tree915b4bf3ea6645a1a65c30c4aee51870d6f955e3 /megapixels/commands/cv/face_landmark.py
parent824c958a7f29ab1fe31d09035c04a150379aecea (diff)
parentbff4e1c50349b0ba7d8e5fab6ce697c0b856f13f (diff)
Merge branch 'master' of github.com:adamhrv/megapixels_dev
Diffstat (limited to 'megapixels/commands/cv/face_landmark.py')
-rw-r--r--megapixels/commands/cv/face_landmark.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/megapixels/commands/cv/face_landmark.py b/megapixels/commands/cv/face_landmark.py
new file mode 100644
index 00000000..03ef8fc2
--- /dev/null
+++ b/megapixels/commands/cv/face_landmark.py
@@ -0,0 +1,96 @@
+"""
+
+"""
+
+import click
+
+from app.settings import types
+from app.utils import click_utils
+from app.settings import app_cfg as cfg
+
+color_filters = {'color': 1, 'gray': 2, 'all': 3}
+
+@click.command()
+@click.option('-i', '--input', 'opt_dirs_in', required=True, multiple=True,
+ help='Input directory')
+@click.option('-o', '--output', 'opt_fp_out', required=True,
+ help='Output CSV')
+@click.option('-e', '--ext', 'opt_ext',
+ default='jpg', type=click.Choice(['jpg', 'png']),
+ help='File glob ext')
+@click.option('--size', 'opt_size',
+ type=(int, int), default=(300, 300),
+ help='Output image size')
+@click.option('-g', '--gpu', 'opt_gpu', default=0,
+ help='GPU index')
+@click.option('--slice', 'opt_slice', type=(int, int), default=(None, None),
+ help='Slice list of files')
+@click.option('--recursive/--no-recursive', 'opt_recursive', is_flag=True, default=False,
+ help='Use glob recursion (slower)')
+@click.option('-f', '--force', 'opt_force', is_flag=True,
+ help='Force overwrite file')
+@click.pass_context
+def cli(ctx, opt_dirs_in, opt_fp_out, opt_ext, opt_size, opt_gpu, opt_slice,
+ opt_recursive, opt_force):
+ """Converts face imges to 3D landmarks"""
+
+ import sys
+ import os
+ from os.path import join
+ from pathlib import Path
+ from glob import glob
+
+ from tqdm import tqdm
+ import numpy as np
+ import dlib # must keep a local reference for dlib
+ import cv2 as cv
+ import pandas as pd
+ from face_alignment import FaceAlignment, LandmarksType
+ from skimage import io
+
+ from app.utils import logger_utils, file_utils
+ from app.processors import face_detector
+
+ # -------------------------------------------------
+ # init here
+
+
+ log = logger_utils.Logger.getLogger()
+
+ if not opt_force and Path(opt_fp_out).exists():
+ log.error('File exists. Use "-f / --force" to overwite')
+ return
+
+ device = 'cuda' if opt_gpu > -1 else 'cpu'
+ fa = FaceAlignment(LandmarksType._3D, flip_input=False, device=device)
+
+ # get list of files to process
+ fp_ims = []
+ for opt_dir_in in opt_dirs_in:
+ if opt_recursive:
+ fp_glob = join(opt_dir_in, '**/*.{}'.format(opt_ext))
+ fp_ims += glob(fp_glob, recursive=True)
+ else:
+ fp_glob = join(opt_dir_in, '*.{}'.format(opt_ext))
+ fp_ims += glob(fp_glob)
+ log.debug(fp_glob)
+
+
+ if opt_slice:
+ fp_ims = fp_ims[opt_slice[0]:opt_slice[1]]
+ log.debug('processing {:,} files'.format(len(fp_ims)))
+
+
+ data = {}
+
+ for fp_im in tqdm(fp_ims):
+ fpp_im = Path(fp_im)
+ im = io.imread(fp_im)
+ preds = fa.get_landmarks(im)
+ if preds and len(preds) > 0:
+ data[fpp_im.name] = preds[0].tolist()
+
+ # save date
+ file_utils.mkdirs(opt_fp_out)
+
+ file_utils.write_json(data, opt_fp_out, verbose=True) \ No newline at end of file