Refactor application structure.

pull/800/head
cattodotpy 2024-11-20 22:53:20 +08:00
parent 6171141505
commit b7d9889565
7 changed files with 1076 additions and 1102 deletions

View File

@ -17,7 +17,7 @@ import tensorflow
import modules.globals import modules.globals
import modules.metadata import modules.metadata
import modules.ui as ui from modules.ui import DeepFakeUI
from modules.processors.frame.core import get_frame_processors_modules from modules.processors.frame.core import get_frame_processors_modules
from modules.utilities import has_image_extension, is_image, is_video, detect_fps, create_video, extract_frames, get_temp_frame_paths, restore_audio, create_temp, move_temp, clean_temp, normalize_output_path from modules.utilities import has_image_extension, is_image, is_video, detect_fps, create_video, extract_frames, get_temp_frame_paths, restore_audio, create_temp, move_temp, clean_temp, normalize_output_path
@ -27,9 +27,148 @@ if 'ROCMExecutionProvider' in modules.globals.execution_providers:
warnings.filterwarnings('ignore', category=FutureWarning, module='insightface') warnings.filterwarnings('ignore', category=FutureWarning, module='insightface')
warnings.filterwarnings('ignore', category=UserWarning, module='torchvision') warnings.filterwarnings('ignore', category=UserWarning, module='torchvision')
def encode_execution_providers(execution_providers: List[str]) -> List[str]:
return [execution_provider.replace('ExecutionProvider', '').lower() for execution_provider in execution_providers]
def parse_args() -> None:
signal.signal(signal.SIGINT, lambda signal_number, frame: destroy()) def decode_execution_providers(execution_providers: List[str]) -> List[str]:
return [provider for provider, encoded_execution_provider in zip(onnxruntime.get_available_providers(), encode_execution_providers(onnxruntime.get_available_providers()))
if any(execution_provider in encoded_execution_provider for execution_provider in execution_providers)]
def suggest_max_memory() -> int:
if platform.system().lower() == 'darwin':
return 4
return 16
def suggest_execution_providers() -> List[str]:
return encode_execution_providers(onnxruntime.get_available_providers())
def suggest_execution_threads() -> int:
if 'DmlExecutionProvider' in modules.globals.execution_providers:
return 1
if 'ROCMExecutionProvider' in modules.globals.execution_providers:
return 1
return 8
def limit_resources() -> None:
# prevent tensorflow memory leak
gpus = tensorflow.config.experimental.list_physical_devices('GPU')
for gpu in gpus:
tensorflow.config.experimental.set_memory_growth(gpu, True)
# limit memory usage
if modules.globals.max_memory:
memory = modules.globals.max_memory * 1024 ** 3
if platform.system().lower() == 'darwin':
memory = modules.globals.max_memory * 1024 ** 6
if platform.system().lower() == 'windows':
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetProcessWorkingSetSize(-1, ctypes.c_size_t(memory), ctypes.c_size_t(memory))
else:
import resource
resource.setrlimit(resource.RLIMIT_DATA, (memory, memory))
def release_resources() -> None:
if 'CUDAExecutionProvider' in modules.globals.execution_providers:
torch.cuda.empty_cache()
class DeepFakeApp:
def __init__(self):
self.ui = DeepFakeUI(
self.start,
self.destroy
)
def update_status(self, message: str, scope: str = 'DLC.CORE') -> None:
print(f'[{scope}] {message}')
if not modules.globals.headless:
self.ui.update_status(message)
def pre_check(self) -> bool:
if sys.version_info < (3, 9):
update_status('Python version is not supported - please upgrade to 3.9 or higher.')
return False
if not shutil.which('ffmpeg'):
self.update_status('ffmpeg is not installed.')
return False
return True
def start(self) -> None:
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
if not frame_processor.pre_start():
return
self.update_status('Processing...')
# process image to image
if has_image_extension(modules.globals.target_path):
if modules.globals.nsfw_filter and self.ui.check_and_ignore_nsfw(modules.globals.target_path, self.destroy):
return
try:
shutil.copy2(modules.globals.target_path, modules.globals.output_path)
except Exception as e:
print("Error copying file:", str(e))
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
self.update_status('Progressing...', frame_processor.NAME)
frame_processor.process_image(modules.globals.source_path, modules.globals.output_path, modules.globals.output_path)
release_resources()
if is_image(modules.globals.target_path):
self.update_status('Processing to image succeed!')
else:
self.update_status('Processing to image failed!')
return
# process image to videos
if modules.globals.nsfw_filter and self.ui.check_and_ignore_nsfw(modules.globals.target_path, self.destroy):
return
if not modules.globals.map_faces:
self.update_status('Creating temp resources...')
create_temp(modules.globals.target_path)
self.update_status('Extracting frames...')
extract_frames(modules.globals.target_path)
temp_frame_paths = get_temp_frame_paths(modules.globals.target_path)
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
self.update_status('Progressing...', frame_processor.NAME)
frame_processor.process_video(modules.globals.source_path, temp_frame_paths)
release_resources()
# handles fps
if modules.globals.keep_fps:
self.update_status('Detecting fps...')
fps = detect_fps(modules.globals.target_path)
self.update_status(f'Creating video with {fps} fps...')
create_video(modules.globals.target_path, fps)
else:
self.update_status('Creating video with 30.0 fps...')
create_video(modules.globals.target_path)
# handle audio
if modules.globals.keep_audio:
if modules.globals.keep_fps:
self.update_status('Restoring audio...')
else:
self.update_status('Restoring audio might cause issues as fps are not kept...')
restore_audio(modules.globals.target_path, modules.globals.output_path)
else:
move_temp(modules.globals.target_path, modules.globals.output_path)
# clean and validate
clean_temp(modules.globals.target_path)
if is_video(modules.globals.target_path):
self.update_status('Processing to video succeed!')
else:
self.update_status('Processing to video failed!')
def destroy(self, to_quit=True) -> None:
if modules.globals.target_path:
clean_temp(modules.globals.target_path)
if to_quit:
sys.exit(0)
def parse_args(self) -> None:
signal.signal(signal.SIGINT, lambda _: self.destroy())
program = argparse.ArgumentParser() program = argparse.ArgumentParser()
program.add_argument('-s', '--source', help='select an source image', dest='source_path') program.add_argument('-s', '--source', help='select an source image', dest='source_path')
program.add_argument('-t', '--target', help='select an target image or video', dest='target_path') program.add_argument('-t', '--target', help='select an target image or video', dest='target_path')
@ -105,151 +244,16 @@ def parse_args() -> None:
modules.globals.execution_threads = args.gpu_threads_deprecated modules.globals.execution_threads = args.gpu_threads_deprecated
def encode_execution_providers(execution_providers: List[str]) -> List[str]: def run(self) -> None:
return [execution_provider.replace('ExecutionProvider', '').lower() for execution_provider in execution_providers] self.parse_args()
if not self.pre_check():
def decode_execution_providers(execution_providers: List[str]) -> List[str]:
return [provider for provider, encoded_execution_provider in zip(onnxruntime.get_available_providers(), encode_execution_providers(onnxruntime.get_available_providers()))
if any(execution_provider in encoded_execution_provider for execution_provider in execution_providers)]
def suggest_max_memory() -> int:
if platform.system().lower() == 'darwin':
return 4
return 16
def suggest_execution_providers() -> List[str]:
return encode_execution_providers(onnxruntime.get_available_providers())
def suggest_execution_threads() -> int:
if 'DmlExecutionProvider' in modules.globals.execution_providers:
return 1
if 'ROCMExecutionProvider' in modules.globals.execution_providers:
return 1
return 8
def limit_resources() -> None:
# prevent tensorflow memory leak
gpus = tensorflow.config.experimental.list_physical_devices('GPU')
for gpu in gpus:
tensorflow.config.experimental.set_memory_growth(gpu, True)
# limit memory usage
if modules.globals.max_memory:
memory = modules.globals.max_memory * 1024 ** 3
if platform.system().lower() == 'darwin':
memory = modules.globals.max_memory * 1024 ** 6
if platform.system().lower() == 'windows':
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetProcessWorkingSetSize(-1, ctypes.c_size_t(memory), ctypes.c_size_t(memory))
else:
import resource
resource.setrlimit(resource.RLIMIT_DATA, (memory, memory))
def release_resources() -> None:
if 'CUDAExecutionProvider' in modules.globals.execution_providers:
torch.cuda.empty_cache()
def pre_check() -> bool:
if sys.version_info < (3, 9):
update_status('Python version is not supported - please upgrade to 3.9 or higher.')
return False
if not shutil.which('ffmpeg'):
update_status('ffmpeg is not installed.')
return False
return True
def update_status(message: str, scope: str = 'DLC.CORE') -> None:
print(f'[{scope}] {message}')
if not modules.globals.headless:
ui.update_status(message)
def start() -> None:
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
if not frame_processor.pre_start():
return
update_status('Processing...')
# process image to image
if has_image_extension(modules.globals.target_path):
if modules.globals.nsfw_filter and ui.check_and_ignore_nsfw(modules.globals.target_path, destroy):
return
try:
shutil.copy2(modules.globals.target_path, modules.globals.output_path)
except Exception as e:
print("Error copying file:", str(e))
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME)
frame_processor.process_image(modules.globals.source_path, modules.globals.output_path, modules.globals.output_path)
release_resources()
if is_image(modules.globals.target_path):
update_status('Processing to image succeed!')
else:
update_status('Processing to image failed!')
return
# process image to videos
if modules.globals.nsfw_filter and ui.check_and_ignore_nsfw(modules.globals.target_path, destroy):
return
if not modules.globals.map_faces:
update_status('Creating temp resources...')
create_temp(modules.globals.target_path)
update_status('Extracting frames...')
extract_frames(modules.globals.target_path)
temp_frame_paths = get_temp_frame_paths(modules.globals.target_path)
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME)
frame_processor.process_video(modules.globals.source_path, temp_frame_paths)
release_resources()
# handles fps
if modules.globals.keep_fps:
update_status('Detecting fps...')
fps = detect_fps(modules.globals.target_path)
update_status(f'Creating video with {fps} fps...')
create_video(modules.globals.target_path, fps)
else:
update_status('Creating video with 30.0 fps...')
create_video(modules.globals.target_path)
# handle audio
if modules.globals.keep_audio:
if modules.globals.keep_fps:
update_status('Restoring audio...')
else:
update_status('Restoring audio might cause issues as fps are not kept...')
restore_audio(modules.globals.target_path, modules.globals.output_path)
else:
move_temp(modules.globals.target_path, modules.globals.output_path)
# clean and validate
clean_temp(modules.globals.target_path)
if is_video(modules.globals.target_path):
update_status('Processing to video succeed!')
else:
update_status('Processing to video failed!')
def destroy(to_quit=True) -> None:
if modules.globals.target_path:
clean_temp(modules.globals.target_path)
if to_quit: quit()
def run() -> None:
parse_args()
if not pre_check():
return return
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors): for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
if not frame_processor.pre_check(): if not frame_processor.pre_check():
return return
limit_resources() limit_resources()
if modules.globals.headless: if modules.globals.headless:
start() self.start()
else: else:
window = ui.init(start, destroy) self.ui.root.mainloop()
window.mainloop()

