mirror of
https://github.com/iperov/DeepFaceLive
synced 2025-07-07 05:22:08 -07:00
refactoring, FaceSwapper now can swap all faces
This commit is contained in:
parent
c0efaa1900
commit
6311a12c63
6 changed files with 119 additions and 84 deletions
|
@ -23,7 +23,7 @@ from .ui.QFrameAdjuster import QFrameAdjuster
|
|||
from .ui.QStreamOutput import QStreamOutput
|
||||
from .ui.widgets.QBCFaceAlignViewer import QBCFaceAlignViewer
|
||||
from .ui.widgets.QBCFaceSwapViewer import QBCFaceSwapViewer
|
||||
from .ui.widgets.QBCFinalFrameViewer import QBCFinalFrameViewer
|
||||
from .ui.widgets.QBCMergedFrameViewer import QBCMergedFrameViewer
|
||||
from .ui.widgets.QBCFrameViewer import QBCFrameViewer
|
||||
|
||||
|
||||
|
@ -77,7 +77,7 @@ class QLiveSwap(lib_qt.QXWidget):
|
|||
self.q_ds_frame_viewer = QBCFrameViewer(backed_weak_heap, multi_sources_bc_out)
|
||||
self.q_ds_fa_viewer = QBCFaceAlignViewer(backed_weak_heap, face_aligner_bc_out, preview_width=256)
|
||||
self.q_ds_fc_viewer = QBCFaceSwapViewer(backed_weak_heap, face_swapper_bc_out, preview_width=256)
|
||||
self.q_ds_merged_frame_viewer = QBCFinalFrameViewer(backed_weak_heap, face_merger_bc_out)
|
||||
self.q_ds_merged_frame_viewer = QBCMergedFrameViewer(backed_weak_heap, face_merger_bc_out)
|
||||
|
||||
q_nodes = lib_qt.QXWidget(size_policy=(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed),
|
||||
layout=lib_qt.QXHBoxLayout([
|
||||
|
|
|
@ -208,7 +208,7 @@ class FaceMergerWorker(BackendWorker):
|
|||
_cpu_interp = {'bilinear' : ImageProcessor.Interpolation.LINEAR,
|
||||
'bicubic' : ImageProcessor.Interpolation.CUBIC,
|
||||
'lanczos4' : ImageProcessor.Interpolation.LANCZOS4}
|
||||
def _merge_on_cpu(self, out_merged_frame, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height ):
|
||||
def _merge_on_cpu(self, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height, do_color_compression ):
|
||||
state = self.get_state()
|
||||
|
||||
interpolation = self._cpu_interp[state.interpolation]
|
||||
|
@ -247,11 +247,11 @@ class FaceMergerWorker(BackendWorker):
|
|||
opacity = np.float32(state.face_opacity)
|
||||
one_f = np.float32(1.0)
|
||||
if opacity == 1.0:
|
||||
ne.evaluate('frame_image*(one_f-frame_face_mask) + frame_face_swap_img*frame_face_mask', out=out_merged_frame)
|
||||
out_merged_frame = ne.evaluate('frame_image*(one_f-frame_face_mask) + frame_face_swap_img*frame_face_mask')
|
||||
else:
|
||||
ne.evaluate('frame_image*(one_f-frame_face_mask) + frame_image*frame_face_mask*(one_f-opacity) + frame_face_swap_img*frame_face_mask*opacity', out=out_merged_frame)
|
||||
out_merged_frame = ne.evaluate('frame_image*(one_f-frame_face_mask) + frame_image*frame_face_mask*(one_f-opacity) + frame_face_swap_img*frame_face_mask*opacity')
|
||||
|
||||
if state.color_compression != 0:
|
||||
if do_color_compression and state.color_compression != 0:
|
||||
color_compression = max(4, (127.0 - state.color_compression) )
|
||||
out_merged_frame *= color_compression
|
||||
np.floor(out_merged_frame, out=out_merged_frame)
|
||||
|
@ -266,7 +266,7 @@ class FaceMergerWorker(BackendWorker):
|
|||
|
||||
_n_mask_multiply_op_text = [ f"float X = {'*'.join([f'(((float)I{i}) / 255.0)' for i in range(n)])}; O = (X <= 0.5 ? 0 : 1);" for n in range(5) ]
|
||||
|
||||
def _merge_on_gpu(self, out_merged_frame, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height ):
|
||||
def _merge_on_gpu(self, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height, do_color_compression ):
|
||||
state = self.get_state()
|
||||
interpolation = self._gpu_interp[state.interpolation]
|
||||
|
||||
|
@ -294,21 +294,20 @@ class FaceMergerWorker(BackendWorker):
|
|||
frame_face_mask_t = lib_cl.remap_np_affine(face_mask_t, aligned_to_source_uni_mat, interpolation=lib_cl.EInterpolation.LINEAR, output_size=(frame_height, frame_width), post_op_text='O = (O <= (1.0/255.0) ? 0.0 : O > 1.0 ? 1.0 : O);' )
|
||||
frame_face_swap_img_t = lib_cl.remap_np_affine(face_swap_img_t, aligned_to_source_uni_mat, interpolation=interpolation, output_size=(frame_height, frame_width), post_op_text='O = clamp(O, 0.0, 1.0);' )
|
||||
|
||||
frame_image_t = lib_cl.Tensor.from_value(frame_image).transpose( (2,0,1) )
|
||||
frame_image_t = lib_cl.Tensor.from_value(frame_image).transpose( (2,0,1), op_text='O = ((float)I) / 255.0;' if frame_image.dtype == np.uint8 else None,
|
||||
dtype=np.float32 if frame_image.dtype == np.uint8 else None)
|
||||
|
||||
opacity = state.face_opacity
|
||||
if opacity == 1.0:
|
||||
frame_final_t = lib_cl.any_wise('float I0f = (((float)I0) / 255.0); O = I0f*(1.0-I1) + I2*I1', frame_image_t, frame_face_mask_t, frame_face_swap_img_t, dtype=np.float32)
|
||||
frame_final_t = lib_cl.any_wise('O = I0*(1.0-I1) + I2*I1', frame_image_t, frame_face_mask_t, frame_face_swap_img_t, dtype=np.float32)
|
||||
else:
|
||||
frame_final_t = lib_cl.any_wise('float I0f = (((float)I0) / 255.0); O = I0f*(1.0-I1) + I0f*I1*(1.0-I3) + I2*I1*I3', frame_image_t, frame_face_mask_t, frame_face_swap_img_t, np.float32(opacity), dtype=np.float32)
|
||||
frame_final_t = lib_cl.any_wise('O = I0*(1.0-I1) + I0*I1*(1.0-I3) + I2*I1*I3', frame_image_t, frame_face_mask_t, frame_face_swap_img_t, np.float32(opacity), dtype=np.float32)
|
||||
|
||||
color_compression = state.color_compression
|
||||
if color_compression != 0:
|
||||
color_compression = max(4, (127.0 - color_compression) )
|
||||
if do_color_compression and state.color_compression != 0:
|
||||
color_compression = max(4, (127.0 - state.color_compression) )
|
||||
frame_final_t = lib_cl.any_wise('O = ( floor(I0 * I1) / I1 ) + (2.0 / I1);', frame_final_t, np.float32(color_compression))
|
||||
|
||||
frame_final_t.transpose( (1,2,0) ).np(out=out_merged_frame)
|
||||
return out_merged_frame
|
||||
return frame_final_t.transpose( (1,2,0) ).np()
|
||||
|
||||
def on_tick(self):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
|
@ -321,41 +320,42 @@ class FaceMergerWorker(BackendWorker):
|
|||
bcd.assign_weak_heap(self.weak_heap)
|
||||
|
||||
frame_image_name = bcd.get_frame_image_name()
|
||||
frame_image = bcd.get_image(frame_image_name)
|
||||
merged_frame = bcd.get_image(frame_image_name)
|
||||
|
||||
if merged_frame is not None:
|
||||
fsi_list = bcd.get_face_swap_info_list()
|
||||
fsi_list_len = len(fsi_list)
|
||||
has_merged_faces = False
|
||||
for fsi_id, fsi in enumerate(fsi_list):
|
||||
image_to_align_uni_mat = fsi.image_to_align_uni_mat
|
||||
face_resolution = fsi.face_resolution
|
||||
|
||||
if frame_image is not None:
|
||||
for fsi in bcd.get_face_swap_info_list():
|
||||
face_align_img = bcd.get_image(fsi.face_align_image_name)
|
||||
face_align_lmrks_mask_img = bcd.get_image(fsi.face_align_lmrks_mask_name)
|
||||
face_align_mask_img = bcd.get_image(fsi.face_align_mask_name)
|
||||
face_swap_img = bcd.get_image(fsi.face_swap_image_name)
|
||||
face_swap_mask_img = bcd.get_image(fsi.face_swap_mask_name)
|
||||
image_to_align_uni_mat = fsi.image_to_align_uni_mat
|
||||
|
||||
face_resolution = fsi.face_resolution
|
||||
|
||||
if all_is_not_None(face_resolution, face_align_img, face_align_mask_img, face_swap_img, face_swap_mask_img, image_to_align_uni_mat):
|
||||
has_merged_faces = True
|
||||
face_height, face_width = face_align_img.shape[:2]
|
||||
frame_height, frame_width = frame_image.shape[:2]
|
||||
frame_height, frame_width = merged_frame.shape[:2]
|
||||
aligned_to_source_uni_mat = image_to_align_uni_mat.invert()
|
||||
aligned_to_source_uni_mat = aligned_to_source_uni_mat.source_translated(-state.face_x_offset, -state.face_y_offset)
|
||||
aligned_to_source_uni_mat = aligned_to_source_uni_mat.source_scaled_around_center(state.face_scale,state.face_scale)
|
||||
aligned_to_source_uni_mat = aligned_to_source_uni_mat.to_exact_mat (face_width, face_height, frame_width, frame_height)
|
||||
|
||||
out_merged_frame = self.out_merged_frame
|
||||
if out_merged_frame is None or out_merged_frame.shape[:2] != (frame_height, frame_width):
|
||||
out_merged_frame = self.out_merged_frame = np.empty_like(frame_image, np.float32)
|
||||
|
||||
do_color_compression = fsi_id == fsi_list_len-1
|
||||
if state.device == 'CPU':
|
||||
merged_frame = self._merge_on_cpu(out_merged_frame, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height )
|
||||
merged_frame = self._merge_on_cpu(merged_frame, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height, do_color_compression=do_color_compression )
|
||||
else:
|
||||
merged_frame = self._merge_on_gpu(out_merged_frame, frame_image, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height )
|
||||
merged_frame = self._merge_on_gpu(merged_frame, face_resolution, face_align_img, face_align_mask_img, face_align_lmrks_mask_img, face_swap_img, face_swap_mask_img, aligned_to_source_uni_mat, frame_width, frame_height, do_color_compression=do_color_compression )
|
||||
|
||||
if has_merged_faces:
|
||||
# keep image in float32 in order not to extra load FaceMerger
|
||||
merged_image_name = f'{frame_image_name}_merged'
|
||||
bcd.set_merged_image_name(merged_image_name)
|
||||
bcd.set_image(merged_image_name, merged_frame)
|
||||
break
|
||||
|
||||
self.stop_profile_timing()
|
||||
self.pending_bcd = bcd
|
||||
|
@ -425,3 +425,7 @@ class WorkerState(BackendWorkerState):
|
|||
interpolation = None
|
||||
color_compression : int = None
|
||||
face_opacity : float = None
|
||||
|
||||
# out_merged_frame = self.out_merged_frame
|
||||
# if out_merged_frame is None or out_merged_frame.shape[:2] != (frame_height, frame_width):
|
||||
# out_merged_frame = self.out_merged_frame = np.empty_like(frame_image, np.float32)
|
||||
|
|
|
@ -14,7 +14,9 @@ from .BackendBase import (BackendConnection, BackendDB, BackendHost,
|
|||
|
||||
|
||||
class FaceSwapper(BackendHost):
|
||||
def __init__(self, weak_heap : BackendWeakHeap, reemit_frame_signal : BackendSignal, bc_in : BackendConnection, bc_out : BackendConnection, dfm_models_path : Path, backend_db : BackendDB = None):
|
||||
def __init__(self, weak_heap : BackendWeakHeap, reemit_frame_signal : BackendSignal, bc_in : BackendConnection, bc_out : BackendConnection, dfm_models_path : Path, backend_db : BackendDB = None,
|
||||
id : int = 0):
|
||||
self._id = id
|
||||
super().__init__(backend_db=backend_db,
|
||||
sheet_cls=Sheet,
|
||||
worker_cls=FaceSwapperWorker,
|
||||
|
@ -23,6 +25,8 @@ class FaceSwapper(BackendHost):
|
|||
|
||||
def get_control_sheet(self) -> 'Sheet.Host': return super().get_control_sheet()
|
||||
|
||||
def _get_name(self):
|
||||
return super()._get_name()# + f'{self._id}'
|
||||
|
||||
class FaceSwapperWorker(BackendWorker):
|
||||
def get_state(self) -> 'WorkerState': return super().get_state()
|
||||
|
@ -46,6 +50,7 @@ class FaceSwapperWorker(BackendWorker):
|
|||
|
||||
cs.model.call_on_selected(self.on_cs_model_info)
|
||||
cs.device.call_on_selected(self.on_cs_device)
|
||||
cs.swap_all_faces.call_on_flag(self.on_cs_swap_all_faces)
|
||||
cs.face_id.call_on_number(self.on_cs_face_id)
|
||||
cs.morph_factor.call_on_number(self.on_cs_morph_factor)
|
||||
cs.presharpen_amount.call_on_number(self.on_cs_presharpen_amount)
|
||||
|
@ -83,11 +88,28 @@ class FaceSwapperWorker(BackendWorker):
|
|||
self.save_state()
|
||||
self.restart()
|
||||
|
||||
def on_cs_swap_all_faces(self, swap_all_faces):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
if model_state is not None:
|
||||
model_state.swap_all_faces = swap_all_faces
|
||||
|
||||
if not swap_all_faces:
|
||||
cs.face_id.enable()
|
||||
cs.face_id.set_config(lib_csw.Number.Config(min=0, max=999, step=1, decimals=0, allow_instant_update=True))
|
||||
cs.face_id.set_number(state.model_state.face_id if state.model_state.face_id is not None else 0)
|
||||
else:
|
||||
cs.face_id.disable()
|
||||
|
||||
self.save_state()
|
||||
self.reemit_frame_signal.send()
|
||||
|
||||
|
||||
def on_cs_face_id(self, face_id):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.face_id.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.face_id.get_config()
|
||||
face_id = model_state.face_id = int(np.clip(face_id, cfg.min, cfg.max))
|
||||
cs.face_id.set_number(face_id)
|
||||
self.save_state()
|
||||
|
@ -96,8 +118,8 @@ class FaceSwapperWorker(BackendWorker):
|
|||
def on_cs_presharpen_amount(self, presharpen_amount):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.presharpen_amount.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.presharpen_amount.get_config()
|
||||
presharpen_amount = model_state.presharpen_amount = float(np.clip(presharpen_amount, cfg.min, cfg.max))
|
||||
cs.presharpen_amount.set_number(presharpen_amount)
|
||||
self.save_state()
|
||||
|
@ -106,8 +128,8 @@ class FaceSwapperWorker(BackendWorker):
|
|||
def on_cs_morph_factor(self, morph_factor):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.morph_factor.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.morph_factor.get_config()
|
||||
morph_factor = model_state.morph_factor = float(np.clip(morph_factor, cfg.min, cfg.max))
|
||||
cs.morph_factor.set_number(morph_factor)
|
||||
self.save_state()
|
||||
|
@ -116,8 +138,8 @@ class FaceSwapperWorker(BackendWorker):
|
|||
def on_cs_gamma_red(self, pre_gamma_red):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.pre_gamma_red.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.pre_gamma_red.get_config()
|
||||
pre_gamma_red = model_state.pre_gamma_red = float(np.clip(pre_gamma_red, cfg.min, cfg.max))
|
||||
cs.pre_gamma_red.set_number(pre_gamma_red)
|
||||
self.save_state()
|
||||
|
@ -126,8 +148,8 @@ class FaceSwapperWorker(BackendWorker):
|
|||
def on_cs_pre_gamma_green(self, pre_gamma_green):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.pre_gamma_green.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.pre_gamma_green.get_config()
|
||||
pre_gamma_green = model_state.pre_gamma_green = float(np.clip(pre_gamma_green, cfg.min, cfg.max))
|
||||
cs.pre_gamma_green.set_number(pre_gamma_green)
|
||||
self.save_state()
|
||||
|
@ -136,8 +158,8 @@ class FaceSwapperWorker(BackendWorker):
|
|||
def on_cs_pre_gamma_blue(self, pre_gamma_blue):
|
||||
state, cs = self.get_state(), self.get_control_sheet()
|
||||
model_state = state.model_state
|
||||
cfg = cs.pre_gamma_blue.get_config()
|
||||
if model_state is not None:
|
||||
cfg = cs.pre_gamma_blue.get_config()
|
||||
pre_gamma_blue = model_state.pre_gamma_blue = float(np.clip(pre_gamma_blue, cfg.min, cfg.max))
|
||||
cs.pre_gamma_blue.set_number(pre_gamma_blue)
|
||||
self.save_state()
|
||||
|
@ -186,9 +208,9 @@ class FaceSwapperWorker(BackendWorker):
|
|||
'',
|
||||
f'@FaceSwapper.resolution',
|
||||
f'{model_width}x{model_height}']) )
|
||||
cs.face_id.enable()
|
||||
cs.face_id.set_config(lib_csw.Number.Config(min=0, max=16, step=1, decimals=0, allow_instant_update=True))
|
||||
cs.face_id.set_number(state.model_state.face_id if state.model_state.face_id is not None else 0)
|
||||
|
||||
cs.swap_all_faces.enable()
|
||||
cs.swap_all_faces.set_flag( state.model_state.swap_all_faces if state.model_state.swap_all_faces is not None else False)
|
||||
|
||||
if self.dfm_model.has_morph_value():
|
||||
cs.morph_factor.enable()
|
||||
|
@ -225,7 +247,6 @@ class FaceSwapperWorker(BackendWorker):
|
|||
if events.download_progress is not None:
|
||||
cs.model_dl_progress.set_progress(events.download_progress)
|
||||
|
||||
|
||||
if self.pending_bcd is None:
|
||||
self.start_profile_timing()
|
||||
|
||||
|
@ -236,10 +257,9 @@ class FaceSwapperWorker(BackendWorker):
|
|||
model_state = state.model_state
|
||||
dfm_model = self.dfm_model
|
||||
if all_is_not_None(dfm_model, model_state):
|
||||
face_id = model_state.face_id
|
||||
if face_id is not None:
|
||||
|
||||
for i, fsi in enumerate(bcd.get_face_swap_info_list()):
|
||||
if face_id != i:
|
||||
if not model_state.swap_all_faces and model_state.face_id != i:
|
||||
continue
|
||||
|
||||
face_align_image = bcd.get_image(fsi.face_align_image_name)
|
||||
|
@ -291,6 +311,7 @@ class Sheet:
|
|||
self.model_dl_progress = lib_csw.Progress.Client()
|
||||
self.model_dl_error = lib_csw.Error.Client()
|
||||
self.device = lib_csw.DynamicSingleSwitch.Client()
|
||||
self.swap_all_faces = lib_csw.Flag.Client()
|
||||
self.face_id = lib_csw.Number.Client()
|
||||
self.morph_factor = lib_csw.Number.Client()
|
||||
self.presharpen_amount = lib_csw.Number.Client()
|
||||
|
@ -307,6 +328,7 @@ class Sheet:
|
|||
self.model_dl_progress = lib_csw.Progress.Host()
|
||||
self.model_dl_error = lib_csw.Error.Host()
|
||||
self.device = lib_csw.DynamicSingleSwitch.Host()
|
||||
self.swap_all_faces = lib_csw.Flag.Host()
|
||||
self.face_id = lib_csw.Number.Host()
|
||||
self.morph_factor = lib_csw.Number.Host()
|
||||
self.presharpen_amount = lib_csw.Number.Host()
|
||||
|
@ -317,6 +339,7 @@ class Sheet:
|
|||
|
||||
class ModelState(BackendWorkerState):
|
||||
device = None
|
||||
swap_all_faces : bool = None
|
||||
face_id : int = None
|
||||
morph_factor : float = None
|
||||
presharpen_amount : float = None
|
||||
|
|
|
@ -39,6 +39,9 @@ class QFaceSwapper(QBackendPanel):
|
|||
q_device_label = QLabelPopupInfo(label=L('@QFaceSwapper.device'), popup_info_text=L('@QFaceSwapper.help.device') )
|
||||
q_device = QComboBoxCSWDynamicSingleSwitch(cs.device, reflect_state_widgets=[q_device_label])
|
||||
|
||||
q_swap_all_faces_label = QLabelPopupInfo(label=L('@QFaceSwapper.swap_all_faces') )
|
||||
q_swap_all_faces = QCheckBoxCSWFlag(cs.swap_all_faces, reflect_state_widgets=[q_swap_all_faces_label])
|
||||
|
||||
q_face_id_label = QLabelPopupInfo(label=L('@QFaceSwapper.face_id'), popup_info_text=L('@QFaceSwapper.help.face_id') )
|
||||
q_face_id = QSpinBoxCSWNumber(cs.face_id, reflect_state_widgets=[q_face_id_label])
|
||||
|
||||
|
@ -69,8 +72,8 @@ class QFaceSwapper(QBackendPanel):
|
|||
grid_l.addWidget(q_device_label, row, 0, alignment=Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter )
|
||||
grid_l.addWidget(q_device, row, 1, alignment=Qt.AlignmentFlag.AlignLeft )
|
||||
row += 1
|
||||
grid_l.addWidget(q_face_id_label, row, 0, alignment=Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter )
|
||||
grid_l.addWidget(q_face_id, row, 1, alignment=Qt.AlignmentFlag.AlignLeft )
|
||||
grid_l.addWidget( q_swap_all_faces_label, row, 0, alignment=Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter )
|
||||
grid_l.addLayout( lib_qt.QXHBoxLayout([q_swap_all_faces, 4, q_face_id_label, 4, q_face_id ]), row, 1, alignment=Qt.AlignmentFlag.AlignLeft )
|
||||
row += 1
|
||||
grid_l.addWidget(q_morph_factor_label, row, 0, alignment=Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter )
|
||||
grid_l.addWidget(q_morph_factor, row, 1)
|
||||
|
|
|
@ -10,7 +10,7 @@ from xlib import qt as lib_qt
|
|||
from ... import backend
|
||||
|
||||
|
||||
class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection):
|
||||
class QBCMergedFrameViewer(lib_qt.QXCollapsibleSection):
|
||||
def __init__(self, backed_weak_heap : backend.BackendWeakHeap,
|
||||
bc : backend.BackendConnection,
|
||||
preview_width=256):
|
||||
|
@ -27,7 +27,7 @@ class QBCFinalFrameViewer(lib_qt.QXCollapsibleSection):
|
|||
main_l = lib_qt.QXVBoxLayout([ (layered_images, Qt.AlignmentFlag.AlignCenter),
|
||||
(info_label, Qt.AlignmentFlag.AlignCenter),
|
||||
], spacing=0)
|
||||
super().__init__(title=L('@QBCFinalFrameViewer.title'), content_layout=main_l)
|
||||
super().__init__(title=L('@QBCMergedFrameViewer.title'), content_layout=main_l)
|
||||
|
||||
def _on_timer_16ms(self):
|
||||
top_qx = self.get_top_QXWindow()
|
|
@ -427,6 +427,11 @@ class Localization:
|
|||
'ru-RU' : 'Настройте комбинации устройств модулей для достижения высоких кадр/сек либо снижения нагрузки на процессор.',
|
||||
'zh-CN' : '调整模块设备的组合以实现更高的fps或更低的CPU使用率'},
|
||||
|
||||
'QFaceSwapper.swap_all_faces':{
|
||||
'en-US' : 'Swap all faces',
|
||||
'ru-RU' : 'Заменить все лица',
|
||||
'zh-CN' : '改变所有面孔'},
|
||||
|
||||
'QFaceSwapper.face_id':{
|
||||
'en-US' : 'Face ID',
|
||||
'ru-RU' : 'Номер лица',
|
||||
|
@ -652,10 +657,10 @@ class Localization:
|
|||
'ru-RU' : 'Заменённое лицо',
|
||||
'zh-CN' : '换后的脸'},
|
||||
|
||||
'QBCFinalFrameViewer.title':{
|
||||
'en-US' : 'Final frame',
|
||||
'ru-RU' : 'Финальный кадр',
|
||||
'zh-CN' : '结果'},
|
||||
'QBCMergedFrameViewer.title':{
|
||||
'en-US' : 'Merged frame',
|
||||
'ru-RU' : 'Склеенный кадр',
|
||||
'zh-CN' : '合成后的画面'},
|
||||
|
||||
'FileSource.image_folder':{
|
||||
'en-US' : 'Image folder',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue