summaryrefslogtreecommitdiff
path: root/megapixels/commands
diff options
context:
space:
mode:
authoradamhrv <adam@ahprojects.com>2019-01-18 11:00:18 +0100
committeradamhrv <adam@ahprojects.com>2019-01-18 11:00:18 +0100
commite06af50389f849be0bfe4fa97d39f4519ef2c711 (patch)
tree49755b51e1b8b1f8031e5483333570a8e9951272 /megapixels/commands
parent03ad11fb2a3dcd425d50167b15d72d4e0ef536a2 (diff)
change to cli_proc
Diffstat (limited to 'megapixels/commands')
-rw-r--r--megapixels/commands/datasets/preproc_wiki_imdb.py205
-rw-r--r--megapixels/commands/demo/face_search.py38
-rw-r--r--megapixels/commands/processor/_old_files_to_face_rois.py (renamed from megapixels/commands/cv/_old_files_to_face_rois.py)0
-rw-r--r--megapixels/commands/processor/cluster.py (renamed from megapixels/commands/cv/cluster.py)0
-rw-r--r--megapixels/commands/processor/crop.py (renamed from megapixels/commands/cv/crop.py)0
-rw-r--r--megapixels/commands/processor/csv_to_faces.py (renamed from megapixels/commands/cv/csv_to_faces.py)0
-rw-r--r--megapixels/commands/processor/csv_to_faces_mt.py (renamed from megapixels/commands/cv/csv_to_faces_mt.py)0
-rw-r--r--megapixels/commands/processor/face_3ddfa.py (renamed from megapixels/commands/cv/face_3ddfa.py)0
-rw-r--r--megapixels/commands/processor/face_attributes.py (renamed from megapixels/commands/cv/face_attributes.py)0
-rw-r--r--megapixels/commands/processor/face_frames.py (renamed from megapixels/commands/cv/face_frames.py)0
-rw-r--r--megapixels/commands/processor/face_landmark_2d_5.py (renamed from megapixels/commands/cv/face_landmark_2d_5.py)0
-rw-r--r--megapixels/commands/processor/face_landmark_2d_68.py (renamed from megapixels/commands/cv/face_landmark_2d_68.py)0
-rw-r--r--megapixels/commands/processor/face_landmark_3d_68.py (renamed from megapixels/commands/cv/face_landmark_3d_68.py)0
-rw-r--r--megapixels/commands/processor/face_pose.py (renamed from megapixels/commands/cv/face_pose.py)0
-rw-r--r--megapixels/commands/processor/face_roi.py (renamed from megapixels/commands/cv/face_roi.py)4
-rw-r--r--megapixels/commands/processor/face_vector.py (renamed from megapixels/commands/cv/face_vector.py)0
-rw-r--r--megapixels/commands/processor/mirror.py (renamed from megapixels/commands/cv/mirror.py)0
-rw-r--r--megapixels/commands/processor/resize.py (renamed from megapixels/commands/cv/resize.py)0
-rw-r--r--megapixels/commands/processor/resize_dataset.py (renamed from megapixels/commands/cv/resize_dataset.py)0
-rw-r--r--megapixels/commands/processor/videos_to_frames.py (renamed from megapixels/commands/cv/videos_to_frames.py)0
20 files changed, 240 insertions, 7 deletions
diff --git a/megapixels/commands/datasets/preproc_wiki_imdb.py b/megapixels/commands/datasets/preproc_wiki_imdb.py
new file mode 100644
index 00000000..66680ed0
--- /dev/null
+++ b/megapixels/commands/datasets/preproc_wiki_imdb.py
@@ -0,0 +1,205 @@
+from glob import glob
+import os
+from os.path import join
+from pathlib import Path
+
+import click
+
+from app.settings import types
+from app.utils import click_utils
+from app.settings import app_cfg as cfg
+from app.utils import logger_utils
+
+import dlib
+import pandas as pd
+from PIL import Image, ImageOps, ImageFilter
+from app.utils import file_utils, im_utils
+
+
+log = logger_utils.Logger.getLogger()
+
+@click.command()
+@click.option('-i', '--input', 'opt_fp_in', required=True,
+ help='Input directory')
+@click.option('-o', '--output', 'opt_fp_out',
+ help='Output directory')
+@click.option('--videos', 'opt_dir_videos',
+ help='Output directory')
+@click.option('--action', 'opt_action',
+ type=click.Choice(['info', 'faces', 'rename', 'download', 'metadata', 'split_frames']),
+ default='info',
+ help='Command action')
+@click.pass_context
+def cli(ctx, opt_fp_in, opt_fp_out, opt_dir_videos, opt_action):
+ """YTMU utils"""
+
+
+ from tqdm import tqdm
+
+ # -------------------------------------------------
+ # process
+
+ if opt_action == 'metadata':
+ # downloads video metadata with ytdl
+ handle_metadata(opt_fp_in, opt_fp_out)
+ elif opt_action == 'download':
+ # downloads video files with ytdl
+ handle_download(opt_fp_in, opt_fp_out)
+ elif opt_action == 'info':
+ # converts original data file to clean CSV
+ handle_info()
+ elif opt_action == 'rename':
+ # rename the videos to video ID
+ handle_rename(opt_fp_in, opt_fp_out, opt_dir_videos)
+ elif opt_action == 'split_frames':
+ # rename the videos to video ID
+ handle_split_frames(opt_fp_in, opt_fp_out, opt_dir_videos)
+
+
+
+
+# ----------------------------------------------------
+# handlers
+
+def handle_split_frames(fp_in, dir_out, dir_videos):
+ if not dir_out or not dir_videos:
+ log.error('-o/--output and --videos required')
+ return
+ import cv2 as cv
+ from tqdm import tqdm
+ from app.processors import face_detector
+ detector = face_detector.DetectorDLIBCNN()
+
+ # get file list
+ fp_videos = glob(join(dir_videos, '*.mp4'))
+ fp_videos += glob(join(dir_videos, '*.webm'))
+ fp_videos += glob(join(dir_videos, '*.mkv'))
+ face_interval = 30
+ frame_interval_count = 0
+ frame_count = 0
+
+ file_utils.mkdirs(dir_out)
+
+ for fp_video in tqdm(fp_videos):
+ # log.debug('opening: {}'.format(fp_video))
+ video = cv.VideoCapture(fp_video)
+ while video.isOpened():
+ res, frame = video.read()
+ if not res:
+ break
+
+ frame_count += 1 # for naming
+ frame_interval_count += 1 # for interval
+ bboxes = detector.detect(frame, opt_size=(320, 240), opt_pyramids=0)
+ if len(bboxes) > 0 and frame_interval_count >= face_interval:
+ # save frame
+ fp_frame = join(dir_out, '{}_{}.jpg'.format(Path(fp_video).stem, file_utils.zpad(frame_count)))
+ cv.imwrite(fp_frame, frame)
+ frame_interval_count = 0
+
+
+def handle_metadata(fp_in, fp_out):
+
+ keys = ['description', 'average_rating', 'dislike_count', 'categories',
+ 'thumbnail', 'title', 'upload_date', 'uploader_url', 'uploader_id',
+ 'fps', 'height', 'width', 'like_count', 'license', 'tags']
+
+ import youtube_dl
+
+ ydl = youtube_dl.YoutubeDL({'outtmpl': '%(id)s%(ext)s'})
+
+ df = pd.read_csv(fp_in)
+ data_exp = []
+
+ for i, row in df.iterrows():
+ video_data = {'url': row['url'], 'id': row['id']}
+ try:
+ with ydl:
+ url = 'http://www.youtube.com/watch?v={}'.format(row['id'])
+ result = ydl.extract_info(url, download=False)
+ video = result['entries'][0] if 'entries' in result else result
+ for k in keys:
+ val = video[k]
+ if k == 'title':
+ log.debug(val)
+ if type(val) == list:
+ val = '; '.join(val)
+ if type(val) == str:
+ video_data[k] = str(val).replace(',',';')
+ # log.debug('video_data: {}'.format(video_data))
+ except Exception as e:
+ log.warn('video unavilable: {}'.format(row['url']))
+ log.error(e)
+ continue
+ data_exp.append(video_data)
+
+ df_exp = pd.DataFrame.from_dict(data_exp)
+ df_exp.to_csv(fp_out)
+
+
+def handle_download(fp_in, dir_out):
+ import youtube_dl
+ df = pd.read_csv(fp_in)
+ fp_videos = glob(join(dir_out, '*.mp4'))
+ fp_videos += glob(join(dir_out, '*.webm'))
+ fp_videos += glob(join(dir_out, '*.mkv'))
+
+ ydl = youtube_dl.YoutubeDL({'outtmpl': '%(id)s%(ext)s'})
+
+ for i, row in df.iterrows():
+ vid = row['id']
+ found = False
+ for fp_video in fp_videos:
+ if vid in fp_video:
+ log.debug('skip: {}'.format(vid))
+ found = True
+ if not found:
+ try:
+ with ydl:
+ ydl.download(['http://www.youtube.com/watch?v={}'.format(vid)])
+ except:
+ log.error('could not dl: {}'.format(vid))
+
+
+def handle_info(fp_in, fp_out):
+ if not fp_out:
+ log.error('--output required')
+ return
+ urls = file_utils.load_text(fp_in)
+ videos = []
+ for url in urls:
+ splits = url.split('v=')
+ try:
+ vid = splits[1]
+ vid = vid.split('&')[0]
+ videos.append({'url': url, 'id': vid})
+ except:
+ log.warn('no video id for {}'.format(url))
+ # convert to df
+ df = pd.DataFrame.from_dict(videos)
+ df.to_csv(opt_fp_out)
+
+
+def handle_rename(fp_in, fp_out, dir_videos):
+ import shutil
+
+ if not dir_videos:
+ log.error('--videos required')
+ return
+
+ fp_videos = glob(join(dir_videos, '*.mp4'))
+ fp_videos += glob(join(dir_videos, '*.webm'))
+ fp_videos += glob(join(dir_videos, '*.mkv'))
+
+ df = pd.read_csv(fp_in)
+
+ for i, row in df.iterrows():
+ vid = row['id']
+ fp_videos_copy = fp_videos.copy()
+ for fp_video in fp_videos:
+ if vid in fp_video:
+ dst = join(dir_videos, '{}{}'.format(vid, Path(fp_video).suffix))
+ shutil.move(fp_video, dst)
+ log.debug('move {} to {}'.format(fp_video, dst))
+ fp_videos.remove(fp_video)
+ break \ No newline at end of file
diff --git a/megapixels/commands/demo/face_search.py b/megapixels/commands/demo/face_search.py
index f551cafd..4c7036f4 100644
--- a/megapixels/commands/demo/face_search.py
+++ b/megapixels/commands/demo/face_search.py
@@ -53,7 +53,7 @@ def cli(ctx, opt_fp_in, opt_data_store, opt_dataset, opt_results, opt_gpu):
dataset.load_metadata(types.Metadata.FILE_RECORD)
dataset.load_metadata(types.Metadata.FACE_VECTOR)
dataset.load_metadata(types.Metadata.FACE_ROI)
- # dataset.load_metadata(types.Metadata.IDENTITY)
+ dataset.load_metadata(types.Metadata.IDENTITY)
# init face detection
detector = face_detector.DetectorCVDNN()
@@ -82,22 +82,50 @@ def cli(ctx, opt_fp_in, opt_data_store, opt_dataset, opt_results, opt_gpu):
image_records = dataset.find_matches(vec_query, n_results=opt_results)
# summary
- im_query = draw_utils.draw_bbox(im_query, bbox_norm, stroke_weight=8)
+ im_query = draw_utils.draw_bbox(im_query, bbox_norm, stroke_weight=4)
ims_match = [im_query]
+
+ opt_size = (256,256)
+
for image_record in image_records:
image_record.summarize()
log.info(f'{image_record.filepath}')
im_match = cv.imread(image_record.filepath)
+ dim_match = im_match.shape[:2][::-1]
+ bbox_match = image_record.bbox
+ score = image_record.score
+ if score < .5:
+ clr = (0,255,0)
+ elif score < .6:
+ clr = (0,255,125)
+ elif score < .65:
+ clr = (0,125,125)
+ elif score < .7:
+ clr = (0,125,255)
+ else:
+ clr = (0,0,255)
+
+ im_match = draw_utils.draw_bbox(im_match, bbox_match, stroke_weight=4, color=clr )
+ bbox_match_dim = bbox_match.to_dim(dim_match)
- im_match_pil = Image.open(image_record.filepath).convert('RGB')
- # bbox =
- ims_match.append(im_match)
+ im_pil = im_utils.ensure_pil(im_match)
+ center = (bbox_match_dim.cx, bbox_match_dim.cy)
+ im_pil = ImageOps.fit(im_pil, opt_size, centering=center)
+ im_np = im_utils.ensure_np(im_pil)
+ if image_record.identity is not None:
+ log.debug(f'identity: {image_record.identity.name_display}')
+ else:
+ log.debug('no identity info')
+ log.debug(f'score: {image_record.score}')
+ ims_match.append(im_np)
# make montages of most similar faces
montages = imutils.build_montages(ims_match, (256, 256), (3,2))
# display
for i, montage in enumerate(montages):
cv.imshow(f'{opt_dataset.name.upper()}: page {i}', montage)
+ fp_out = join(Path(opt_fp_in).parent, f'{Path(opt_fp_in).stem}_{i}.png')
+ cv.imwrite(fp_out, montage)
display_utils.handle_keyboard()
diff --git a/megapixels/commands/cv/_old_files_to_face_rois.py b/megapixels/commands/processor/_old_files_to_face_rois.py
index d92cbd74..d92cbd74 100644
--- a/megapixels/commands/cv/_old_files_to_face_rois.py
+++ b/megapixels/commands/processor/_old_files_to_face_rois.py
diff --git a/megapixels/commands/cv/cluster.py b/megapixels/commands/processor/cluster.py
index 419091a0..419091a0 100644
--- a/megapixels/commands/cv/cluster.py
+++ b/megapixels/commands/processor/cluster.py
diff --git a/megapixels/commands/cv/crop.py b/megapixels/commands/processor/crop.py
index 778be0c4..778be0c4 100644
--- a/megapixels/commands/cv/crop.py
+++ b/megapixels/commands/processor/crop.py
diff --git a/megapixels/commands/cv/csv_to_faces.py b/megapixels/commands/processor/csv_to_faces.py
index 64c8b965..64c8b965 100644
--- a/megapixels/commands/cv/csv_to_faces.py
+++ b/megapixels/commands/processor/csv_to_faces.py
diff --git a/megapixels/commands/cv/csv_to_faces_mt.py b/megapixels/commands/processor/csv_to_faces_mt.py
index 64c8b965..64c8b965 100644
--- a/megapixels/commands/cv/csv_to_faces_mt.py
+++ b/megapixels/commands/processor/csv_to_faces_mt.py
diff --git a/megapixels/commands/cv/face_3ddfa.py b/megapixels/commands/processor/face_3ddfa.py
index ffc74180..ffc74180 100644
--- a/megapixels/commands/cv/face_3ddfa.py
+++ b/megapixels/commands/processor/face_3ddfa.py
diff --git a/megapixels/commands/cv/face_attributes.py b/megapixels/commands/processor/face_attributes.py
index 01fe3bd1..01fe3bd1 100644
--- a/megapixels/commands/cv/face_attributes.py
+++ b/megapixels/commands/processor/face_attributes.py
diff --git a/megapixels/commands/cv/face_frames.py b/megapixels/commands/processor/face_frames.py
index 76f23af1..76f23af1 100644
--- a/megapixels/commands/cv/face_frames.py
+++ b/megapixels/commands/processor/face_frames.py
diff --git a/megapixels/commands/cv/face_landmark_2d_5.py b/megapixels/commands/processor/face_landmark_2d_5.py
index 40ec6f41..40ec6f41 100644
--- a/megapixels/commands/cv/face_landmark_2d_5.py
+++ b/megapixels/commands/processor/face_landmark_2d_5.py
diff --git a/megapixels/commands/cv/face_landmark_2d_68.py b/megapixels/commands/processor/face_landmark_2d_68.py
index c6978a40..c6978a40 100644
--- a/megapixels/commands/cv/face_landmark_2d_68.py
+++ b/megapixels/commands/processor/face_landmark_2d_68.py
diff --git a/megapixels/commands/cv/face_landmark_3d_68.py b/megapixels/commands/processor/face_landmark_3d_68.py
index a2d14d72..a2d14d72 100644
--- a/megapixels/commands/cv/face_landmark_3d_68.py
+++ b/megapixels/commands/processor/face_landmark_3d_68.py
diff --git a/megapixels/commands/cv/face_pose.py b/megapixels/commands/processor/face_pose.py
index cb7ec56c..cb7ec56c 100644
--- a/megapixels/commands/cv/face_pose.py
+++ b/megapixels/commands/processor/face_pose.py
diff --git a/megapixels/commands/cv/face_roi.py b/megapixels/commands/processor/face_roi.py
index e83b0f61..fc933049 100644
--- a/megapixels/commands/cv/face_roi.py
+++ b/megapixels/commands/processor/face_roi.py
@@ -48,9 +48,9 @@ color_filters = {'color': 1, 'gray': 2, 'all': 3}
@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='all',
+ 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='all',
+@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)')
diff --git a/megapixels/commands/cv/face_vector.py b/megapixels/commands/processor/face_vector.py
index cb155d08..cb155d08 100644
--- a/megapixels/commands/cv/face_vector.py
+++ b/megapixels/commands/processor/face_vector.py
diff --git a/megapixels/commands/cv/mirror.py b/megapixels/commands/processor/mirror.py
index 9ca1cac7..9ca1cac7 100644
--- a/megapixels/commands/cv/mirror.py
+++ b/megapixels/commands/processor/mirror.py
diff --git a/megapixels/commands/cv/resize.py b/megapixels/commands/processor/resize.py
index 7409ee6f..7409ee6f 100644
--- a/megapixels/commands/cv/resize.py
+++ b/megapixels/commands/processor/resize.py
diff --git a/megapixels/commands/cv/resize_dataset.py b/megapixels/commands/processor/resize_dataset.py
index 3a6ec15f..3a6ec15f 100644
--- a/megapixels/commands/cv/resize_dataset.py
+++ b/megapixels/commands/processor/resize_dataset.py
diff --git a/megapixels/commands/cv/videos_to_frames.py b/megapixels/commands/processor/videos_to_frames.py
index 0b56c46a..0b56c46a 100644
--- a/megapixels/commands/cv/videos_to_frames.py
+++ b/megapixels/commands/processor/videos_to_frames.py