import os import customtkinter as ctk import webbrowser import cv2 import roop.globals import roop.metadata from typing import Callable, Tuple from PIL import Image, ImageOps from roop.face_helper import get_many_faces, get_one_face, extract_face_images from roop.capturer import get_video_frame, get_video_frame_total from roop.utilities import is_image, is_video, resolve_relative_path, open_with_default_app, compute_cosine_distance, has_extension ROOT = None ROOT_HEIGHT = 550 ROOT_WIDTH = 600 PREVIEW = None PREVIEW_MAX_HEIGHT = 700 PREVIEW_MAX_WIDTH = 1200 IMAGE_BUTTON_WIDTH = 200 IMAGE_BUTTON_HEIGHT = 200 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 FACE_BUTTONS = [] INPUT_FACES_DATA = None OUTPUT_FACES_DATA = None def init(start: Callable, destroy: Callable) -> ctk.CTk: global ROOT, PREVIEW, FACE_SELECT ROOT = create_root(start, destroy) PREVIEW = create_preview(ROOT) FACE_SELECT = create_select_faces_win(ROOT) return ROOT def create_root(start: Callable, destroy: Callable) -> ctk.CTk: global source_button, target_button, status_label ctk.deactivate_automatic_dpi_awareness() ctk.set_appearance_mode('system') ctk.set_default_color_theme(resolve_relative_path('ui.json')) root = ctk.CTk() root.minsize(ROOT_WIDTH, ROOT_HEIGHT) root.title(f'{roop.metadata.name} {roop.metadata.version}') root.configure() root.protocol('WM_DELETE_WINDOW', lambda: destroy()) base_x1 = 0.075 base_x2 = 0.575 base_y = 0.635 source_button = ctk.CTkButton(root, text='Select image with face(s)', width=IMAGE_BUTTON_WIDTH, height=IMAGE_BUTTON_HEIGHT, compound='top', anchor='center', command=lambda: select_source_path()) source_button.place(relx=base_x1, rely=0.05) target_button = ctk.CTkButton(root, text='Select target image/video', width=IMAGE_BUTTON_WIDTH, height=IMAGE_BUTTON_HEIGHT, compound='top', anchor='center', command=lambda: select_target_path()) target_button.place(relx=base_x2, rely=0.05) enhance_label = ctk.CTkLabel(root, text='Select face enhancement engine', anchor='w') enhance_label.place(relx=base_x1, rely=0.49) enhance_label.configure(text_color=ctk.ThemeManager.theme.get('RoopDonate').get('text_color')) enhancer_cb = ctk.CTkComboBox(root, values=["None", "Codeformer", "DMDNet (unavailable)", "GFPGAN"], width=IMAGE_BUTTON_WIDTH, command=select_enhancer) enhancer_cb.set("None") enhancer_cb.place(relx=base_x1, rely=0.532) keep_fps_value = ctk.BooleanVar(value=roop.globals.keep_fps) keep_fps_checkbox = ctk.CTkSwitch(root, text='Keep fps', variable=keep_fps_value, command=lambda: setattr(roop.globals, 'keep_fps', not roop.globals.keep_fps)) keep_fps_checkbox.place(relx=base_x1, rely=base_y) keep_frames_value = ctk.BooleanVar(value=roop.globals.keep_frames) keep_frames_switch = ctk.CTkSwitch(root, text='Keep frames', variable=keep_frames_value, command=lambda: setattr(roop.globals, 'keep_frames', keep_frames_value.get())) keep_frames_switch.place(relx=base_x1, rely=0.68) skip_audio_value = ctk.BooleanVar(value=roop.globals.skip_audio) skip_audio_switch = ctk.CTkSwitch(root, text='Skip audio', variable=skip_audio_value, command=lambda: setattr(roop.globals, 'skip_audio', skip_audio_value.get())) skip_audio_switch.place(relx=base_x2, rely=base_y) many_faces_value = ctk.BooleanVar(value=roop.globals.many_faces) many_faces_switch = ctk.CTkSwitch(root, text='Many faces', variable=many_faces_value, command=lambda: setattr(roop.globals, 'many_faces', many_faces_value.get())) many_faces_switch.place(relx=base_x2, rely=0.68) use_batch_value = ctk.BooleanVar(value=roop.globals.use_batch) use_batch_switch = ctk.CTkSwitch(root, text='Batch process folder', variable=use_batch_value, command=lambda: setattr(roop.globals, 'use_batch', use_batch_value.get())) use_batch_switch.place(relx=base_x1, rely=0.725) base_y = 0.84 start_button = ctk.CTkButton(root, text='Start', command=lambda: select_output_path(start)) start_button.place(relx=base_x1, rely=base_y, relwidth=0.15, relheight=0.05) stop_button = ctk.CTkButton(root, text='Destroy', command=lambda: destroy()) stop_button.place(relx=0.35, rely=base_y, relwidth=0.15, relheight=0.05) preview_button = ctk.CTkButton(root, text='Preview', command=lambda: toggle_preview()) preview_button.place(relx=0.55, rely=base_y, relwidth=0.15, relheight=0.05) result_button = ctk.CTkButton(root, text='Show Result', command=lambda: show_result()) result_button.place(relx=0.75, rely=base_y, relwidth=0.15, relheight=0.05) status_label = ctk.CTkLabel(root, text=None, justify='center') status_label.place(relx=base_x1, rely=0.9, relwidth=0.8) donate_label = ctk.CTkLabel(root, text='Visit the Github Page', justify='center', cursor='hand2') donate_label.place(relx=0.1, rely=0.95, relwidth=0.8) donate_label.configure(text_color=ctk.ThemeManager.theme.get('RoopDonate').get('text_color')) donate_label.bind('