""" Converts ROIs to face vector """ import click 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_fp_files', required=True, help='Input ROI CSV') @click.option('-r', '--rois', 'opt_fp_rois', required=True, help='Input ROI CSV') @click.option('-m', '--media', 'opt_dir_media', required=True, help='Input media directory') @click.option('-o', '--output', 'opt_fp_out', required=True, help='Output CSV') @click.option('--size', 'opt_size', type=(int, int), default=(300, 300), help='Output image size') @click.option('-j', '--jitters', 'opt_jitters', default=cfg.DLIB_FACEREC_JITTERS, help='Number of jitters') @click.option('-p', '--padding', 'opt_padding', default=cfg.DLIB_FACEREC_PADDING, help='Percentage padding') @click.option('--slice', 'opt_slice', type=(int, int), default=(None, None), help='Slice list of files') @click.option('-f', '--force', 'opt_force', is_flag=True, help='Force overwrite file') @click.option('-g', '--gpu', 'opt_gpu', default=0, help='GPU index') @click.pass_context def cli(ctx, opt_fp_files, opt_fp_rois, opt_dir_media, opt_fp_out, opt_size, opt_slice, opt_force, opt_gpu, opt_jitters, opt_padding): """Converts face ROIs to vectors""" 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.models.bbox import BBox from app.utils import logger_utils, file_utils, im_utils from app.processors import face_recognition # ------------------------------------------------- # init here log = logger_utils.Logger.getLogger() # init face processors facerec = face_recognition.RecognitionDLIB() # load data df_file_meta = pd.read_csv(opt_fp_files) df_rois = pd.read_csv(opt_fp_rois) if not opt_force and Path(opt_fp_out).exists(): log.error('File exists. Use "-f / --force" to overwite') return if opt_slice: df_rois = df_rois[opt_slice[0]:opt_slice[1]] # ------------------------------------------------- # process here df_img_groups = df_rois.groupby('image_index') log.debug('processing {:,} groups'.format(len(df_img_groups))) vecs = [] for image_index, df_img_group in tqdm(df_img_groups): # make fp roi_index = df_img_group.index.values[0] file_meta = df_file_meta.iloc[image_index] # locate image meta fp_im = join(opt_dir_media, file_meta.subdir, '{}.{}'.format(file_meta.fn, file_meta.ext)) im = cv.imread(fp_im) # get bbox x = df_img_group.x.values[0] y = df_img_group.y.values[0] w = df_img_group.w.values[0] h = df_img_group.h.values[0] imw = df_img_group.image_width.values[0] imh = df_img_group.image_height.values[0] dim = im.shape[:2][::-1] # get face vector dim = (imw, imh) bbox_dim = BBox.from_xywh(x, y, w, h).to_dim(dim) # convert to int real dimensions # compute vec # padding=opt_padding not yet implemented in 19.16 but merged in master vec = facerec.vec(im, bbox_dim, jitters=opt_jitters) vec_str = ','.join([repr(x) for x in vec]) # convert to string for CSV vecs.append( {'roi_index': roi_index, 'image_index': image_index, 'vec': vec_str}) # save date file_utils.mkdirs(opt_fp_out) df = pd.DataFrame.from_dict(vecs) df.index.name = 'index' df.to_csv(opt_fp_out)