View File

@ -19,14 +19,10 @@ FRAME_PROCESSORS_INTERFACE = [
def load_frame_processor_module(frame_processor: str) -> Any: def load_frame_processor_module(frame_processor: str) -> Any:
try:
frame_processor_module = importlib.import_module(f'modules.processors.frame.{frame_processor}') frame_processor_module = importlib.import_module(f'modules.processors.frame.{frame_processor}')
for method_name in FRAME_PROCESSORS_INTERFACE: for method_name in FRAME_PROCESSORS_INTERFACE:
if not hasattr(frame_processor_module, method_name): if not hasattr(frame_processor_module, method_name):
sys.exit() sys.exit()
except ImportError:
print(f"Frame processor {frame_processor} not found")
sys.exit()
return frame_processor_module return frame_processor_module

View File

@ -5,7 +5,7 @@ import threading
import numpy as np import numpy as np
import modules.globals import modules.globals
import modules.processors.frame.core import modules.processors.frame.core
from modules.core import update_status from run import app
from modules.face_analyser import get_one_face, get_many_faces, default_source_face from modules.face_analyser import get_one_face, get_many_faces, default_source_face
from modules.typing import Face, Frame from modules.typing import Face, Frame
from modules.utilities import ( from modules.utilities import (
@ -36,17 +36,17 @@ def pre_check() -> bool:
def pre_start() -> bool: def pre_start() -> bool:
if not modules.globals.map_faces and not is_image(modules.globals.source_path): if not modules.globals.map_faces and not is_image(modules.globals.source_path):
update_status("Select an image for source path.", NAME) app.update_status("Select an image for source path.", NAME)
return False return False
elif not modules.globals.map_faces and not get_one_face( elif not modules.globals.map_faces and not get_one_face(
cv2.imread(modules.globals.source_path) cv2.imread(modules.globals.source_path)
): ):
update_status("No face in source path detected.", NAME) app.update_status("No face in source path detected.", NAME)
return False return False
if not is_image(modules.globals.target_path) and not is_video( if not is_image(modules.globals.target_path) and not is_video(
modules.globals.target_path modules.globals.target_path
): ):
update_status("Select an image or video for target path.", NAME) app.update_status("Select an image or video for target path.", NAME)
return False return False
return True return True
@ -236,7 +236,7 @@ def process_image(source_path: str, target_path: str, output_path: str) -> None:
cv2.imwrite(output_path, result) cv2.imwrite(output_path, result)
else: else:
if modules.globals.many_faces: if modules.globals.many_faces:
update_status( app.update_status(
"Many faces enabled. Using first source image. Progressing...", NAME "Many faces enabled. Using first source image. Progressing...", NAME
) )
target_frame = cv2.imread(output_path) target_frame = cv2.imread(output_path)
@ -246,7 +246,7 @@ def process_image(source_path: str, target_path: str, output_path: str) -> None:
def process_video(source_path: str, temp_frame_paths: List[str]) -> None: def process_video(source_path: str, temp_frame_paths: List[str]) -> None:
if modules.globals.map_faces and modules.globals.many_faces: if modules.globals.map_faces and modules.globals.many_faces:
update_status( app.update_status(
"Many faces enabled. Using first source image. Progressing...", NAME "Many faces enabled. Using first source image. Progressing...", NAME
) )
modules.processors.frame.core.process_video( modules.processors.frame.core.process_video(
@ -256,7 +256,7 @@ def process_video(source_path: str, temp_frame_paths: List[str]) -> None:
def create_lower_mouth_mask( def create_lower_mouth_mask(
face: Face, frame: Frame face: Face, frame: Frame
) -> (np.ndarray, np.ndarray, tuple, np.ndarray): ) -> tuple[np.ndarray, np.ndarray, tuple, np.ndarray]:
mask = np.zeros(frame.shape[:2], dtype=np.uint8) mask = np.zeros(frame.shape[:2], dtype=np.uint8)
mouth_cutout = None mouth_cutout = None
landmarks = face.landmark_2d_106 landmarks = face.landmark_2d_106

View File

@ -1,7 +1,6 @@
from typing import Any from typing import Any, TypeAlias
from insightface.app.common import Face from insightface.app.common import Face
import numpy import numpy
Face = Face Frame: TypeAlias = numpy.ndarray[Any, Any]
Frame = numpy.ndarray[Any, Any]

View File

@ -7,6 +7,8 @@ from cv2_enumerate_cameras import enumerate_cameras # Add this import
from PIL import Image, ImageOps from PIL import Image, ImageOps
import time import time
import json import json
from numpy import ndarray
from modules.predicter import predict_image, predict_video, predict_frame
import modules.globals import modules.globals
import modules.metadata import modules.metadata
@ -27,13 +29,9 @@ from modules.utilities import (
has_image_extension, has_image_extension,
) )
ROOT = None
POPUP = None
POPUP_LIVE = None
ROOT_HEIGHT = 700 ROOT_HEIGHT = 700
ROOT_WIDTH = 600 ROOT_WIDTH = 600
PREVIEW = None
PREVIEW_MAX_HEIGHT = 700 PREVIEW_MAX_HEIGHT = 700
PREVIEW_MAX_WIDTH = 1200 PREVIEW_MAX_WIDTH = 1200
PREVIEW_DEFAULT_WIDTH = 960 PREVIEW_DEFAULT_WIDTH = 960
@ -55,33 +53,9 @@ MAPPER_PREVIEW_MAX_WIDTH = 100
DEFAULT_BUTTON_WIDTH = 200 DEFAULT_BUTTON_WIDTH = 200
DEFAULT_BUTTON_HEIGHT = 40 DEFAULT_BUTTON_HEIGHT = 40
RECENT_DIRECTORY_SOURCE = None
RECENT_DIRECTORY_TARGET = None
RECENT_DIRECTORY_OUTPUT = None
preview_label = None
preview_slider = None
source_label = None
target_label = None
status_label = None
popup_status_label = None
popup_status_label_live = None
source_label_dict = {}
source_label_dict_live = {}
target_label_dict_live = {}
img_ft, vid_ft = modules.globals.file_types img_ft, vid_ft = modules.globals.file_types
def init(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.CTk:
global ROOT, PREVIEW
ROOT = create_root(start, destroy)
PREVIEW = create_preview(ROOT)
return ROOT
def save_switch_states(): def save_switch_states():
switch_states = { switch_states = {
"keep_fps": modules.globals.keep_fps, "keep_fps": modules.globals.keep_fps,
@ -123,10 +97,58 @@ def load_switch_states():
# If the file doesn't exist, use default values # If the file doesn't exist, use default values
pass pass
def fit_image_to_size(image, width: int, height: int):
if width is None and height is None:
return image
h, w, _ = image.shape
ratio_h = 0.0
ratio_w = 0.0
if width > height:
ratio_h = height / h
else:
ratio_w = width / w
ratio = max(ratio_w, ratio_h)
new_size = (int(ratio * w), int(ratio * h))
return cv2.resize(image, dsize=new_size)
def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.CTk: def get_available_cameras():
global source_label, target_label, status_label, show_fps_switch """Returns a list of available camera names and indices."""
camera_indices = []
camera_names = []
for camera in enumerate_cameras():
cap = cv2.VideoCapture(camera.index)
if cap.isOpened():
camera_indices.append(camera.index)
camera_names.append(camera.name)
cap.release()
return (camera_indices, camera_names)
class DeepFakeUI:
preview_label: ctk.CTkLabel
source_label: ctk.CTkLabel
target_label: ctk.CTkLabel
status_label: ctk.CTkLabel
popup_status_label: ctk.CTkLabel
popup_status_label_live: ctk.CTkLabel
preview_slider: ctk.CTkSlider
source_label_dict: dict[int, ctk.CTkLabel] = {}
source_label_dict_live: dict[int, ctk.CTkLabel] = {}
target_label_dict_live: dict[int, ctk.CTkLabel] = {}
source_label_dict_live = {}
target_label_dict_live = {}
popup_live: ctk.CTkToplevel
popup: ctk.CTkToplevel = None
recent_directory_source: str = os.path.expanduser("~")
recent_directory_target: str = os.path.expanduser("~")
recent_directory_output: str = os.path.expanduser("~")
def __init__(self, start: Callable[[], None], destroy: Callable[[], None]) -> None:
self.root = self.create_root(start, destroy)
self.preview = self.create_preview(self.root)
def create_root(self, start: Callable[[], None], destroy: Callable[[], None]) -> ctk.CTk:
load_switch_states() load_switch_states()
ctk.deactivate_automatic_dpi_awareness() ctk.deactivate_automatic_dpi_awareness()
@ -148,12 +170,12 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
target_label.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.25) target_label.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.25)
select_face_button = ctk.CTkButton( select_face_button = ctk.CTkButton(
root, text="Select a face", cursor="hand2", command=lambda: select_source_path() root, text="Select a face", cursor="hand2", command=lambda: self.select_source_path()
) )
select_face_button.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1) select_face_button.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)
swap_faces_button = ctk.CTkButton( swap_faces_button = ctk.CTkButton(
root, text="", cursor="hand2", command=lambda: swap_faces_paths() root, text="", cursor="hand2", command=lambda: self.swap_faces_paths()
) )
swap_faces_button.place(relx=0.45, rely=0.4, relwidth=0.1, relheight=0.1) swap_faces_button.place(relx=0.45, rely=0.4, relwidth=0.1, relheight=0.1)
@ -161,7 +183,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
root, root,
text="Select a target", text="Select a target",
cursor="hand2", cursor="hand2",
command=lambda: select_target_path(), command=lambda: self.select_target_path(),
) )
select_target_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1) select_target_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)
@ -198,7 +220,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
variable=enhancer_value, variable=enhancer_value,
cursor="hand2", cursor="hand2",
command=lambda: ( command=lambda: (
update_tumbler("face_enhancer", enhancer_value.get()), self.update_tumbler("face_enhancer", enhancer_value.get()),
save_switch_states(), save_switch_states(),
), ),
) )
@ -296,7 +318,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
show_mouth_mask_box_switch.place(relx=0.6, rely=0.55) show_mouth_mask_box_switch.place(relx=0.6, rely=0.55)
start_button = ctk.CTkButton( start_button = ctk.CTkButton(
root, text="Start", cursor="hand2", command=lambda: analyze_target(start, root) root, text="Start", cursor="hand2", command=lambda: self.analyze_target(start, root)
) )
start_button.place(relx=0.15, rely=0.80, relwidth=0.2, relheight=0.05) start_button.place(relx=0.15, rely=0.80, relwidth=0.2, relheight=0.05)
@ -306,7 +328,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
stop_button.place(relx=0.4, rely=0.80, relwidth=0.2, relheight=0.05) stop_button.place(relx=0.4, rely=0.80, relwidth=0.2, relheight=0.05)
preview_button = ctk.CTkButton( preview_button = ctk.CTkButton(
root, text="Preview", cursor="hand2", command=lambda: toggle_preview() root, text="Preview", cursor="hand2", command=lambda: self.toggle_preview()
) )
preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05) preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05)
@ -333,7 +355,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
root, root,
text="Live", text="Live",
cursor="hand2", cursor="hand2",
command=lambda: webcam_preview( command=lambda: self.webcam_preview(
root, root,
available_camera_indices[ available_camera_indices[
available_camera_strings.index(camera_variable.get()) available_camera_strings.index(camera_variable.get())
@ -357,56 +379,58 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
"<Button>", lambda event: webbrowser.open("https://paypal.me/hacksider") "<Button>", lambda event: webbrowser.open("https://paypal.me/hacksider")
) )
self.source_label = source_label
self.target_label = target_label
self.status_label = status_label
return root return root
def analyze_target(start: Callable[[], None], root: ctk.CTk): def analyze_target(self, start: Callable[[], None], root: ctk.CTk):
if POPUP != None and POPUP.winfo_exists(): if self.popup != None and self.popup.winfo_exists():
update_status("Please complete pop-up or close it.") self.update_status("Please complete pop-up or close it.")
return return
if modules.globals.map_faces: if modules.globals.map_faces:
modules.globals.souce_target_map = [] modules.globals.souce_target_map = []
if is_image(modules.globals.target_path): if is_image(modules.globals.target_path):
update_status("Getting unique faces") self.update_status("Getting unique faces")
get_unique_faces_from_target_image() get_unique_faces_from_target_image()
elif is_video(modules.globals.target_path): elif is_video(modules.globals.target_path):
update_status("Getting unique faces") self.update_status("Getting unique faces")
get_unique_faces_from_target_video() get_unique_faces_from_target_video()
if len(modules.globals.souce_target_map) > 0: if len(modules.globals.souce_target_map) > 0:
create_source_target_popup(start, root, modules.globals.souce_target_map) self.create_source_target_popup(start, root, modules.globals.souce_target_map)
else: else:
update_status("No faces found in target") self.update_status("No faces found in target")
else: else:
select_output_path(start) self.select_output_path(start)
def create_source_target_popup( def create_source_target_popup(
start: Callable[[], None], root: ctk.CTk, map: list self, start: Callable[[], None], root: ctk.CTk, map: list
) -> None: ) -> None:
global POPUP, popup_status_label popup = ctk.CTkToplevel(root)
popup.title("Source x Target Mapper")
POPUP = ctk.CTkToplevel(root) popup.geometry(f"{POPUP_WIDTH}x{POPUP_HEIGHT}")
POPUP.title("Source x Target Mapper") popup.focus()
POPUP.geometry(f"{POPUP_WIDTH}x{POPUP_HEIGHT}")
POPUP.focus()
def on_submit_click(start): def on_submit_click(start):
if has_valid_map(): if has_valid_map():
POPUP.destroy() popup.destroy()
select_output_path(start) self.select_output_path(start)
else: else:
update_pop_status("Atleast 1 source with target is required!") self.update_pop_status("Atleast 1 source with target is required!")
scrollable_frame = ctk.CTkScrollableFrame( scrollable_frame = ctk.CTkScrollableFrame(
POPUP, width=POPUP_SCROLL_WIDTH, height=POPUP_SCROLL_HEIGHT popup, width=POPUP_SCROLL_WIDTH, height=POPUP_SCROLL_HEIGHT
) )
scrollable_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") scrollable_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
def on_button_click(map, button_num): def on_button_click(map, button_num):
map = update_popup_source(scrollable_frame, map, button_num) map = self.update_popup_source(scrollable_frame, map, button_num)
for item in map: for item in map:
id = item["id"] id = item["id"]
@ -443,30 +467,31 @@ def create_source_target_popup(
target_image.grid(row=id, column=3, padx=10, pady=10) target_image.grid(row=id, column=3, padx=10, pady=10)
target_image.configure(image=tk_image) target_image.configure(image=tk_image)
popup_status_label = ctk.CTkLabel(POPUP, text=None, justify="center") popup_status_label = ctk.CTkLabel(popup, text=None, justify="center")
popup_status_label.grid(row=1, column=0, pady=15) popup_status_label.grid(row=1, column=0, pady=15)
close_button = ctk.CTkButton( close_button = ctk.CTkButton(
POPUP, text="Submit", command=lambda: on_submit_click(start) popup, text="Submit", command=lambda: on_submit_click(start)
) )
close_button.grid(row=2, column=0, pady=10) close_button.grid(row=2, column=0, pady=10)
self.popup_status_label = popup_status_label
self.popup = popup
def update_popup_source( def update_popup_source(
scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int self, scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int
) -> list: ) -> list:
global source_label_dict
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title="select an source image", title="select an source image",
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=self.recent_directory_source,
filetypes=[img_ft], filetypes=[img_ft],
) )
if "source" in map[button_num]: if "source" in map[button_num]:
map[button_num].pop("source") map[button_num].pop("source")
source_label_dict[button_num].destroy() self.source_label_dict[button_num].destroy()
del source_label_dict[button_num] del self.source_label_dict[button_num]
if source_path == "": if source_path == "":
return map return map
@ -498,78 +523,71 @@ def update_popup_source(
) )
source_image.grid(row=button_num, column=1, padx=10, pady=10) source_image.grid(row=button_num, column=1, padx=10, pady=10)
source_image.configure(image=tk_image) source_image.configure(image=tk_image)
source_label_dict[button_num] = source_image self.source_label_dict[button_num] = source_image
else: else:
update_pop_status("Face could not be detected in last upload!") self.update_pop_status("Face could not be detected in last upload!")
return map return map
def create_preview(parent: ctk.CTkToplevel) -> ctk.CTkToplevel: def create_preview(self, parent: ctk.CTkToplevel) -> ctk.CTkToplevel:
global preview_label, preview_slider
preview = ctk.CTkToplevel(parent) preview = ctk.CTkToplevel(parent)
preview.withdraw() preview.withdraw()
preview.title("Preview") preview.title("Preview")
preview.configure() preview.configure()
preview.protocol("WM_DELETE_WINDOW", lambda: toggle_preview()) preview.protocol("WM_DELETE_WINDOW", lambda: self.toggle_preview())
preview.resizable(width=True, height=True) preview.resizable(width=True, height=True)
preview_label = ctk.CTkLabel(preview, text=None) self.preview_label = ctk.CTkLabel(preview, text=None)
preview_label.pack(fill="both", expand=True) self.preview_label.pack(fill="both", expand=True)
preview_slider = ctk.CTkSlider( self.preview_slider = ctk.CTkSlider(
preview, from_=0, to=0, command=lambda frame_value: update_preview(frame_value) preview, from_=0, to=0, command=lambda frame_value: self.update_preview(frame_value)
) )
return preview return preview
def update_status(text: str) -> None: def update_status(self, text: str) -> None:
status_label.configure(text=text) self.status_label.configure(text=text)
ROOT.update() self.root.update()
def update_pop_status(text: str) -> None: def update_pop_status(self, text: str) -> None:
popup_status_label.configure(text=text) self.popup_status_label.configure(text=text)
def update_pop_live_status(text: str) -> None: def update_pop_live_status(self, text: str) -> None:
popup_status_label_live.configure(text=text) self.popup_status_label_live.configure(text=text)
def update_tumbler(var: str, value: bool) -> None: def update_tumbler(self, var: str, value: bool) -> None:
modules.globals.fp_ui[var] = value modules.globals.fp_ui[var] = value
save_switch_states() save_switch_states()
# If we're currently in a live preview, update the frame processors # If we're currently in a live preview, update the frame processors
if PREVIEW.state() == "normal": if self.preview.state() == "normal":
global frame_processors self.frame_processors = get_frame_processors_modules(
frame_processors = get_frame_processors_modules(
modules.globals.frame_processors modules.globals.frame_processors
) )
def select_source_path() -> None: def select_source_path(self) -> None:
global RECENT_DIRECTORY_SOURCE, img_ft, vid_ft self.preview.withdraw()
PREVIEW.withdraw()
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title="select an source image", title="select an source image",
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=self.recent_directory_source,
filetypes=[img_ft], filetypes=[img_ft],
) )
if is_image(source_path): if is_image(source_path):
modules.globals.source_path = source_path modules.globals.source_path = source_path
RECENT_DIRECTORY_SOURCE = os.path.dirname(modules.globals.source_path) self.recent_directory_source = os.path.dirname(modules.globals.source_path)
image = render_image_preview(modules.globals.source_path, (200, 200)) image = self.render_image_preview(modules.globals.source_path, (200, 200))
source_label.configure(image=image) self.source_label.configure(image=image)
else: else:
modules.globals.source_path = None modules.globals.source_path = None
source_label.configure(image=None) self.source_label.configure(image=None)
def swap_faces_paths() -> None: def swap_faces_paths(self) -> None:
global RECENT_DIRECTORY_SOURCE, RECENT_DIRECTORY_TARGET
source_path = modules.globals.source_path source_path = modules.globals.source_path
target_path = modules.globals.target_path target_path = modules.globals.target_path
@ -579,52 +597,48 @@ def swap_faces_paths() -> None:
modules.globals.source_path = target_path modules.globals.source_path = target_path
modules.globals.target_path = source_path modules.globals.target_path = source_path
RECENT_DIRECTORY_SOURCE = os.path.dirname(modules.globals.source_path) self.recent_directory_source = os.path.dirname(modules.globals.source_path)
RECENT_DIRECTORY_TARGET = os.path.dirname(modules.globals.target_path) self.recent_directory_target = os.path.dirname(modules.globals.target_path)
PREVIEW.withdraw() self.preview.withdraw()
source_image = render_image_preview(modules.globals.source_path, (200, 200)) source_image = self.render_image_preview(modules.globals.source_path, (200, 200))
source_label.configure(image=source_image) self.source_label.configure(image=source_image)
target_image = render_image_preview(modules.globals.target_path, (200, 200)) target_image = self.render_image_preview(modules.globals.target_path, (200, 200))
target_label.configure(image=target_image) self.target_label.configure(image=target_image)
def select_target_path() -> None: def select_target_path(self) -> None:
global RECENT_DIRECTORY_TARGET, img_ft, vid_ft self.preview.withdraw()
PREVIEW.withdraw()
target_path = ctk.filedialog.askopenfilename( target_path = ctk.filedialog.askopenfilename(
title="select an target image or video", title="select an target image or video",
initialdir=RECENT_DIRECTORY_TARGET, initialdir=self.recent_directory_target,
filetypes=[img_ft, vid_ft], filetypes=[img_ft, vid_ft],
) )
if is_image(target_path): if is_image(target_path):
modules.globals.target_path = target_path modules.globals.target_path = target_path
RECENT_DIRECTORY_TARGET = os.path.dirname(modules.globals.target_path) self.recent_directory_target = os.path.dirname(modules.globals.target_path)
image = render_image_preview(modules.globals.target_path, (200, 200)) image = self.render_image_preview(modules.globals.target_path, (200, 200))
target_label.configure(image=image) self.target_label.configure(image=image)
elif is_video(target_path): elif is_video(target_path):
modules.globals.target_path = target_path modules.globals.target_path = target_path
RECENT_DIRECTORY_TARGET = os.path.dirname(modules.globals.target_path) self.recent_directory_target = os.path.dirname(modules.globals.target_path)
video_frame = render_video_preview(target_path, (200, 200)) video_frame = self.render_video_preview(target_path, (200, 200))
target_label.configure(image=video_frame) self.target_label.configure(image=video_frame)
else: else:
modules.globals.target_path = None modules.globals.target_path = None
target_label.configure(image=None) self.target_label.configure(image=None)
def select_output_path(start: Callable[[], None]) -> None: def select_output_path(self, start: Callable[[], None]) -> None:
global RECENT_DIRECTORY_OUTPUT, img_ft, vid_ft
if is_image(modules.globals.target_path): if is_image(modules.globals.target_path):
output_path = ctk.filedialog.asksaveasfilename( output_path = ctk.filedialog.asksaveasfilename(
title="save image output file", title="save image output file",
filetypes=[img_ft], filetypes=[img_ft],
defaultextension=".png", defaultextension=".png",
initialfile="output.png", initialfile="output.png",
initialdir=RECENT_DIRECTORY_OUTPUT, initialdir=self.recent_directory_output,
) )
elif is_video(modules.globals.target_path): elif is_video(modules.globals.target_path):
output_path = ctk.filedialog.asksaveasfilename( output_path = ctk.filedialog.asksaveasfilename(
@ -632,22 +646,19 @@ def select_output_path(start: Callable[[], None]) -> None:
filetypes=[vid_ft], filetypes=[vid_ft],
defaultextension=".mp4", defaultextension=".mp4",
initialfile="output.mp4", initialfile="output.mp4",
initialdir=RECENT_DIRECTORY_OUTPUT, initialdir=self.recent_directory_output,
) )
else: else:
output_path = None output_path = None
if output_path: if output_path:
modules.globals.output_path = output_path modules.globals.output_path = output_path
RECENT_DIRECTORY_OUTPUT = os.path.dirname(modules.globals.output_path) self.recent_directory_output = os.path.dirname(modules.globals.output_path)
start() start()
def check_and_ignore_nsfw(self, target: str | ndarray, destroy: Callable | None = None) -> bool:
def check_and_ignore_nsfw(target, destroy: Callable = None) -> bool:
"""Check if the target is NSFW. """Check if the target is NSFW.
TODO: Consider to make blur the target. TODO: Consider to make blur the target.
""" """
from numpy import ndarray
from modules.predicter import predict_image, predict_video, predict_frame
if type(target) is str: # image/video file path if type(target) is str: # image/video file path
check_nsfw = predict_image if has_image_extension(target) else predict_video check_nsfw = predict_image if has_image_extension(target) else predict_video
@ -658,28 +669,12 @@ def check_and_ignore_nsfw(target, destroy: Callable = None) -> bool:
destroy( destroy(
to_quit=False to_quit=False
) # Do not need to destroy the window frame if the target is NSFW ) # Do not need to destroy the window frame if the target is NSFW
update_status("Processing ignored!") self.update_status("Processing ignored!")
return True return True
else: else:
return False return False
def render_image_preview(self, image_path: str, size: Tuple[int, int]) -> ctk.CTkImage:
def fit_image_to_size(image, width: int, height: int):
if width is None and height is None:
return image
h, w, _ = image.shape
ratio_h = 0.0
ratio_w = 0.0
if width > height:
ratio_h = height / h
else:
ratio_w = width / w
ratio = max(ratio_w, ratio_h)
new_size = (int(ratio * w), int(ratio * h))
return cv2.resize(image, dsize=new_size)
def render_image_preview(image_path: str, size: Tuple[int, int]) -> ctk.CTkImage:
image = Image.open(image_path) image = Image.open(image_path)
if size: if size:
image = ImageOps.fit(image, size, Image.LANCZOS) image = ImageOps.fit(image, size, Image.LANCZOS)
@ -687,8 +682,8 @@ def render_image_preview(image_path: str, size: Tuple[int, int]) -> ctk.CTkImage
def render_video_preview( def render_video_preview(
video_path: str, size: Tuple[int, int], frame_number: int = 0 self, video_path: str, size: Tuple[int, int], frame_number: int = 0
) -> ctk.CTkImage: ) -> None:
capture = cv2.VideoCapture(video_path) capture = cv2.VideoCapture(video_path)
if frame_number: if frame_number:
capture.set(cv2.CAP_PROP_POS_FRAMES, frame_number) capture.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
@ -702,29 +697,29 @@ def render_video_preview(
cv2.destroyAllWindows() cv2.destroyAllWindows()
def toggle_preview() -> None: def toggle_preview(self) -> None:
if PREVIEW.state() == "normal": if self.preview.state() == "normal":
PREVIEW.withdraw() self.preview.withdraw()
elif modules.globals.source_path and modules.globals.target_path: elif modules.globals.source_path and modules.globals.target_path:
init_preview() self.init_preview()
update_preview() self.update_preview()
def init_preview() -> None: def init_preview(self) -> None:
if is_image(modules.globals.target_path): if is_image(modules.globals.target_path):
preview_slider.pack_forget() self.preview_slider.pack_forget()
if is_video(modules.globals.target_path): if is_video(modules.globals.target_path):
video_frame_total = get_video_frame_total(modules.globals.target_path) video_frame_total = get_video_frame_total(modules.globals.target_path)
preview_slider.configure(to=video_frame_total) self.preview_slider.configure(to=video_frame_total)
preview_slider.pack(fill="x") self.preview_slider.pack(fill="x")
preview_slider.set(0) self.preview_slider.set(0)
def update_preview(frame_number: int = 0) -> None: def update_preview(self, frame_number: int = 0) -> None:
if modules.globals.source_path and modules.globals.target_path: if modules.globals.source_path and modules.globals.target_path:
update_status("Processing...") self.update_status("Processing...")
temp_frame = get_video_frame(modules.globals.target_path, frame_number) temp_frame = get_video_frame(modules.globals.target_path, frame_number)
if modules.globals.nsfw_filter and check_and_ignore_nsfw(temp_frame): if modules.globals.nsfw_filter and self.check_and_ignore_nsfw(temp_frame):
return return
for frame_processor in get_frame_processors_modules( for frame_processor in get_frame_processors_modules(
modules.globals.frame_processors modules.globals.frame_processors
@ -737,49 +732,32 @@ def update_preview(frame_number: int = 0) -> None:
image, (PREVIEW_MAX_WIDTH, PREVIEW_MAX_HEIGHT), Image.LANCZOS image, (PREVIEW_MAX_WIDTH, PREVIEW_MAX_HEIGHT), Image.LANCZOS
) )
image = ctk.CTkImage(image, size=image.size) image = ctk.CTkImage(image, size=image.size)
preview_label.configure(image=image) self.preview_label.configure(image=image)
update_status("Processing succeed!") self.update_status("Processing succeed!")
PREVIEW.deiconify() self.preview.deiconify()
def webcam_preview(root: ctk.CTk, camera_index: int): def webcam_preview(self, root: ctk.CTk, camera_index: int):
if not modules.globals.map_faces: if not modules.globals.map_faces:
if modules.globals.source_path is None: if modules.globals.source_path is None:
# No image selected # No image selected
return return
create_webcam_preview(camera_index) self.create_webcam_preview(camera_index)
else: else:
modules.globals.souce_target_map = [] modules.globals.souce_target_map = []
create_source_target_popup_for_webcam( self.create_source_target_popup_for_webcam(
root, modules.globals.souce_target_map, camera_index root, modules.globals.souce_target_map, camera_index
) )
def create_webcam_preview(self, camera_index: int):
def get_available_cameras():
"""Returns a list of available camera names and indices."""
camera_indices = []
camera_names = []
for camera in enumerate_cameras():
cap = cv2.VideoCapture(camera.index)
if cap.isOpened():
camera_indices.append(camera.index)
camera_names.append(camera.name)
cap.release()
return (camera_indices, camera_names)
def create_webcam_preview(camera_index: int):
global preview_label, PREVIEW
camera = cv2.VideoCapture(camera_index) camera = cv2.VideoCapture(camera_index)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, PREVIEW_DEFAULT_WIDTH) camera.set(cv2.CAP_PROP_FRAME_WIDTH, PREVIEW_DEFAULT_WIDTH)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, PREVIEW_DEFAULT_HEIGHT) camera.set(cv2.CAP_PROP_FRAME_HEIGHT, PREVIEW_DEFAULT_HEIGHT)
camera.set(cv2.CAP_PROP_FPS, 60) camera.set(cv2.CAP_PROP_FPS, 60)
preview_label.configure(width=PREVIEW_DEFAULT_WIDTH, height=PREVIEW_DEFAULT_HEIGHT) self.preview_label.configure(width=PREVIEW_DEFAULT_WIDTH, height=PREVIEW_DEFAULT_HEIGHT)
PREVIEW.deiconify() self.preview.deiconify()
frame_processors = get_frame_processors_modules(modules.globals.frame_processors) frame_processors = get_frame_processors_modules(modules.globals.frame_processors)
@ -801,7 +779,7 @@ def create_webcam_preview(camera_index: int):
if modules.globals.live_resizable: if modules.globals.live_resizable:
temp_frame = fit_image_to_size( temp_frame = fit_image_to_size(
temp_frame, PREVIEW.winfo_width(), PREVIEW.winfo_height() temp_frame, self.preview.winfo_width(), self.preview.winfo_height()
) )
if not modules.globals.map_faces: if not modules.globals.map_faces:
@ -849,64 +827,62 @@ def create_webcam_preview(camera_index: int):
image, (temp_frame.shape[1], temp_frame.shape[0]), Image.LANCZOS image, (temp_frame.shape[1], temp_frame.shape[0]), Image.LANCZOS
) )
image = ctk.CTkImage(image, size=image.size) image = ctk.CTkImage(image, size=image.size)
preview_label.configure(image=image) self.preview_label.configure(image=image)
ROOT.update() self.root.update()
if PREVIEW.state() == "withdrawn": if self.preview.state() == "withdrawn":
break break
camera.release() camera.release()
PREVIEW.withdraw() self.preview.withdraw()
def create_source_target_popup_for_webcam( def create_source_target_popup_for_webcam(
root: ctk.CTk, map: list, camera_index: int self, root: ctk.CTk, map: list, camera_index: int
) -> None: ) -> None:
global POPUP_LIVE, popup_status_label_live self.popup_live = ctk.CTkToplevel(root)
self.popup_live.title("Source x Target Mapper")
POPUP_LIVE = ctk.CTkToplevel(root) self.popup_live.geometry(f"{POPUP_LIVE_WIDTH}x{POPUP_LIVE_HEIGHT}")
POPUP_LIVE.title("Source x Target Mapper") self.popup_live.focus()
POPUP_LIVE.geometry(f"{POPUP_LIVE_WIDTH}x{POPUP_LIVE_HEIGHT}")
POPUP_LIVE.focus()
def on_submit_click(): def on_submit_click():
if has_valid_map(): if has_valid_map():
POPUP_LIVE.destroy() self.popup_live.destroy()
simplify_maps() simplify_maps()
create_webcam_preview(camera_index) self.create_webcam_preview(camera_index)
else: else:
update_pop_live_status("At least 1 source with target is required!") self.update_pop_live_status("At least 1 source with target is required!")
def on_add_click(): def on_add_click():
add_blank_map() add_blank_map()
refresh_data(map) self.refresh_data(map)
update_pop_live_status("Please provide mapping!") self.update_pop_live_status("Please provide mapping!")
popup_status_label_live = ctk.CTkLabel(POPUP_LIVE, text=None, justify="center") popup_status_label_live = ctk.CTkLabel(self.popup_live, text=None, justify="center")
popup_status_label_live.grid(row=1, column=0, pady=15) popup_status_label_live.grid(row=1, column=0, pady=15)
add_button = ctk.CTkButton(POPUP_LIVE, text="Add", command=lambda: on_add_click()) add_button = ctk.CTkButton(self.popup_live, text="Add", command=lambda: on_add_click())
add_button.place(relx=0.2, rely=0.92, relwidth=0.2, relheight=0.05) add_button.place(relx=0.2, rely=0.92, relwidth=0.2, relheight=0.05)
close_button = ctk.CTkButton( close_button = ctk.CTkButton(
POPUP_LIVE, text="Submit", command=lambda: on_submit_click() self.popup_live, text="Submit", command=lambda: on_submit_click()
) )
close_button.place(relx=0.6, rely=0.92, relwidth=0.2, relheight=0.05) close_button.place(relx=0.6, rely=0.92, relwidth=0.2, relheight=0.05)
self.popup_status_label_live = popup_status_label_live
def refresh_data(map: list):
global POPUP_LIVE
def refresh_data(self, map: list):
scrollable_frame = ctk.CTkScrollableFrame( scrollable_frame = ctk.CTkScrollableFrame(
POPUP_LIVE, width=POPUP_LIVE_SCROLL_WIDTH, height=POPUP_LIVE_SCROLL_HEIGHT self.popup_live, width=POPUP_LIVE_SCROLL_WIDTH, height=POPUP_LIVE_SCROLL_HEIGHT
) )
scrollable_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") scrollable_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
def on_sbutton_click(map, button_num): def on_sbutton_click(map, button_num):
map = update_webcam_source(scrollable_frame, map, button_num) map = self.update_webcam_source(scrollable_frame, map, button_num)
def on_tbutton_click(map, button_num): def on_tbutton_click(map, button_num):
map = update_webcam_target(scrollable_frame, map, button_num) map = self.update_webcam_target(scrollable_frame, map, button_num)
for item in map: for item in map:
id = item["id"] id = item["id"]
@ -975,20 +951,18 @@ def refresh_data(map: list):
def update_webcam_source( def update_webcam_source(
scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int self, scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int
) -> list: ) -> list:
global source_label_dict_live
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title="select an source image", title="select an source image",
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=self.recent_directory_source,
filetypes=[img_ft], filetypes=[img_ft],
) )
if "source" in map[button_num]: if "source" in map[button_num]:
map[button_num].pop("source") map[button_num].pop("source")
source_label_dict_live[button_num].destroy() self.source_label_dict_live[button_num].destroy()
del source_label_dict_live[button_num] del self.source_label_dict_live[button_num]
if source_path == "": if source_path == "":
return map return map
@ -1020,27 +994,25 @@ def update_webcam_source(
) )
source_image.grid(row=button_num, column=1, padx=10, pady=10) source_image.grid(row=button_num, column=1, padx=10, pady=10)
source_image.configure(image=tk_image) source_image.configure(image=tk_image)
source_label_dict_live[button_num] = source_image self.source_label_dict_live[button_num] = source_image
else: else:
update_pop_live_status("Face could not be detected in last upload!") self.update_pop_live_status("Face could not be detected in last upload!")
return map return map
def update_webcam_target( def update_webcam_target(
scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int self, scrollable_frame: ctk.CTkScrollableFrame, map: list, button_num: int
) -> list: ) -> list:
global target_label_dict_live
target_path = ctk.filedialog.askopenfilename( target_path = ctk.filedialog.askopenfilename(
title="select an target image", title="select an target image",
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=self.recent_directory_source,
filetypes=[img_ft], filetypes=[img_ft],
) )
if "target" in map[button_num]: if "target" in map[button_num]:
map[button_num].pop("target") map[button_num].pop("target")
target_label_dict_live[button_num].destroy() self.target_label_dict_live[button_num].destroy()
del target_label_dict_live[button_num] del self.target_label_dict_live[button_num]
if target_path == "": if target_path == "":
return map return map
@ -1072,7 +1044,7 @@ def update_webcam_target(
) )
target_image.grid(row=button_num, column=4, padx=20, pady=10) target_image.grid(row=button_num, column=4, padx=20, pady=10)
target_image.configure(image=tk_image) target_image.configure(image=tk_image)
target_label_dict_live[button_num] = target_image self.target_label_dict_live[button_num] = target_image
else: else:
update_pop_live_status("Face could not be detected in last upload!") self.update_pop_live_status("Face could not be detected in last upload!")
return map return map

7
run.py
View File

@ -1,6 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from modules import core from modules.core import DeepFakeApp
app = DeepFakeApp()
if __name__ == '__main__': if __name__ == '__main__':
core.run() app.run()