""" Crop images to prepare for training """ import click # from PIL import Image, ImageOps, ImageFilter, ImageDraw from app.settings import types from app.utils import click_utils from app.settings import app_cfg as cfg @click.command() @click.option('-i', '--input', 'opt_dir_in', required=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('-t', '--detector-type', 'opt_detector_type', type=cfg.FaceDetectNetVar, default=click_utils.get_default(types.FaceDetectNet.DLIB_CNN), help=click_utils.show_help(types.FaceDetectNet)) @click.option('-g', '--gpu', 'opt_gpu', default=0, help='GPU index') @click.option('--conf', 'opt_conf_thresh', default=0.85, type=click.FloatRange(0,1), help='Confidence minimum threshold') @click.option('--pyramids', 'opt_pyramids', default=0, type=click.IntRange(0,4), help='Number pyramids to upscale for DLIB detectors') @click.option('--slice', 'opt_slice', type=(int, int), default=(None, None), help='Slice list of files') @click.option('--display/--no-display', 'opt_display', is_flag=True, default=False, help='Display detections to debug') @click.pass_context def cli(ctx, opt_dir_in, opt_fp_out, opt_ext, opt_size, opt_detector_type, opt_gpu, opt_conf_thresh, opt_pyramids, opt_slice, opt_display): """Extrace face""" 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 app.utils import logger_utils, file_utils, im_utils from app.processors import face_detector # ------------------------------------------------- # init here log = logger_utils.Logger.getLogger() if opt_detector_type == types.FaceDetectNet.CVDNN: detector = face_detector.DetectorCVDNN() elif opt_detector_type == types.FaceDetectNet.DLIB_CNN: detector = face_detector.DetectorDLIBCNN(opt_gpu) elif opt_detector_type == types.FaceDetectNet.DLIB_HOG: detector = face_detector.DetectorDLIBHOG() elif opt_detector_type == types.FaceDetectNet.HAAR: log.error('{} not yet implemented'.format(opt_detector_type.name)) return # ------------------------------------------------- # process here # get list of files to process fp_ims = glob(join(opt_dir_in, '*.{}'.format(opt_ext))) 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): im = cv.imread(fp_im) bboxes = detector.detect(im, opt_size=opt_size, opt_pyramids=opt_pyramids) fpp_im = Path(fp_im) for bbox in bboxes: roi = { 'fn': fpp_im.stem, 'ext': fpp_im.suffix, 'x': bbox.x, 'y': bbox.y, 'w': bbox.w, 'h': bbox.h} dim = bbox.to_dim(im.shape[:2][::-1]) # w,h data.append(roi) # debug display if opt_display and len(bboxes): im_md = im_utils.resize(im, width=opt_size[0]) for bbox in bboxes: dim = bbox.to_dim(im_md.shape[:2][::-1]) cv.rectangle(im_md, dim.pt_tl, dim.pt_br, (0,255,0), 3) cv.imshow('', im_md) 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 # save date df = pd.DataFrame.from_dict(data) df.to_csv(opt_fp_out)