Compare commits
3 Commits
e3a38ec8be
...
5c12a45269
Author | SHA1 | Date |
---|---|---|
|
5c12a45269 | |
|
f164d9234b | |
|
441412e7ae |
15
README.md
15
README.md
|
@ -12,13 +12,6 @@
|
|||
<img src="media/demo.gif" alt="Demo GIF" width="800">
|
||||
</p>
|
||||
|
||||
## Disclaimer
|
||||
###### This software is intended as a productive contribution to the AI-generated media industry. It aims to assist artists with tasks like animating custom characters or using them as models for clothing, etc.
|
||||
|
||||
###### We are aware of the potential for unethical applications and are committed to preventative measures. A built-in check prevents the program from processing inappropriate media (nudity, graphic content, sensitive material like war footage, etc.). We will continue to develop this project responsibly, adhering to the law and ethics. We may shut down the project or add watermarks if legally required.
|
||||
|
||||
###### Users are expected to use this software responsibly and legally. If using a real person's face, obtain their consent and clearly label any output as a deepfake when sharing online. We are not responsible for end-user actions.
|
||||
|
||||
## Quick Start - Pre-built (Windows / Nvidia)
|
||||
<a href="https://hacksider.gumroad.com/l/vccdmm"> <img src="https://github.com/user-attachments/assets/7d993b32-e3e8-4cd3-bbfb-a549152ebdd5" width="285" height="77" />
|
||||
|
||||
|
@ -282,3 +275,11 @@ Looking for a CLI mode? Using the -s/--source argument will make the run program
|
|||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
|
||||
## Disclaimer
|
||||
###### This software is intended as a productive contribution to the AI-generated media industry. It aims to assist artists with tasks like animating custom characters or using them as models for clothing, etc.
|
||||
|
||||
###### We are aware of the potential for unethical applications and are committed to preventative measures. A built-in check prevents the program from processing inappropriate media (nudity, graphic content, sensitive material like war footage, etc.). We will continue to develop this project responsibly, adhering to the law and ethics. We may shut down the project or add watermarks if legally required.
|
||||
|
||||
###### Users are expected to use this software responsibly and legally. If using a real person's face, obtain their consent and clearly label any output as a deepfake when sharing online. We are not responsible for end-user actions.
|
||||
|
|
110
modules/ui.py
110
modules/ui.py
|
@ -26,7 +26,6 @@ from modules.utilities import (
|
|||
has_image_extension,
|
||||
)
|
||||
from modules.video_capture import VideoCapturer
|
||||
from modules.gettext import LanguageManager
|
||||
import platform
|
||||
|
||||
if platform.system() == "Windows":
|
||||
|
@ -64,7 +63,6 @@ RECENT_DIRECTORY_SOURCE = None
|
|||
RECENT_DIRECTORY_TARGET = None
|
||||
RECENT_DIRECTORY_OUTPUT = None
|
||||
|
||||
_ = None
|
||||
preview_label = None
|
||||
preview_slider = None
|
||||
source_label = None
|
||||
|
@ -79,11 +77,9 @@ target_label_dict_live = {}
|
|||
img_ft, vid_ft = modules.globals.file_types
|
||||
|
||||
|
||||
def init(start: Callable[[], None], destroy: Callable[[], None], lang: str) -> ctk.CTk:
|
||||
global ROOT, PREVIEW, _
|
||||
def init(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.CTk:
|
||||
global ROOT, PREVIEW
|
||||
|
||||
lang_manager = LanguageManager(lang)
|
||||
_ = lang_manager._
|
||||
ROOT = create_root(start, destroy)
|
||||
PREVIEW = create_preview(ROOT)
|
||||
|
||||
|
@ -158,27 +154,47 @@ 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)
|
||||
|
||||
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: 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.375, relwidth=0.3, relheight=0.1)
|
||||
|
||||
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)
|
||||
swap_faces_button.place(relx=0.45, rely=0.375, relwidth=0.1, relheight=0.1)
|
||||
|
||||
select_target_button = ctk.CTkButton(
|
||||
root,
|
||||
text=_("Select a target"),
|
||||
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)
|
||||
select_target_button.place(relx=0.6, rely=0.375, relwidth=0.3, relheight=0.1)
|
||||
|
||||
transparency_values = ["25%", "50%", "75%", "100%"]
|
||||
transparency_var = ctk.StringVar(value="100%") # Default to 100%
|
||||
|
||||
def on_transparency_change(value: str):
|
||||
percentage = int(value.strip('%'))
|
||||
opacity = percentage / 100.0
|
||||
modules.globals.opacity = opacity # Save opacity globally for real-time updates
|
||||
update_status(f"Transparency set to {value}")
|
||||
|
||||
transparency_label = ctk.CTkLabel(root, text="Transparency:")
|
||||
transparency_label.place(relx=0.1, rely=0.5, relwidth=0.2, relheight=0.05)
|
||||
|
||||
transparency_dropdown = ctk.CTkOptionMenu(
|
||||
root,
|
||||
values=transparency_values,
|
||||
variable=transparency_var,
|
||||
command=on_transparency_change,
|
||||
)
|
||||
transparency_dropdown.place(relx=0.35, rely=0.5, relwidth=0.25, relheight=0.05)
|
||||
|
||||
keep_fps_value = ctk.BooleanVar(value=modules.globals.keep_fps)
|
||||
keep_fps_checkbox = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Keep fps"),
|
||||
text="Keep fps",
|
||||
variable=keep_fps_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -191,7 +207,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
keep_frames_value = ctk.BooleanVar(value=modules.globals.keep_frames)
|
||||
keep_frames_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Keep frames"),
|
||||
text="Keep frames",
|
||||
variable=keep_frames_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -204,7 +220,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
enhancer_value = ctk.BooleanVar(value=modules.globals.fp_ui["face_enhancer"])
|
||||
enhancer_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Face Enhancer"),
|
||||
text="Face Enhancer",
|
||||
variable=enhancer_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -217,7 +233,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
keep_audio_value = ctk.BooleanVar(value=modules.globals.keep_audio)
|
||||
keep_audio_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Keep audio"),
|
||||
text="Keep audio",
|
||||
variable=keep_audio_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -230,7 +246,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
many_faces_value = ctk.BooleanVar(value=modules.globals.many_faces)
|
||||
many_faces_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Many faces"),
|
||||
text="Many faces",
|
||||
variable=many_faces_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -243,7 +259,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
color_correction_value = ctk.BooleanVar(value=modules.globals.color_correction)
|
||||
color_correction_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Fix Blueish Cam"),
|
||||
text="Fix Blueish Cam",
|
||||
variable=color_correction_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -260,7 +276,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
map_faces = ctk.BooleanVar(value=modules.globals.map_faces)
|
||||
map_faces_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Map faces"),
|
||||
text="Map faces",
|
||||
variable=map_faces,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -274,7 +290,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
show_fps_value = ctk.BooleanVar(value=modules.globals.show_fps)
|
||||
show_fps_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Show FPS"),
|
||||
text="Show FPS",
|
||||
variable=show_fps_value,
|
||||
cursor="hand2",
|
||||
command=lambda: (
|
||||
|
@ -287,7 +303,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
mouth_mask_var = ctk.BooleanVar(value=modules.globals.mouth_mask)
|
||||
mouth_mask_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Mouth Mask"),
|
||||
text="Mouth Mask",
|
||||
variable=mouth_mask_var,
|
||||
cursor="hand2",
|
||||
command=lambda: setattr(modules.globals, "mouth_mask", mouth_mask_var.get()),
|
||||
|
@ -297,7 +313,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
show_mouth_mask_box_var = ctk.BooleanVar(value=modules.globals.show_mouth_mask_box)
|
||||
show_mouth_mask_box_switch = ctk.CTkSwitch(
|
||||
root,
|
||||
text=_("Show Mouth Mask Box"),
|
||||
text="Show Mouth Mask Box",
|
||||
variable=show_mouth_mask_box_var,
|
||||
cursor="hand2",
|
||||
command=lambda: setattr(
|
||||
|
@ -307,22 +323,22 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
show_mouth_mask_box_switch.place(relx=0.6, rely=0.55)
|
||||
|
||||
start_button = ctk.CTkButton(
|
||||
root, text=_("Start"), cursor="hand2", command=lambda: analyze_target(start, root)
|
||||
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()
|
||||
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()
|
||||
root, text="Preview", cursor="hand2", command=lambda: toggle_preview()
|
||||
)
|
||||
preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05)
|
||||
|
||||
# --- Camera Selection ---
|
||||
camera_label = ctk.CTkLabel(root, text=_("Select Camera:"))
|
||||
camera_label = ctk.CTkLabel(root, text="Select Camera:")
|
||||
camera_label.place(relx=0.1, rely=0.86, relwidth=0.2, relheight=0.05)
|
||||
|
||||
available_cameras = get_available_cameras()
|
||||
|
@ -346,7 +362,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.C
|
|||
|
||||
live_button = ctk.CTkButton(
|
||||
root,
|
||||
text=_("Live"),
|
||||
text="Live",
|
||||
cursor="hand2",
|
||||
command=lambda: webcam_preview(
|
||||
root,
|
||||
|
@ -420,7 +436,7 @@ def create_source_target_popup(
|
|||
global POPUP, popup_status_label
|
||||
|
||||
POPUP = ctk.CTkToplevel(root)
|
||||
POPUP.title(_("Source x Target Mapper"))
|
||||
POPUP.title("Source x Target Mapper")
|
||||
POPUP.geometry(f"{POPUP_WIDTH}x{POPUP_HEIGHT}")
|
||||
POPUP.focus()
|
||||
|
||||
|
@ -444,7 +460,7 @@ def create_source_target_popup(
|
|||
|
||||
button = ctk.CTkButton(
|
||||
scrollable_frame,
|
||||
text=_("Select source image"),
|
||||
text="Select source image",
|
||||
command=lambda id=id: on_button_click(map, id),
|
||||
width=DEFAULT_BUTTON_WIDTH,
|
||||
height=DEFAULT_BUTTON_HEIGHT,
|
||||
|
@ -478,7 +494,7 @@ def create_source_target_popup(
|
|||
popup_status_label.grid(row=1, column=0, pady=15)
|
||||
|
||||
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)
|
||||
|
||||
|
@ -489,7 +505,7 @@ def update_popup_source(
|
|||
global source_label_dict
|
||||
|
||||
source_path = ctk.filedialog.askopenfilename(
|
||||
title=_("select an source image"),
|
||||
title="select an source image",
|
||||
initialdir=RECENT_DIRECTORY_SOURCE,
|
||||
filetypes=[img_ft],
|
||||
)
|
||||
|
@ -540,7 +556,7 @@ def create_preview(parent: ctk.CTkToplevel) -> ctk.CTkToplevel:
|
|||
|
||||
preview = ctk.CTkToplevel(parent)
|
||||
preview.withdraw()
|
||||
preview.title(_("Preview"))
|
||||
preview.title("Preview")
|
||||
preview.configure()
|
||||
preview.protocol("WM_DELETE_WINDOW", lambda: toggle_preview())
|
||||
preview.resizable(width=True, height=True)
|
||||
|
@ -556,16 +572,16 @@ def create_preview(parent: ctk.CTkToplevel) -> ctk.CTkToplevel:
|
|||
|
||||
|
||||
def update_status(text: str) -> None:
|
||||
status_label.configure(text=_(text))
|
||||
status_label.configure(text=text)
|
||||
ROOT.update()
|
||||
|
||||
|
||||
def update_pop_status(text: str) -> None:
|
||||
popup_status_label.configure(text=_(text))
|
||||
popup_status_label.configure(text=text)
|
||||
|
||||
|
||||
def update_pop_live_status(text: str) -> None:
|
||||
popup_status_label_live.configure(text=_(text))
|
||||
popup_status_label_live.configure(text=text)
|
||||
|
||||
|
||||
def update_tumbler(var: str, value: bool) -> None:
|
||||
|
@ -584,7 +600,7 @@ def select_source_path() -> None:
|
|||
|
||||
PREVIEW.withdraw()
|
||||
source_path = ctk.filedialog.askopenfilename(
|
||||
title=_("select an source image"),
|
||||
title="select an source image",
|
||||
initialdir=RECENT_DIRECTORY_SOURCE,
|
||||
filetypes=[img_ft],
|
||||
)
|
||||
|
@ -627,7 +643,7 @@ def select_target_path() -> None:
|
|||
|
||||
PREVIEW.withdraw()
|
||||
target_path = ctk.filedialog.askopenfilename(
|
||||
title=_("select an target image or video"),
|
||||
title="select an target image or video",
|
||||
initialdir=RECENT_DIRECTORY_TARGET,
|
||||
filetypes=[img_ft, vid_ft],
|
||||
)
|
||||
|
@ -651,7 +667,7 @@ def select_output_path(start: Callable[[], None]) -> None:
|
|||
|
||||
if is_image(modules.globals.target_path):
|
||||
output_path = ctk.filedialog.asksaveasfilename(
|
||||
title=_("save image output file"),
|
||||
title="save image output file",
|
||||
filetypes=[img_ft],
|
||||
defaultextension=".png",
|
||||
initialfile="output.png",
|
||||
|
@ -659,7 +675,7 @@ def select_output_path(start: Callable[[], None]) -> None:
|
|||
)
|
||||
elif is_video(modules.globals.target_path):
|
||||
output_path = ctk.filedialog.asksaveasfilename(
|
||||
title=_("save video output file"),
|
||||
title="save video output file",
|
||||
filetypes=[vid_ft],
|
||||
defaultextension=".mp4",
|
||||
initialfile="output.mp4",
|
||||
|
@ -962,7 +978,7 @@ def create_source_target_popup_for_webcam(
|
|||
global POPUP_LIVE, popup_status_label_live
|
||||
|
||||
POPUP_LIVE = ctk.CTkToplevel(root)
|
||||
POPUP_LIVE.title(_("Source x Target Mapper"))
|
||||
POPUP_LIVE.title("Source x Target Mapper")
|
||||
POPUP_LIVE.geometry(f"{POPUP_LIVE_WIDTH}x{POPUP_LIVE_HEIGHT}")
|
||||
POPUP_LIVE.focus()
|
||||
|
||||
|
@ -987,14 +1003,14 @@ def create_source_target_popup_for_webcam(
|
|||
popup_status_label_live = ctk.CTkLabel(POPUP_LIVE, text=None, justify="center")
|
||||
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(POPUP_LIVE, text="Add", command=lambda: on_add_click())
|
||||
add_button.place(relx=0.1, rely=0.92, relwidth=0.2, relheight=0.05)
|
||||
|
||||
clear_button = ctk.CTkButton(POPUP_LIVE, text=_("Clear"), command=lambda: on_clear_click())
|
||||
clear_button = ctk.CTkButton(POPUP_LIVE, text="Clear", command=lambda: on_clear_click())
|
||||
clear_button.place(relx=0.4, rely=0.92, relwidth=0.2, relheight=0.05)
|
||||
|
||||
close_button = ctk.CTkButton(
|
||||
POPUP_LIVE, text=_("Submit"), command=lambda: on_submit_click()
|
||||
POPUP_LIVE, text="Submit", command=lambda: on_submit_click()
|
||||
)
|
||||
close_button.place(relx=0.7, rely=0.92, relwidth=0.2, relheight=0.05)
|
||||
|
||||
|
@ -1037,7 +1053,7 @@ def refresh_data(map: list):
|
|||
|
||||
button = ctk.CTkButton(
|
||||
scrollable_frame,
|
||||
text=_("Select source image"),
|
||||
text="Select source image",
|
||||
command=lambda id=id: on_sbutton_click(map, id),
|
||||
width=DEFAULT_BUTTON_WIDTH,
|
||||
height=DEFAULT_BUTTON_HEIGHT,
|
||||
|
@ -1054,7 +1070,7 @@ def refresh_data(map: list):
|
|||
|
||||
button = ctk.CTkButton(
|
||||
scrollable_frame,
|
||||
text=_("Select target image"),
|
||||
text="Select target image",
|
||||
command=lambda id=id: on_tbutton_click(map, id),
|
||||
width=DEFAULT_BUTTON_WIDTH,
|
||||
height=DEFAULT_BUTTON_HEIGHT,
|
||||
|
@ -1104,7 +1120,7 @@ def update_webcam_source(
|
|||
global source_label_dict_live
|
||||
|
||||
source_path = ctk.filedialog.askopenfilename(
|
||||
title=_("select an source image"),
|
||||
title="select an source image",
|
||||
initialdir=RECENT_DIRECTORY_SOURCE,
|
||||
filetypes=[img_ft],
|
||||
)
|
||||
|
@ -1156,7 +1172,7 @@ def update_webcam_target(
|
|||
global target_label_dict_live
|
||||
|
||||
target_path = ctk.filedialog.askopenfilename(
|
||||
title=_("select an target image"),
|
||||
title="select an target image",
|
||||
initialdir=RECENT_DIRECTORY_SOURCE,
|
||||
filetypes=[img_ft],
|
||||
)
|
||||
|
@ -1199,4 +1215,4 @@ def update_webcam_target(
|
|||
target_label_dict_live[button_num] = target_image
|
||||
else:
|
||||
update_pop_live_status("Face could not be detected in last upload!")
|
||||
return map
|
||||
return map
|
||||
|
|
Loading…
Reference in New Issue