mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-08-14 02:37:00 -07:00
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:
parent
a3dfcb91b9
commit
76ca79216e
49 changed files with 1320 additions and 1297 deletions
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()))
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue