""" 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 color_filters = {'color': 1, 'gray': 2, 'all': 3} @click.command() @click.option('-i', '--input', 'opt_fp_in', required=True, help='Override enum input filename CSV') @click.option('-o', '--output', 'opt_fp_out', required=True, help='Override enum output filename CSV') @click.option('--store', 'opt_data_store', type=cfg.DataStoreVar, default=click_utils.get_default(types.DataStore.HDD), show_default=True, help=click_utils.show_help(types.Dataset)) @click.option('--size', 'opt_size', type=(int, int), default=(640, 480), help='Input image size') @click.option('-d', '--detector', 'opt_detector_type', type=cfg.BodyDetectNetVar, default=click_utils.get_default(types.BodyDetectNet.CVDNN), help=click_utils.show_help(types.BodyDetectNet)) @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('-p', '--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.option('-f', '--force', 'opt_force', is_flag=True, help='Force overwrite file') @click.option('--color', 'opt_color_filter', type=click.Choice(color_filters.keys()), default='color', help='Filter to keep color or grayscale images (color = keep color') @click.option('--keep', 'opt_largest', type=click.Choice(['largest', 'all']), default='largest', help='Only keep largest face') @click.option('--zone', 'opt_zone', default=(0.0, 0.0), type=(float, float), help='Face center must be located within zone region (0.5 = half width/height)') @click.pass_context def cli(ctx, opt_fp_in, opt_fp_out, opt_data_store, opt_size, opt_detector_type, opt_gpu, opt_conf_thresh, opt_pyramids, opt_slice, opt_display, opt_force, opt_color_filter, opt_largest, opt_zone): """Converts frames with faces to CSV of ROIs""" 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, display_utils, draw_utils from app.processors import person_detector from app.models.data_store import DataStore # ------------------------------------------------- # init here log = logger_utils.Logger.getLogger() opt_fp_out = opt_fp_out if not opt_force and Path(opt_fp_out).exists(): log.error('File exists. Use "-f / --force" to overwite') return # set detector if opt_detector_type == types.BodyDetectNet.CVDNN: detector = person_detector.DetectorCVDNN() else: log.error('{} not yet implemented'.format(opt_detector_type.name)) return # set largest flag, to keep all or only largest opt_largest = (opt_largest == 'largest') # process video cap = cv.VideoCapture(opt_fp_in) bboxes_all = [] data_out = [] frame_index = 0 while cap.isOpened(): # get video frame readable, im = cap.read() if not readable: break im_resized = im_utils.resize(im, width=opt_size[0], height=opt_size[1]) try: bboxes_norm = detector.detect(im_resized, pyramids=opt_pyramids, largest=opt_largest, zone=opt_zone, conf=opt_conf_thresh, blob_size=opt_size) except Exception as e: log.error('could not detect: {}'.format(frame_index)) log.error('{}'.format(e)) continue for bbox in bboxes_norm: roi = { 'record_index': frame_index, 'x': bbox.x, 'y': bbox.y, 'w': bbox.w, 'h': bbox.h } data_out.append(roi) if opt_display and len(bboxes_norm): # draw each box for bbox_norm in bboxes_norm: dim = im_resized.shape[:2][::-1] bbox_dim = bbox.to_dim(dim) # if dim[0] > 1000: # im_resized = im_utils.resize(im_resized, width=1000) im_resized = draw_utils.draw_bbox(im_resized, bbox_norm) # display and wait cv.imshow('', im_resized) display_utils.handle_keyboard_video() frame_index += 1 # create DataFrame and save to CSV file_utils.mkdirs(opt_fp_out) df = pd.DataFrame.from_dict(data_out) df.index.name = 'index' df.to_csv(opt_fp_out) # save script file_utils.write_text(' '.join(sys.argv), '{}.sh'.format(opt_fp_out))