From 8b96461d1109b30438477c64b80acb8f11856c44 Mon Sep 17 00:00:00 2001 From: KRSHH <136873090+KRSHH@users.noreply.github.com> Date: Fri, 4 Oct 2024 19:46:45 +0530 Subject: [PATCH] Webcam selection --- modules/ui.py | 572 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 426 insertions(+), 146 deletions(-) diff --git a/modules/ui.py b/modules/ui.py index a8c6522..33cc23d 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -3,14 +3,27 @@ import webbrowser import customtkinter as ctk from typing import Callable, Tuple import cv2 +from cv2_enumerate_cameras import enumerate_cameras # Add this import from PIL import Image, ImageOps import modules.globals import modules.metadata -from modules.face_analyser import get_one_face, get_unique_faces_from_target_image, get_unique_faces_from_target_video, add_blank_map, has_valid_map, simplify_maps +from modules.face_analyser import ( + get_one_face, + get_unique_faces_from_target_image, + get_unique_faces_from_target_video, + add_blank_map, + has_valid_map, + simplify_maps, +) from modules.capturer import get_video_frame, get_video_frame_total from modules.processors.frame.core import get_frame_processors_modules -from modules.utilities import is_image, is_video, resolve_relative_path, has_image_extension +from modules.utilities import ( + is_image, + is_video, + resolve_relative_path, + has_image_extension, +) ROOT = None POPUP = None @@ -20,18 +33,18 @@ ROOT_WIDTH = 600 PREVIEW = None PREVIEW_MAX_HEIGHT = 700 -PREVIEW_MAX_WIDTH = 1200 -PREVIEW_DEFAULT_WIDTH = 960 +PREVIEW_MAX_WIDTH = 1200 +PREVIEW_DEFAULT_WIDTH = 960 PREVIEW_DEFAULT_HEIGHT = 540 POPUP_WIDTH = 750 POPUP_HEIGHT = 810 -POPUP_SCROLL_WIDTH = 740, +POPUP_SCROLL_WIDTH = (740,) POPUP_SCROLL_HEIGHT = 700 POPUP_LIVE_WIDTH = 900 POPUP_LIVE_HEIGHT = 820 -POPUP_LIVE_SCROLL_WIDTH = 890, +POPUP_LIVE_SCROLL_WIDTH = (890,) POPUP_LIVE_SCROLL_HEIGHT = 700 MAPPER_PREVIEW_MAX_HEIGHT = 100 @@ -71,14 +84,16 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C global source_label, target_label, status_label ctk.deactivate_automatic_dpi_awareness() - ctk.set_appearance_mode('system') - ctk.set_default_color_theme(resolve_relative_path('ui.json')) + 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'{modules.metadata.name} {modules.metadata.version} {modules.metadata.edition}') + root.title( + f"{modules.metadata.name} {modules.metadata.version} {modules.metadata.edition}" + ) root.configure() - root.protocol('WM_DELETE_WINDOW', lambda: destroy()) + root.protocol("WM_DELETE_WINDOW", lambda: destroy()) source_label = ctk.CTkLabel(root, text=None) source_label.place(relx=0.1, rely=0.1, relwidth=0.3, relheight=0.25) @@ -86,71 +101,171 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C target_label = ctk.CTkLabel(root, text=None) target_label.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.25) - select_face_button = ctk.CTkButton(root, text='Select a face', cursor='hand2', command=lambda: select_source_path()) + select_face_button = ctk.CTkButton( + root, text="Select a face", cursor="hand2", command=lambda: select_source_path() + ) select_face_button.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1) - swap_faces_button = ctk.CTkButton(root, text='↔', cursor='hand2', command=lambda: swap_faces_paths()) + swap_faces_button = ctk.CTkButton( + root, text="↔", cursor="hand2", command=lambda: swap_faces_paths() + ) swap_faces_button.place(relx=0.45, rely=0.4, relwidth=0.1, relheight=0.1) - select_target_button = ctk.CTkButton(root, text='Select a target', cursor='hand2', command=lambda: select_target_path()) + select_target_button = ctk.CTkButton( + root, + text="Select a target", + cursor="hand2", + command=lambda: select_target_path(), + ) select_target_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1) keep_fps_value = ctk.BooleanVar(value=modules.globals.keep_fps) - keep_fps_checkbox = ctk.CTkSwitch(root, text='Keep fps', variable=keep_fps_value, cursor='hand2', command=lambda: setattr(modules.globals, 'keep_fps', not modules.globals.keep_fps)) + keep_fps_checkbox = ctk.CTkSwitch( + root, + text="Keep fps", + variable=keep_fps_value, + cursor="hand2", + command=lambda: setattr( + modules.globals, "keep_fps", not modules.globals.keep_fps + ), + ) keep_fps_checkbox.place(relx=0.1, rely=0.6) keep_frames_value = ctk.BooleanVar(value=modules.globals.keep_frames) - keep_frames_switch = ctk.CTkSwitch(root, text='Keep frames', variable=keep_frames_value, cursor='hand2', command=lambda: setattr(modules.globals, 'keep_frames', keep_frames_value.get())) + keep_frames_switch = ctk.CTkSwitch( + root, + text="Keep frames", + variable=keep_frames_value, + cursor="hand2", + command=lambda: setattr( + modules.globals, "keep_frames", keep_frames_value.get() + ), + ) keep_frames_switch.place(relx=0.1, rely=0.65) # for FRAME PROCESSOR ENHANCER tumbler: - enhancer_value = ctk.BooleanVar(value=modules.globals.fp_ui['face_enhancer']) - enhancer_switch = ctk.CTkSwitch(root, text='Face Enhancer', variable=enhancer_value, cursor='hand2', command=lambda: update_tumbler('face_enhancer',enhancer_value.get())) + enhancer_value = ctk.BooleanVar(value=modules.globals.fp_ui["face_enhancer"]) + enhancer_switch = ctk.CTkSwitch( + root, + text="Face Enhancer", + variable=enhancer_value, + cursor="hand2", + command=lambda: update_tumbler("face_enhancer", enhancer_value.get()), + ) enhancer_switch.place(relx=0.1, rely=0.7) keep_audio_value = ctk.BooleanVar(value=modules.globals.keep_audio) - keep_audio_switch = ctk.CTkSwitch(root, text='Keep audio', variable=keep_audio_value, cursor='hand2', command=lambda: setattr(modules.globals, 'keep_audio', keep_audio_value.get())) + keep_audio_switch = ctk.CTkSwitch( + root, + text="Keep audio", + variable=keep_audio_value, + cursor="hand2", + command=lambda: setattr(modules.globals, "keep_audio", keep_audio_value.get()), + ) keep_audio_switch.place(relx=0.6, rely=0.6) many_faces_value = ctk.BooleanVar(value=modules.globals.many_faces) - many_faces_switch = ctk.CTkSwitch(root, text='Many faces', variable=many_faces_value, cursor='hand2', command=lambda: setattr(modules.globals, 'many_faces', many_faces_value.get())) + many_faces_switch = ctk.CTkSwitch( + root, + text="Many faces", + variable=many_faces_value, + cursor="hand2", + command=lambda: setattr(modules.globals, "many_faces", many_faces_value.get()), + ) many_faces_switch.place(relx=0.6, rely=0.65) # Add color correction toggle button color_correction_value = ctk.BooleanVar(value=modules.globals.color_correction) - color_correction_switch = ctk.CTkSwitch(root, text='Fix Blueish Cam\n(force cv2 to use RGB instead of BGR)', variable=color_correction_value, cursor='hand2', command=lambda: setattr(modules.globals, 'color_correction', color_correction_value.get())) + color_correction_switch = ctk.CTkSwitch( + root, + text="Fix Blueish Cam\n(force cv2 to use RGB instead of BGR)", + variable=color_correction_value, + cursor="hand2", + command=lambda: setattr( + modules.globals, "color_correction", color_correction_value.get() + ), + ) color_correction_switch.place(relx=0.6, rely=0.70) -# nsfw_value = ctk.BooleanVar(value=modules.globals.nsfw_filter) -# nsfw_switch = ctk.CTkSwitch(root, text='NSFW filter', variable=nsfw_value, cursor='hand2', command=lambda: setattr(modules.globals, 'nsfw_filter', nsfw_value.get())) -# nsfw_switch.place(relx=0.6, rely=0.7) + # nsfw_value = ctk.BooleanVar(value=modules.globals.nsfw_filter) + # nsfw_switch = ctk.CTkSwitch(root, text='NSFW filter', variable=nsfw_value, cursor='hand2', command=lambda: setattr(modules.globals, 'nsfw_filter', nsfw_value.get())) + # nsfw_switch.place(relx=0.6, rely=0.7) map_faces = ctk.BooleanVar(value=modules.globals.map_faces) - map_faces_switch = ctk.CTkSwitch(root, text='Map faces', variable=map_faces, cursor='hand2', command=lambda: setattr(modules.globals, 'map_faces', map_faces.get())) + map_faces_switch = ctk.CTkSwitch( + root, + text="Map faces", + variable=map_faces, + cursor="hand2", + command=lambda: setattr(modules.globals, "map_faces", map_faces.get()), + ) map_faces_switch.place(relx=0.1, rely=0.75) - start_button = ctk.CTkButton(root, text='Start', cursor='hand2', command=lambda: analyze_target(start, root)) + start_button = ctk.CTkButton( + root, text="Start", cursor="hand2", command=lambda: analyze_target(start, root) + ) start_button.place(relx=0.15, rely=0.80, relwidth=0.2, relheight=0.05) - stop_button = ctk.CTkButton(root, text='Destroy', cursor='hand2', command=lambda: destroy()) + stop_button = ctk.CTkButton( + root, text="Destroy", cursor="hand2", command=lambda: destroy() + ) stop_button.place(relx=0.4, rely=0.80, relwidth=0.2, relheight=0.05) - preview_button = ctk.CTkButton(root, text='Preview', cursor='hand2', command=lambda: toggle_preview()) + preview_button = ctk.CTkButton( + root, text="Preview", cursor="hand2", command=lambda: toggle_preview() + ) preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05) - live_button = ctk.CTkButton(root, text='Live', cursor='hand2', command=lambda: webcam_preview(root)) - live_button.place(relx=0.40, rely=0.86, relwidth=0.2, relheight=0.05) + # --- Camera Selection --- + camera_label = ctk.CTkLabel(root, text="Select Camera:") + camera_label.place(relx=0.1, rely=0.86, relwidth=0.2, relheight=0.05) - status_label = ctk.CTkLabel(root, text=None, justify='center') + available_cameras = get_available_cameras() + # Convert camera indices to strings for CTkOptionMenu + available_camera_indices, available_camera_strings = available_cameras + camera_variable = ctk.StringVar( + value=( + available_camera_strings[0] + if available_camera_strings + else "No cameras found" + ) + ) + camera_optionmenu = ctk.CTkOptionMenu( + root, variable=camera_variable, values=available_camera_strings + ) + camera_optionmenu.place(relx=0.35, rely=0.86, relwidth=0.25, relheight=0.05) + + live_button = ctk.CTkButton( + root, + text="Live", + cursor="hand2", + command=lambda: webcam_preview( + root, + available_camera_indices[ + available_camera_strings.index(camera_variable.get()) + ], + ), + ) + live_button.place(relx=0.65, rely=0.86, relwidth=0.2, relheight=0.05) + # --- End Camera Selection --- + + status_label = ctk.CTkLabel(root, text=None, justify="center") status_label.place(relx=0.1, rely=0.9, relwidth=0.8) - donate_label = ctk.CTkLabel(root, text='Deep Live Cam', justify='center', cursor='hand2') + donate_label = ctk.CTkLabel( + root, text="Deep Live Cam", 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('URL').get('text_color')) - donate_label.bind('