Upgraded to TF version 1.13.2

Removed the wait at first launch for most graphics cards.

Increased speed of training by 10-20%, but you have to retrain all models from scratch.

SAEHD:

added option 'use float16'
	Experimental option. Reduces the model size by half.
	Increases the speed of training.
	Decreases the accuracy of the model.
	The model may collapse or not train.
	Model may not learn the mask in large resolutions.

true_face_training option is replaced by
"True face power". 0.0000 .. 1.0
Experimental option. Discriminates the result face to be more like the src face. Higher value - stronger discrimination.
Comparison - https://i.imgur.com/czScS9q.png
This commit is contained in:
Colombo 2020-01-25 21:58:19 +04:00
commit 76ca79216e
49 changed files with 1320 additions and 1297 deletions

View file

@ -47,7 +47,7 @@ class ExtractSubprocessor(Subprocessor):
self.max_faces_from_image = client_dict['max_faces_from_image']
self.device_idx = client_dict['device_idx']
self.cpu_only = client_dict['device_type'] == 'CPU'
self.final_output_path = client_dict['final_output_path']
self.final_output_path = client_dict['final_output_path']
self.output_debug_path = client_dict['output_debug_path']
#transfer and set stdin in order to work code.interact in debug subprocess
@ -64,9 +64,9 @@ class ExtractSubprocessor(Subprocessor):
if self.type == 'all' or 'rects' in self.type or 'landmarks' in self.type:
nn.initialize (device_config)
self.log_info (f"Running on {client_dict['device_name'] }")
if self.type == 'all' or self.type == 'rects-s3fd' or 'landmarks' in self.type:
self.rects_extractor = facelib.S3FDExtractor(place_model_on_cpu=place_model_on_cpu)
@ -79,8 +79,8 @@ class ExtractSubprocessor(Subprocessor):
def process_data(self, data):
if 'landmarks' in self.type and len(data.rects) == 0:
return data
filepath = data.filepath
filepath = data.filepath
cached_filepath, image = self.cached_image
if cached_filepath != filepath:
image = cv2_imread( filepath )
@ -93,7 +93,7 @@ class ExtractSubprocessor(Subprocessor):
h, w, c = image.shape
extract_from_dflimg = (h == w and DFLIMG.load (filepath) is not None)
if 'rects' in self.type or self.type == 'all':
data = ExtractSubprocessor.Cli.rects_stage (data=data,
image=image,
@ -119,7 +119,7 @@ class ExtractSubprocessor(Subprocessor):
final_output_path=self.final_output_path,
)
return data
@staticmethod
def rects_stage(data,
image,
@ -157,7 +157,7 @@ class ExtractSubprocessor(Subprocessor):
rects_extractor,
):
h, w, ch = image.shape
if data.rects_rotation == 0:
rotated_image = image
elif data.rects_rotation == 90:
@ -323,7 +323,7 @@ class ExtractSubprocessor(Subprocessor):
self.manual_window_size = manual_window_size
self.max_faces_from_image = max_faces_from_image
self.result = []
self.devices = ExtractSubprocessor.get_devices_for_config(self.type, device_config)
super().__init__('Extractor', ExtractSubprocessor.Cli,
@ -731,21 +731,21 @@ def main(detector=None,
if detector == 'manual':
io.log_info ('Performing manual extract...')
data = ExtractSubprocessor ([ ExtractSubprocessor.Data(Path(filename)) for filename in input_path_image_paths ], 'landmarks-manual', image_size, face_type, output_debug_path if output_debug else None, manual_window_size=manual_window_size, device_config=device_config).run()
io.log_info ('Performing 3rd pass...')
data = ExtractSubprocessor (data, 'final', image_size, face_type, output_debug_path if output_debug else None, final_output_path=output_path, device_config=device_config).run()
else:
io.log_info ('Extracting faces...')
data = ExtractSubprocessor ([ ExtractSubprocessor.Data(Path(filename)) for filename in input_path_image_paths ],
'all',
image_size,
face_type,
output_debug_path if output_debug else None,
max_faces_from_image=max_faces_from_image,
data = ExtractSubprocessor ([ ExtractSubprocessor.Data(Path(filename)) for filename in input_path_image_paths ],
'all',
image_size,
face_type,
output_debug_path if output_debug else None,
max_faces_from_image=max_faces_from_image,
final_output_path=output_path,
device_config=device_config).run()
faces_detected += sum([d.faces_detected for d in data])
if manual_fix:

View file

@ -10,7 +10,7 @@ from core.cv2ex import *
class FacesetEnhancerSubprocessor(Subprocessor):
#override
def __init__(self, image_paths, output_dirpath, device_config):
self.image_paths = image_paths
@ -18,17 +18,17 @@ class FacesetEnhancerSubprocessor(Subprocessor):
self.result = []
self.nn_initialize_mp_lock = multiprocessing.Lock()
self.devices = FacesetEnhancerSubprocessor.get_devices_for_config(device_config)
super().__init__('FacesetEnhancer', FacesetEnhancerSubprocessor.Cli, 600)
#override
def on_clients_initialized(self):
io.progress_bar (None, len (self.image_paths))
#override
def on_clients_finalized(self):
io.progress_bar_close()
#override
def process_info_generator(self):
base_dict = {'output_dirpath':self.output_dirpath,
@ -42,34 +42,34 @@ class FacesetEnhancerSubprocessor(Subprocessor):
yield client_dict['device_name'], {}, client_dict
#override
def get_data(self, host_dict):
def get_data(self, host_dict):
if len (self.image_paths) > 0:
return self.image_paths.pop(0)
#override
def on_data_return (self, host_dict, data):
self.image_paths.insert(0, data)
#override
def on_result (self, host_dict, data, result):
io.progress_bar_inc(1)
if result[0] == 1:
self.result +=[ (result[1], result[2]) ]
#override
def get_result(self):
return self.result
@staticmethod
def get_devices_for_config (device_config):
def get_devices_for_config (device_config):
devices = device_config.devices
cpu_only = len(devices) == 0
if not cpu_only:
if not cpu_only:
return [ (device.index, 'GPU', device.name, device.total_mem_gb) for device in devices ]
else:
return [ (i, 'CPU', 'CPU%d' % (i), 0 ) for i in range( min(8, multiprocessing.cpu_count() // 2) ) ]
class Cli(Subprocessor.Cli):
#override
@ -85,14 +85,14 @@ class FacesetEnhancerSubprocessor(Subprocessor):
else:
device_config = nn.DeviceConfig.GPUIndexes ([device_idx])
device_vram = device_config.devices[0].total_mem_gb
nn.initialize (device_config)
nn.initialize (device_config)
intro_str = 'Running on %s.' % (client_dict['device_name'])
self.log_info (intro_str)
from facelib import FaceEnhancer
from facelib import FaceEnhancer
self.fe = FaceEnhancer( place_model_on_cpu=(device_vram<=2) )
#override
@ -103,28 +103,28 @@ class FacesetEnhancerSubprocessor(Subprocessor):
self.log_err ("%s is not a dfl image file" % (filepath.name) )
else:
img = cv2_imread(filepath).astype(np.float32) / 255.0
img = self.fe.enhance(img)
img = np.clip (img*255, 0, 255).astype(np.uint8)
output_filepath = self.output_dirpath / filepath.name
cv2_imwrite ( str(output_filepath), img, [int(cv2.IMWRITE_JPEG_QUALITY), 100] )
dflimg.embed_and_set ( str(output_filepath) )
return (1, filepath, output_filepath)
except:
self.log_err (f"Exception occured while processing file {filepath}. Error: {traceback.format_exc()}")
return (0, filepath, None)
def process_folder ( dirpath, cpu_only=False, force_gpu_idxs=None ):
device_config = nn.DeviceConfig.GPUIndexes( force_gpu_idxs or nn.ask_choose_device_idxs(suggest_all_gpu=True) ) \
if not cpu_only else nn.DeviceConfig.CPU()
output_dirpath = dirpath.parent / (dirpath.name + '_enhanced')
output_dirpath.mkdir (exist_ok=True, parents=True)
dirpath_parts = '/'.join( dirpath.parts[-2:])
output_dirpath_parts = '/'.join( output_dirpath.parts[-2:] )
io.log_info (f"Enhancing faceset in {dirpath_parts}")
@ -134,19 +134,19 @@ def process_folder ( dirpath, cpu_only=False, force_gpu_idxs=None ):
if len(output_images_paths) > 0:
for filename in output_images_paths:
Path(filename).unlink()
image_paths = [Path(x) for x in pathex.get_image_paths( dirpath )]
image_paths = [Path(x) for x in pathex.get_image_paths( dirpath )]
result = FacesetEnhancerSubprocessor ( image_paths, output_dirpath, device_config=device_config).run()
is_merge = io.input_bool (f"\r\nMerge {output_dirpath_parts} to {dirpath_parts} ?", True)
if is_merge:
io.log_info (f"Copying processed files to {dirpath_parts}")
for (filepath, output_filepath) in result:
try:
for (filepath, output_filepath) in result:
try:
shutil.copy (output_filepath, filepath)
except:
pass
io.log_info (f"Removing {output_dirpath_parts}")
shutil.rmtree(output_dirpath)

View file

@ -319,14 +319,14 @@ class MaskEditor:
def get_ie_polys(self):
return self.ie_polys
def set_ie_polys(self, saved_ie_polys):
self.state = self.STATE_NONE
self.ie_polys = saved_ie_polys
self.redo_to_end_point()
self.mask_finish()
def mask_editor_main(input_dir, confirmed_dir=None, skipped_dir=None, no_default_mask=False):
input_path = Path(input_dir)
@ -341,7 +341,7 @@ def mask_editor_main(input_dir, confirmed_dir=None, skipped_dir=None, no_default
if not skipped_path.exists():
skipped_path.mkdir(parents=True)
if not no_default_mask:
eyebrows_expand_mod = np.clip ( io.input_int ("Default eyebrows expand modifier?", 100, add_info="0..400"), 0, 400 ) / 100.0
else:
@ -368,7 +368,7 @@ def mask_editor_main(input_dir, confirmed_dir=None, skipped_dir=None, no_default
do_save_count = 0
do_skip_move_count = 0
do_skip_count = 0
def jobs_count():
return do_prev_count + do_save_move_count + do_save_count + do_skip_move_count + do_skip_count

View file

@ -237,7 +237,7 @@ class MergeSubprocessor(Subprocessor):
try:
with open( str(self.merger_session_filepath), "rb") as f:
session_data = pickle.loads(f.read())
except Exception as e:
pass
@ -282,8 +282,8 @@ class MergeSubprocessor(Subprocessor):
self.frames_done_idxs = s_frames_done_idxs
rewind_to_begin = len(self.frames_idxs) == 0 # all frames are done?
if self.model_iter != s_model_iter:
if self.model_iter != s_model_iter:
# model was more trained, recompute all frames
rewind_to_begin = True
for frame in self.frames:
@ -461,15 +461,15 @@ class MergeSubprocessor(Subprocessor):
if key == 27: #esc
self.is_interactive_quitting = True
elif self.screen_manager.get_current() is self.main_screen:
if self.merger_config.type == MergerConfig.TYPE_MASKED and chr_key in self.masked_keys:
if self.merger_config.type == MergerConfig.TYPE_MASKED and chr_key in self.masked_keys:
self.process_remain_frames = False
if cur_frame is not None:
cfg = cur_frame.cfg
prev_cfg = cfg.copy()
if cfg.type == MergerConfig.TYPE_MASKED:
if cfg.type == MergerConfig.TYPE_MASKED:
self.masked_keys_funcs[chr_key](cfg, shift_pressed)
if prev_cfg != cfg:
@ -485,7 +485,7 @@ class MergeSubprocessor(Subprocessor):
if chr_key == ',':
if shift_pressed:
go_first_frame = True
elif chr_key == 'm':
if not shift_pressed:
go_prev_frame_overriding_cfg = True
@ -499,7 +499,7 @@ class MergeSubprocessor(Subprocessor):
if chr_key == '.':
if shift_pressed:
self.process_remain_frames = not self.process_remain_frames
elif chr_key == '/':
if not shift_pressed:
go_next_frame_overriding_cfg = True
@ -566,7 +566,7 @@ class MergeSubprocessor(Subprocessor):
frame.cfg = cur_frame.cfg.copy()
else:
frame.cfg = f[ self.frames_idxs[i-1] ].cfg.copy()
frame.is_done = False #initiate solve again
frame.is_shown = False
@ -775,7 +775,7 @@ def main (model_class_name=None,
io.log_info ("No frames to merge in input_dir.")
else:
MergeSubprocessor (
is_interactive = is_interactive,
is_interactive = is_interactive,
merger_session_filepath = merger_session_filepath,
predictor_func = predictor_func,
predictor_input_shape = predictor_input_shape,

View file

@ -717,7 +717,7 @@ def sort_by_absdiff(input_path):
from core.leras import nn
device_config = nn.ask_choose_device_idxs(choose_only_one=True, return_device_config=True)
nn.initialize( device_config=device_config )
nn.initialize( device_config=device_config, data_format="NHWC" )
tf = nn.tf
image_paths = pathex.get_image_paths(input_path)

View file

@ -12,19 +12,19 @@ import cv2
import models
from core.interact import interact as io
def trainerThread (s2c, c2s, e,
def trainerThread (s2c, c2s, e,
model_class_name = None,
saved_models_path = None,
training_data_src_path = None,
training_data_dst_path = None,
pretraining_data_path = None,
pretrained_model_path = None,
no_preview=False,
pretraining_data_path = None,
pretrained_model_path = None,
no_preview=False,
force_model_name=None,
force_gpu_idxs=None,
cpu_only=None,
cpu_only=None,
execute_programs = None,
debug=False,
debug=False,
**kwargs):
while True:
try:
@ -98,11 +98,11 @@ def trainerThread (s2c, c2s, e,
exec_prog = False
if prog_time > 0 and (cur_time - start_time) >= prog_time:
x[0] = 0
exec_prog = True
elif prog_time < 0 and (cur_time - last_time) >= -prog_time:
x[2] = cur_time
exec_prog = True
elif prog_time < 0 and (cur_time - last_time) >= -prog_time:
x[2] = cur_time
exec_prog = True
if exec_prog:
try:
exec(prog)
@ -110,12 +110,12 @@ def trainerThread (s2c, c2s, e,
print("Unable to execute program: %s" % (prog) )
if not is_reached_goal:
if model.get_iter() == 0:
io.log_info("")
io.log_info("Trying to do the first iteration. If an error occurs, reduce the model parameters.")
io.log_info("")
iter, iter_time = model.train_one_iter()
loss_history = model.get_loss_history()
@ -127,8 +127,8 @@ def trainerThread (s2c, c2s, e,
if shared_state['after_save']:
shared_state['after_save'] = False
last_save_time = time.time()
last_save_time = time.time()
mean_loss = np.mean ( [ np.array(loss_history[i]) for i in range(save_iter, iter) ], axis=0)
for loss_value in mean_loss:
@ -145,10 +145,10 @@ def trainerThread (s2c, c2s, e,
io.log_info ('\r' + loss_string, end='')
else:
io.log_info (loss_string, end='\r')
if model.get_iter() == 1:
model_save()
if model.get_target_iter() != 0 and model.is_reached_iter_goal():
io.log_info ('Reached target iteration.')
model_save()

View file

@ -15,34 +15,34 @@ def save_faceset_metadata_folder(input_path):
input_path = Path(input_path)
metadata_filepath = input_path / 'meta.dat'
io.log_info (f"Saving metadata to {str(metadata_filepath)}\r\n")
d = {}
for filepath in io.progress_bar_generator( pathex.get_image_paths(input_path), "Processing"):
filepath = Path(filepath)
dflimg = DFLIMG.load (filepath)
dfl_dict = dflimg.getDFLDictData()
dfl_dict = dflimg.getDFLDictData()
d[filepath.name] = ( dflimg.get_shape(), dfl_dict )
try:
with open(metadata_filepath, "wb") as f:
f.write ( pickle.dumps(d) )
except:
raise Exception( 'cannot save %s' % (filename) )
io.log_info("Now you can edit images.")
io.log_info("!!! Keep same filenames in the folder.")
io.log_info("You can change size of images, restoring process will downscale back to original size.")
io.log_info("!!! Keep same filenames in the folder.")
io.log_info("You can change size of images, restoring process will downscale back to original size.")
io.log_info("After that, use restore metadata.")
def restore_faceset_metadata_folder(input_path):
input_path = Path(input_path)
metadata_filepath = input_path / 'meta.dat'
io.log_info (f"Restoring metadata from {str(metadata_filepath)}.\r\n")
if not metadata_filepath.exists():
io.log_err(f"Unable to find {str(metadata_filepath)}.")
@ -54,27 +54,27 @@ def restore_faceset_metadata_folder(input_path):
for filepath in io.progress_bar_generator( pathex.get_image_paths(input_path), "Processing"):
filepath = Path(filepath)
shape, dfl_dict = d.get(filepath.name, None)
img = cv2_imread (str(filepath))
if img.shape != shape:
img = cv2.resize (img, (shape[1], shape[0]), cv2.INTER_LANCZOS4 )
if filepath.suffix == '.png':
cv2_imwrite (str(filepath), img)
elif filepath.suffix == '.jpg':
cv2_imwrite (str(filepath), img)
elif filepath.suffix == '.jpg':
cv2_imwrite (str(filepath), img, [int(cv2.IMWRITE_JPEG_QUALITY), 100] )
if filepath.suffix == '.png':
DFLPNG.embed_dfldict( str(filepath), dfl_dict )
elif filepath.suffix == '.jpg':
DFLPNG.embed_dfldict( str(filepath), dfl_dict )
elif filepath.suffix == '.jpg':
DFLJPG.embed_dfldict( str(filepath), dfl_dict )
else:
continue
metadata_filepath.unlink()
def remove_ie_polys_file (filepath):
filepath = Path(filepath)
@ -95,7 +95,7 @@ def remove_ie_polys_folder(input_path):
for filepath in io.progress_bar_generator( pathex.get_image_paths(input_path), "Removing"):
filepath = Path(filepath)
remove_ie_polys_file(filepath)
def remove_fanseg_file (filepath):
filepath = Path(filepath)

View file

@ -101,7 +101,7 @@ def denoise_image_sequence( input_dir, ext=None, factor=None ):
kwargs = {}
if ext == 'jpg':
kwargs.update ({'q:v':'2'})
job = ( ffmpeg
.input(str ( input_path / ('%5d.'+ext) ) )
.filter("hqdn3d", factor, factor, 5,5)
@ -174,7 +174,7 @@ def video_from_sequence( input_dir, output_file, reference_file=None, ext=None,
input_image_paths = pathex.get_image_paths(input_path)
i_in = ffmpeg.input('pipe:', format='image2pipe', r=fps)
output_args = [i_in]
if ref_in_a is not None:
@ -200,14 +200,14 @@ def video_from_sequence( input_dir, output_file, reference_file=None, ext=None,
job = ( ffmpeg.output(*output_args, **output_kwargs).overwrite_output() )
try:
try:
job_run = job.run_async(pipe_stdin=True)
for image_path in input_image_paths:
with open (image_path, "rb") as f:
image_bytes = f.read()
image_bytes = f.read()
job_run.stdin.write (image_bytes)
job_run.stdin.close()
job_run.wait()
except:

View file

@ -23,26 +23,26 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
input_path = Path(input_dir)
if not input_path.exists():
raise ValueError('Input directory not found. Please ensure it exists.')
bb_csv = input_path / 'loose_bb_train.csv'
if not bb_csv.exists():
raise ValueError('loose_bb_train.csv found. Please ensure it exists.')
bb_lines = bb_csv.read_text().split('\n')
bb_lines.pop(0)
bb_dict = {}
for line in bb_lines:
name, l, t, w, h = line.split(',')
name = name[1:-1]
l, t, w, h = [ int(x) for x in (l, t, w, h) ]
l, t, w, h = [ int(x) for x in (l, t, w, h) ]
bb_dict[name] = (l,t,w, h)
output_path = input_path.parent / (input_path.name + '_out')
dir_names = pathex.get_all_dir_names(input_path)
if not output_path.exists():
output_path.mkdir(parents=True, exist_ok=True)
@ -50,15 +50,15 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
for dir_name in io.progress_bar_generator(dir_names, "Collecting"):
cur_input_path = input_path / dir_name
cur_output_path = output_path / dir_name
if not cur_output_path.exists():
cur_output_path.mkdir(parents=True, exist_ok=True)
input_path_image_paths = pathex.get_image_paths(cur_input_path)
for filename in input_path_image_paths:
filename_path = Path(filename)
name = filename_path.parent.name + '/' + filename_path.stem
if name not in bb_dict:
continue
@ -66,29 +66,29 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
l,t,w,h = bb_dict[name]
if min(w,h) < 128:
continue
data += [ ExtractSubprocessor.Data(filename=filename,rects=[ (l,t,l+w,t+h) ], landmarks_accurate=False, force_output_path=cur_output_path ) ]
face_type = FaceType.fromString('full_face')
io.log_info ('Performing 2nd pass...')
data = ExtractSubprocessor (data, 'landmarks', 256, face_type, debug_dir=None, multi_gpu=multi_gpu, cpu_only=cpu_only, manual=False).run()
io.log_info ('Performing 3rd pass...')
ExtractSubprocessor (data, 'final', 256, face_type, debug_dir=None, multi_gpu=multi_gpu, cpu_only=cpu_only, manual=False, final_output_path=None).run()
"""
import code
code.interact(local=dict(globals(), **locals()))
data_len = len(data)
data_len = len(data)
i = 0
while i < data_len-1:
i_name = Path(data[i].filename).parent.name
sub_data = []
for j in range (i, data_len):
j_name = Path(data[j].filename).parent.name
if i_name == j_name:
@ -96,33 +96,33 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
else:
break
i = j
cur_output_path = output_path / i_name
cur_output_path = output_path / i_name
io.log_info (f"Processing: {str(cur_output_path)}, {i}/{data_len} ")
if not cur_output_path.exists():
cur_output_path.mkdir(parents=True, exist_ok=True)
for dir_name in dir_names:
cur_input_path = input_path / dir_name
cur_output_path = output_path / dir_name
input_path_image_paths = pathex.get_image_paths(cur_input_path)
l = len(input_path_image_paths)
#if l < 250 or l > 350:
# continue
io.log_info (f"Processing: {str(cur_input_path)} ")
if not cur_output_path.exists():
cur_output_path.mkdir(parents=True, exist_ok=True)
@ -130,41 +130,41 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
data = []
for filename in input_path_image_paths:
filename_path = Path(filename)
name = filename_path.parent.name + '/' + filename_path.stem
if name not in bb_dict:
continue
bb = bb_dict[name]
l,t,w,h = bb
if min(w,h) < 128:
continue
data += [ ExtractSubprocessor.Data(filename=filename,rects=[ (l,t,l+w,t+h) ], landmarks_accurate=False ) ]
io.log_info ('Performing 2nd pass...')
data = ExtractSubprocessor (data, 'landmarks', 256, face_type, debug_dir=None, multi_gpu=False, cpu_only=False, manual=False).run()
io.log_info ('Performing 3rd pass...')
data = ExtractSubprocessor (data, 'final', 256, face_type, debug_dir=None, multi_gpu=False, cpu_only=False, manual=False, final_output_path=cur_output_path).run()
io.log_info (f"Sorting: {str(cur_output_path)} ")
Sorter.main (input_path=str(cur_output_path), sort_by_method='hist')
import code
code.interact(local=dict(globals(), **locals()))
#try:
# io.log_info (f"Removing: {str(cur_input_path)} ")
# shutil.rmtree(cur_input_path)
#except:
# io.log_info (f"unable to remove: {str(cur_input_path)} ")
def extract_vggface2_dataset(input_dir, device_args={} ):
multi_gpu = device_args.get('multi_gpu', False)
@ -173,27 +173,27 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
input_path = Path(input_dir)
if not input_path.exists():
raise ValueError('Input directory not found. Please ensure it exists.')
output_path = input_path.parent / (input_path.name + '_out')
dir_names = pathex.get_all_dir_names(input_path)
if not output_path.exists():
output_path.mkdir(parents=True, exist_ok=True)
for dir_name in dir_names:
cur_input_path = input_path / dir_name
cur_output_path = output_path / dir_name
l = len(pathex.get_image_paths(cur_input_path))
if l < 250 or l > 350:
continue
io.log_info (f"Processing: {str(cur_input_path)} ")
if not cur_output_path.exists():
cur_output_path.mkdir(parents=True, exist_ok=True)
@ -204,17 +204,17 @@ def extract_vggface2_dataset(input_dir, device_args={} ):
face_type='full_face',
max_faces_from_image=1,
device_args=device_args )
io.log_info (f"Sorting: {str(cur_input_path)} ")
Sorter.main (input_path=str(cur_output_path), sort_by_method='hist')
try:
io.log_info (f"Removing: {str(cur_input_path)} ")
shutil.rmtree(cur_input_path)
except:
io.log_info (f"unable to remove: {str(cur_input_path)} ")
"""
"""
class CelebAMASKHQSubprocessor(Subprocessor):
class Cli(Subprocessor.Cli):
@ -228,31 +228,31 @@ class CelebAMASKHQSubprocessor(Subprocessor):
filename = data[0]
dflimg = DFLIMG.load(Path(filename))
image_to_face_mat = dflimg.get_image_to_face_mat()
image_to_face_mat = dflimg.get_image_to_face_mat()
src_filename = dflimg.get_source_filename()
img = cv2_imread(filename)
h,w,c = img.shape
fanseg_mask = LandmarksProcessor.get_image_hull_mask(img.shape, dflimg.get_landmarks() )
idx_name = '%.5d' % int(src_filename.split('.')[0])
idx_files = [ x for x in self.masks_files_paths if idx_name in x ]
idx_files = [ x for x in self.masks_files_paths if idx_name in x ]
skin_files = [ x for x in idx_files if 'skin' in x ]
eye_glass_files = [ x for x in idx_files if 'eye_g' in x ]
for files, is_invert in [ (skin_files,False),
for files, is_invert in [ (skin_files,False),
(eye_glass_files,True) ]:
if len(files) > 0:
mask = cv2_imread(files[0])
mask = cv2_imread(files[0])
mask = mask[...,0]
mask[mask == 255] = 1
mask = mask.astype(np.float32)
mask = cv2.resize(mask, (1024,1024) )
mask = cv2.resize(mask, (1024,1024) )
mask = cv2.warpAffine(mask, image_to_face_mat, (w, h), cv2.INTER_LANCZOS4)
if not is_invert:
fanseg_mask *= mask[...,None]
else:
@ -270,7 +270,7 @@ class CelebAMASKHQSubprocessor(Subprocessor):
def __init__(self, image_paths, masks_files_paths ):
self.image_paths = image_paths
self.masks_files_paths = masks_files_paths
self.result = []
super().__init__('CelebAMASKHQSubprocessor', CelebAMASKHQSubprocessor.Cli, 60)
@ -304,23 +304,23 @@ class CelebAMASKHQSubprocessor(Subprocessor):
#override
def get_result(self):
return self.result
#unused in end user workflow
def apply_celebamaskhq(input_dir ):
input_path = Path(input_dir)
input_path = Path(input_dir)
img_path = input_path / 'aligned'
mask_path = input_path / 'mask'
if not img_path.exists():
raise ValueError(f'{str(img_path)} directory not found. Please ensure it exists.')
CelebAMASKHQSubprocessor(pathex.get_image_paths(img_path),
CelebAMASKHQSubprocessor(pathex.get_image_paths(img_path),
pathex.get_image_paths(mask_path, subdirs=True) ).run()
return
paths_to_extract = []
for filename in io.progress_bar_generator(pathex.get_image_paths(img_path), desc="Processing"):
filepath = Path(filename)
@ -328,44 +328,44 @@ def apply_celebamaskhq(input_dir ):
if dflimg is not None:
paths_to_extract.append (filepath)
image_to_face_mat = dflimg.get_image_to_face_mat()
image_to_face_mat = dflimg.get_image_to_face_mat()
src_filename = dflimg.get_source_filename()
#img = cv2_imread(filename)
h,w,c = dflimg.get_shape()
fanseg_mask = LandmarksProcessor.get_image_hull_mask( (h,w,c), dflimg.get_landmarks() )
idx_name = '%.5d' % int(src_filename.split('.')[0])
idx_files = [ x for x in masks_files if idx_name in x ]
idx_files = [ x for x in masks_files if idx_name in x ]
skin_files = [ x for x in idx_files if 'skin' in x ]
eye_glass_files = [ x for x in idx_files if 'eye_g' in x ]
for files, is_invert in [ (skin_files,False),
for files, is_invert in [ (skin_files,False),
(eye_glass_files,True) ]:
if len(files) > 0:
mask = cv2_imread(files[0])
mask = cv2_imread(files[0])
mask = mask[...,0]
mask[mask == 255] = 1
mask = mask.astype(np.float32)
mask = cv2.resize(mask, (1024,1024) )
mask = cv2.resize(mask, (1024,1024) )
mask = cv2.warpAffine(mask, image_to_face_mat, (w, h), cv2.INTER_LANCZOS4)
if not is_invert:
fanseg_mask *= mask[...,None]
else:
fanseg_mask *= (1-mask[...,None])
#cv2.imshow("", (fanseg_mask*255).astype(np.uint8) )
#cv2.waitKey(0)
#cv2.waitKey(0)
dflimg.embed_and_set (filename, fanseg_mask=fanseg_mask)
#import code
#code.interact(local=dict(globals(), **locals()))
@ -375,43 +375,43 @@ def apply_celebamaskhq(input_dir ):
def extract_fanseg(input_dir, device_args={} ):
multi_gpu = device_args.get('multi_gpu', False)
cpu_only = device_args.get('cpu_only', False)
input_path = Path(input_dir)
if not input_path.exists():
raise ValueError('Input directory not found. Please ensure it exists.')
paths_to_extract = []
for filename in pathex.get_image_paths(input_path) :
filepath = Path(filename)
dflimg = DFLIMG.load ( filepath )
if dflimg is not None:
paths_to_extract.append (filepath)
paths_to_extract_len = len(paths_to_extract)
if paths_to_extract_len > 0:
io.log_info ("Performing extract fanseg for %d files..." % (paths_to_extract_len) )
data = ExtractSubprocessor ([ ExtractSubprocessor.Data(filename) for filename in paths_to_extract ], 'fanseg', multi_gpu=multi_gpu, cpu_only=cpu_only).run()
#unused in end user workflow
def extract_umd_csv(input_file_csv,
def extract_umd_csv(input_file_csv,
image_size=256,
face_type='full_face',
device_args={} ):
#extract faces from umdfaces.io dataset csv file with pitch,yaw,roll info.
multi_gpu = device_args.get('multi_gpu', False)
cpu_only = device_args.get('cpu_only', False)
face_type = FaceType.fromString(face_type)
input_file_csv_path = Path(input_file_csv)
if not input_file_csv_path.exists():
raise ValueError('input_file_csv not found. Please ensure it exists.')
input_file_csv_root_path = input_file_csv_path.parent
output_path = input_file_csv_path.parent / ('aligned_' + input_file_csv_path.name)
io.log_info("Output dir is %s." % (str(output_path)) )
if output_path.exists():
output_images_paths = pathex.get_image_paths(output_path)
if len(output_images_paths) > 0:
@ -420,15 +420,15 @@ def extract_umd_csv(input_file_csv,
Path(filename).unlink()
else:
output_path.mkdir(parents=True, exist_ok=True)
try:
with open( str(input_file_csv_path), 'r') as f:
csv_file = f.read()
except Exception as e:
io.log_err("Unable to open or read file " + str(input_file_csv_path) + ": " + str(e) )
return
strings = csv_file.split('\n')
strings = csv_file.split('\n')
keys = strings[0].split(',')
keys_len = len(keys)
csv_data = []
@ -437,29 +437,29 @@ def extract_umd_csv(input_file_csv,
if keys_len != len(values):
io.log_err("Wrong string in csv file, skipping.")
continue
csv_data += [ { keys[n] : values[n] for n in range(keys_len) } ]
data = []
for d in csv_data:
filename = input_file_csv_root_path / d['FILE']
x,y,w,h = float(d['FACE_X']), float(d['FACE_Y']), float(d['FACE_WIDTH']), float(d['FACE_HEIGHT'])
data += [ ExtractSubprocessor.Data(filename=filename, rects=[ [x,y,x+w,y+h] ]) ]
images_found = len(data)
faces_detected = 0
if len(data) > 0:
io.log_info ("Performing 2nd pass from csv file...")
data = ExtractSubprocessor (data, 'landmarks', multi_gpu=multi_gpu, cpu_only=cpu_only).run()
io.log_info ('Performing 3rd pass...')
data = ExtractSubprocessor (data, 'final', image_size, face_type, None, multi_gpu=multi_gpu, cpu_only=cpu_only, manual=False, final_output_path=output_path).run()
faces_detected += sum([d.faces_detected for d in data])
io.log_info ('-------------------------')
io.log_info ('Images found: %d' % (images_found) )
io.log_info ('Faces detected: %d' % (faces_detected) )
@ -467,22 +467,21 @@ def extract_umd_csv(input_file_csv,
def dev_test(input_dir):
input_path = Path(input_dir)
dir_names = pathex.get_all_dir_names(input_path)
for dir_name in io.progress_bar_generator(dir_names, desc="Processing"):
img_paths = pathex.get_image_paths (input_path / dir_name)
for filename in img_paths:
filepath = Path(filename)
dflimg = DFLIMG.load (filepath)
if dflimg is None:
raise ValueError
dflimg.embed_and_set(filename, person_name=dir_name)
#import code
#code.interact(local=dict(globals(), **locals()))