This commit is contained in:
Colombo 2020-01-22 22:14:31 +04:00
parent 869c5e8dd0
commit f1a3150ce9
6 changed files with 75 additions and 50 deletions

View File

@ -67,12 +67,16 @@ DeepFaceLab is used by such popular youtube channels as
||bitcoin:31mPd6DxPCzbpCMZk4k1koWAbErSyqkAXr|| ||bitcoin:31mPd6DxPCzbpCMZk4k1koWAbErSyqkAXr||
|||| ||||
|Collect facesets|You can collect faceset of any celebrity that can be used in DeepFaceLab and share it [in the community](https://mrdeepfakes.com/forums/forum-celebrity-facesets)| |Collect facesets|You can collect faceset of any celebrity that can be used in DeepFaceLab and share it [in the community](https://mrdeepfakes.com/forums/forum-celebrity-facesets)|
</td></tr>
<tr><td align="center" width="9999"> <tr><td align="center" width="9999">
## Meme zone ## Meme zone
<p align="center"><img src="doc/DeepFaceLab is working.png"></p> <p align="center"><img src="doc/DeepFaceLab is working.png"></p>
</td></tr>
<tr><td align="center" width="9999">
<sub>#deepfacelab #deepfakes #faceswap #face-swap #deep-learning #deeplearning #deep-neural-networks #deepface #deep-face-swap #fakeapp #fake-app #neural-networks #neural-nets</sub> <sub>#deepfacelab #deepfakes #faceswap #face-swap #deep-learning #deeplearning #deep-neural-networks #deepface #deep-face-swap #fakeapp #fake-app #neural-networks #neural-nets</sub>
</td></tr> </td></tr>

View File

@ -367,6 +367,7 @@ class InteractBase(object):
def input_in_time (self, str, max_time_sec): def input_in_time (self, str, max_time_sec):
sq = multiprocessing.Queue() sq = multiprocessing.Queue()
p = multiprocessing.Process(target=self.input_process, args=( sys.stdin.fileno(), sq, str)) p = multiprocessing.Process(target=self.input_process, args=( sys.stdin.fileno(), sq, str))
p.daemon = True
p.start() p.start()
t = time.time() t = time.time()
inp = False inp = False
@ -380,6 +381,25 @@ class InteractBase(object):
sys.stdin = os.fdopen( sys.stdin.fileno() ) sys.stdin = os.fdopen( sys.stdin.fileno() )
return inp return inp
def input_process_skip_pending(self, stdin_fd):
sys.stdin = os.fdopen(stdin_fd)
while True:
try:
if sys.stdin.isatty():
sys.stdin.read()
except:
pass
def input_skip_pending(self):
"""
skips unnecessary inputs between the dialogs
"""
p = multiprocessing.Process(target=self.input_process_skip_pending, args=( sys.stdin.fileno(), ))
p.daemon = True
p.start()
time.sleep(0.5)
p.terminate()
sys.stdin = os.fdopen( sys.stdin.fileno() )
class InteractDesktop(InteractBase): class InteractDesktop(InteractBase):

View File

@ -38,7 +38,7 @@ class MergeSubprocessor(Subprocessor):
self.prev_temporal_frame_infos = prev_temporal_frame_infos self.prev_temporal_frame_infos = prev_temporal_frame_infos
self.frame_info = frame_info self.frame_info = frame_info
self.next_temporal_frame_infos = next_temporal_frame_infos self.next_temporal_frame_infos = next_temporal_frame_infos
self.output_filename = None self.output_filepath = None
self.idx = None self.idx = None
self.cfg = None self.cfg = None
@ -53,14 +53,14 @@ class MergeSubprocessor(Subprocessor):
prev_temporal_frame_infos=None, prev_temporal_frame_infos=None,
frame_info=None, frame_info=None,
next_temporal_frame_infos=None, next_temporal_frame_infos=None,
output_filename=None, output_filepath=None,
need_return_image = False): need_return_image = False):
self.idx = idx self.idx = idx
self.cfg = cfg self.cfg = cfg
self.prev_temporal_frame_infos = prev_temporal_frame_infos self.prev_temporal_frame_infos = prev_temporal_frame_infos
self.frame_info = frame_info self.frame_info = frame_info
self.next_temporal_frame_infos = next_temporal_frame_infos self.next_temporal_frame_infos = next_temporal_frame_infos
self.output_filename = output_filename self.output_filepath = output_filepath
self.need_return_image = need_return_image self.need_return_image = need_return_image
if self.need_return_image: if self.need_return_image:
@ -124,34 +124,33 @@ class MergeSubprocessor(Subprocessor):
frame_info = pf.frame_info frame_info = pf.frame_info
filename = frame_info.filename filepath = frame_info.filepath
landmarks_list = frame_info.landmarks_list landmarks_list = frame_info.landmarks_list
filename_path = Path(filename) output_filepath = pf.output_filepath
output_filename = pf.output_filename
need_return_image = pf.need_return_image need_return_image = pf.need_return_image
if len(landmarks_list) == 0: if len(landmarks_list) == 0:
self.log_info ( 'no faces found for %s, copying without faces' % (filename_path.name) ) self.log_info ( 'no faces found for %s, copying without faces' % (filepath.name) )
if cfg.export_mask_alpha: if cfg.export_mask_alpha:
img_bgr = cv2_imread(filename) img_bgr = cv2_imread(filepath)
h,w,c = img_bgr.shape h,w,c = img_bgr.shape
if c == 1: if c == 1:
img_bgr = np.repeat(img_bgr, 3, -1) img_bgr = np.repeat(img_bgr, 3, -1)
if c == 3: if c == 3:
img_bgr = np.concatenate ([img_bgr, np.zeros((h,w,1), dtype=img_bgr.dtype) ], axis=-1) img_bgr = np.concatenate ([img_bgr, np.zeros((h,w,1), dtype=img_bgr.dtype) ], axis=-1)
cv2_imwrite (output_filename, img_bgr) cv2_imwrite (output_filepath, img_bgr)
else: else:
if filename_path.suffix == '.png': if filepath.suffix == '.png':
shutil.copy (filename, output_filename ) shutil.copy ( str(filepath), str(output_filepath) )
else: else:
img_bgr = cv2_imread(filename) img_bgr = cv2_imread(filepath)
cv2_imwrite (output_filename, img_bgr) cv2_imwrite (output_filepath, img_bgr)
if need_return_image: if need_return_image:
img_bgr = cv2_imread(filename) img_bgr = cv2_imread(filepath)
pf.image = img_bgr pf.image = img_bgr
else: else:
if cfg.type == MergerConfig.TYPE_MASKED: if cfg.type == MergerConfig.TYPE_MASKED:
@ -165,7 +164,7 @@ class MergeSubprocessor(Subprocessor):
if 'MemoryError' in e_str: if 'MemoryError' in e_str:
raise Subprocessor.SilenceException raise Subprocessor.SilenceException
else: else:
raise Exception( 'Error while merging file [%s]: %s' % (filename, e_str) ) raise Exception( f'Error while merging file [{filepath}]: {e_str}' )
elif cfg.type == MergerConfig.TYPE_FACE_AVATAR: elif cfg.type == MergerConfig.TYPE_FACE_AVATAR:
final_img = MergeFaceAvatar (self.predictor_func, self.predictor_input_shape, final_img = MergeFaceAvatar (self.predictor_func, self.predictor_input_shape,
@ -173,8 +172,8 @@ class MergeSubprocessor(Subprocessor):
pf.frame_info, pf.frame_info,
pf.next_temporal_frame_infos ) pf.next_temporal_frame_infos )
if output_filename is not None and final_img is not None: if output_filepath is not None and final_img is not None:
cv2_imwrite (output_filename, final_img ) cv2_imwrite (output_filepath, final_img )
if need_return_image: if need_return_image:
pf.image = final_img pf.image = final_img
@ -184,10 +183,10 @@ class MergeSubprocessor(Subprocessor):
#overridable #overridable
def get_data_name (self, pf): def get_data_name (self, pf):
#return string identificator of your data #return string identificator of your data
return pf.frame_info.filename return pf.frame_info.filepath
#override #override
def __init__(self, is_interactive, merger_session_filepath, predictor_func, predictor_input_shape, merger_config, frames, output_path, model_iter): def __init__(self, is_interactive, merger_session_filepath, predictor_func, predictor_input_shape, merger_config, frames, frames_root_path, output_path, model_iter):
if len (frames) == 0: if len (frames) == 0:
raise ValueError ("len (frames) == 0") raise ValueError ("len (frames) == 0")
@ -225,6 +224,7 @@ class MergeSubprocessor(Subprocessor):
self.fanseg_host, self.fanseg_extract_func = SubprocessFunctionCaller.make_pair(fanseg_extract_func) self.fanseg_host, self.fanseg_extract_func = SubprocessFunctionCaller.make_pair(fanseg_extract_func)
self.frames_root_path = frames_root_path
self.output_path = output_path self.output_path = output_path
self.model_iter = model_iter self.model_iter = model_iter
@ -232,11 +232,12 @@ class MergeSubprocessor(Subprocessor):
session_data = None session_data = None
if self.is_interactive and self.merger_session_filepath.exists(): if self.is_interactive and self.merger_session_filepath.exists():
io.input_skip_pending()
if io.input_bool ("Use saved session?", True): if io.input_bool ("Use saved session?", True):
try: try:
with open( str(self.merger_session_filepath), "rb") as f: with open( str(self.merger_session_filepath), "rb") as f:
session_data = pickle.loads(f.read()) session_data = pickle.loads(f.read())
except Exception as e: except Exception as e:
pass pass
@ -245,6 +246,7 @@ class MergeSubprocessor(Subprocessor):
self.frames_done_idxs = [] self.frames_done_idxs = []
if self.is_interactive and session_data is not None: if self.is_interactive and session_data is not None:
# Loaded session data, check it
s_frames = session_data.get('frames', None) s_frames = session_data.get('frames', None)
s_frames_idxs = session_data.get('frames_idxs', None) s_frames_idxs = session_data.get('frames_idxs', None)
s_frames_done_idxs = session_data.get('frames_done_idxs', None) s_frames_done_idxs = session_data.get('frames_done_idxs', None)
@ -254,13 +256,14 @@ class MergeSubprocessor(Subprocessor):
(s_frames_idxs is not None) and \ (s_frames_idxs is not None) and \
(s_frames_done_idxs is not None) and \ (s_frames_done_idxs is not None) and \
(s_model_iter is not None) and \ (s_model_iter is not None) and \
(len(frames) == len(s_frames)) (len(frames) == len(s_frames)) # frames count must match
if frames_equal: if frames_equal:
for i in range(len(frames)): for i in range(len(frames)):
frame = frames[i] frame = frames[i]
s_frame = s_frames[i] s_frame = s_frames[i]
if frame.frame_info.filename != s_frame.frame_info.filename: # frames filenames must match
if frame.frame_info.filepath.name != s_frame.frame_info.filepath.name:
frames_equal = False frames_equal = False
if not frames_equal: if not frames_equal:
break break
@ -270,25 +273,23 @@ class MergeSubprocessor(Subprocessor):
for frame in s_frames: for frame in s_frames:
if frame.cfg is not None: if frame.cfg is not None:
#recreate MergerConfig class using constructor with get_config() as dict params # recreate MergerConfig class using constructor with get_config() as dict params
#so if any new param will be added, old merger session will work properly # so if any new param will be added, old merger session will work properly
frame.cfg = frame.cfg.__class__( **frame.cfg.get_config() ) frame.cfg = frame.cfg.__class__( **frame.cfg.get_config() )
self.frames = s_frames self.frames = s_frames
self.frames_idxs = s_frames_idxs self.frames_idxs = s_frames_idxs
self.frames_done_idxs = s_frames_done_idxs 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 is more trained, recompute all frames # model was more trained, recompute all frames
rewind_to_begin = True
for frame in self.frames: for frame in self.frames:
frame.is_done = False frame.is_done = False
if self.model_iter != s_model_iter or \ if rewind_to_begin:
len(self.frames_idxs) == 0:
#rewind to begin if model is more trained or all frames are done
while len(self.frames_done_idxs) > 0: while len(self.frames_done_idxs) > 0:
prev_frame = self.frames[self.frames_done_idxs.pop()] prev_frame = self.frames[self.frames_done_idxs.pop()]
self.frames_idxs.insert(0, prev_frame.idx) self.frames_idxs.insert(0, prev_frame.idx)
@ -309,9 +310,7 @@ class MergeSubprocessor(Subprocessor):
for i in range( len(self.frames) ): for i in range( len(self.frames) ):
frame = self.frames[i] frame = self.frames[i]
frame.idx = i frame.idx = i
frame.output_filename = self.output_path / ( Path(frame.frame_info.filename).stem + '.png' ) frame.output_filepath = self.output_path / ( frame.frame_info.filepath.stem + '.png' )
#override #override
def process_info_generator(self): def process_info_generator(self):
@ -330,7 +329,7 @@ class MergeSubprocessor(Subprocessor):
#overridable optional #overridable optional
def on_clients_initialized(self): def on_clients_initialized(self):
io.progress_bar ("Merging", len (self.frames_idxs), initial=len(self.frames_done_idxs) ) io.progress_bar ("Merging", len(self.frames_idxs)+len(self.frames_done_idxs), initial=len(self.frames_done_idxs) )
self.process_remain_frames = not self.is_interactive self.process_remain_frames = not self.is_interactive
self.is_interactive_quitting = not self.is_interactive self.is_interactive_quitting = not self.is_interactive
@ -393,7 +392,7 @@ class MergeSubprocessor(Subprocessor):
self.screen_manager.finalize() self.screen_manager.finalize()
for frame in self.frames: for frame in self.frames:
frame.output_filename = None frame.output_filepath = None
frame.image = None frame.image = None
session_data = { session_data = {
@ -433,10 +432,10 @@ class MergeSubprocessor(Subprocessor):
if not cur_frame.is_shown: if not cur_frame.is_shown:
if cur_frame.is_done: if cur_frame.is_done:
cur_frame.is_shown = True cur_frame.is_shown = True
io.log_info (cur_frame.cfg.to_string( cur_frame.frame_info.filename_short) ) io.log_info (cur_frame.cfg.to_string( cur_frame.frame_info.filepath.name) )
if cur_frame.image is None: if cur_frame.image is None:
cur_frame.image = cv2_imread ( cur_frame.output_filename) cur_frame.image = cv2_imread ( cur_frame.output_filepath)
if cur_frame.image is None: if cur_frame.image is None:
# unable to read? recompute then # unable to read? recompute then
cur_frame.is_done = False cur_frame.is_done = False
@ -474,7 +473,7 @@ class MergeSubprocessor(Subprocessor):
self.masked_keys_funcs[chr_key](cfg, shift_pressed) self.masked_keys_funcs[chr_key](cfg, shift_pressed)
if prev_cfg != cfg: if prev_cfg != cfg:
io.log_info ( cfg.to_string(cur_frame.frame_info.filename_short) ) io.log_info ( cfg.to_string(cur_frame.frame_info.filepath.name) )
cur_frame.is_done = False cur_frame.is_done = False
cur_frame.is_shown = False cur_frame.is_shown = False
else: else:
@ -607,7 +606,7 @@ class MergeSubprocessor(Subprocessor):
prev_temporal_frame_infos=frame.prev_temporal_frame_infos, prev_temporal_frame_infos=frame.prev_temporal_frame_infos,
frame_info=frame.frame_info, frame_info=frame.frame_info,
next_temporal_frame_infos=frame.next_temporal_frame_infos, next_temporal_frame_infos=frame.next_temporal_frame_infos,
output_filename=frame.output_filename, output_filepath=frame.output_filepath,
need_return_image=True ) need_return_image=True )
return None return None
@ -705,7 +704,7 @@ def main (model_class_name=None,
if multiple_faces_detected: if multiple_faces_detected:
io.log_info ("Warning: multiple faces detected. Strongly recommended to process them separately.") io.log_info ("Warning: multiple faces detected. Strongly recommended to process them separately.")
frames = [ MergeSubprocessor.Frame( frame_info=FrameInfo(filename=p, landmarks_list=alignments.get(Path(p).stem, None))) for p in input_path_image_paths ] frames = [ MergeSubprocessor.Frame( frame_info=FrameInfo(filepath=Path(p), landmarks_list=alignments.get(Path(p).stem, None))) for p in input_path_image_paths ]
if multiple_faces_detected: if multiple_faces_detected:
io.log_info ("Warning: multiple faces detected. Motion blur will not be used.") io.log_info ("Warning: multiple faces detected. Motion blur will not be used.")
@ -750,9 +749,9 @@ def main (model_class_name=None,
if dflimg is None: if dflimg is None:
io.log_err ("%s is not a dfl image file" % (filepath.name) ) io.log_err ("%s is not a dfl image file" % (filepath.name) )
continue continue
filesdata += [ ( FrameInfo(filename=str(filepath), landmarks_list=[dflimg.get_landmarks()] ), dflimg.get_source_filename() ) ] filesdata += [ ( FrameInfo(filepath=filepath, landmarks_list=[dflimg.get_landmarks()] ), dflimg.get_source_filename() ) ]
filesdata = sorted(filesdata, key=operator.itemgetter(1)) #sort by filename filesdata = sorted(filesdata, key=operator.itemgetter(1)) #sort by source_filename
frames = [] frames = []
filesdata_len = len(filesdata) filesdata_len = len(filesdata)
for i in range(len(filesdata)): for i in range(len(filesdata)):
@ -776,12 +775,13 @@ def main (model_class_name=None,
io.log_info ("No frames to merge in input_dir.") io.log_info ("No frames to merge in input_dir.")
else: else:
MergeSubprocessor ( MergeSubprocessor (
is_interactive = is_interactive, is_interactive = is_interactive,
merger_session_filepath = merger_session_filepath, merger_session_filepath = merger_session_filepath,
predictor_func = predictor_func, predictor_func = predictor_func,
predictor_input_shape = predictor_input_shape, predictor_input_shape = predictor_input_shape,
merger_config = cfg, merger_config = cfg,
frames = frames, frames = frames,
frames_root_path = input_path,
output_path = output_path, output_path = output_path,
model_iter = model.get_iter() model_iter = model.get_iter()
).run() ).run()

View File

@ -1,9 +1,8 @@
from pathlib import Path from pathlib import Path
class FrameInfo(object): class FrameInfo(object):
def __init__(self, filename=None, landmarks_list=None): def __init__(self, filepath=None, landmarks_list=None):
self.filename = filename self.filepath = filepath
self.filename_short = str(Path(filename).name)
self.landmarks_list = landmarks_list or [] self.landmarks_list = landmarks_list or []
self.motion_deg = 0 self.motion_deg = 0
self.motion_power = 0 self.motion_power = 0

View File

@ -334,7 +334,7 @@ def MergeMaskedFace (predictor_func, predictor_input_shape, cfg, frame_info, img
def MergeMasked (predictor_func, predictor_input_shape, cfg, frame_info): def MergeMasked (predictor_func, predictor_input_shape, cfg, frame_info):
img_bgr_uint8 = cv2_imread(frame_info.filename) img_bgr_uint8 = cv2_imread(frame_info.filepath)
img_bgr_uint8 = imagelib.normalize_channels (img_bgr_uint8, 3) img_bgr_uint8 = imagelib.normalize_channels (img_bgr_uint8, 3)
img_bgr = img_bgr_uint8.astype(np.float32) / 255.0 img_bgr = img_bgr_uint8.astype(np.float32) / 255.0

View File

@ -158,6 +158,8 @@ class ModelBase(object):
self.batch_size = self.load_or_def_option('batch_size', 1) self.batch_size = self.load_or_def_option('batch_size', 1)
##### #####
io.input_skip_pending()
self.on_initialize_options() self.on_initialize_options()
if self.is_first_run(): if self.is_first_run():
# save as default options only for first run model initialize # save as default options only for first run model initialize