Compare commits

...

11 Commits

Author SHA1 Message Date
Uma Maheshwar Reddy Thipparthi 008af8a135
Merge 0cc4a2216f into f3e83b985c 2025-05-12 10:44:40 +03:00
Kenneth Estanislao f3e83b985c
Merge pull request #1210 from KunjShah01/main
Update __init__.py
2025-05-12 15:14:58 +08:00
Kenneth Estanislao e3e3638b79
Merge pull request #1232 from gboeer/patch-1
Add german localization and fix minor typos
2025-05-12 15:14:32 +08:00
Gordon Böer 75122da389
Create german localization 2025-05-07 13:30:22 +02:00
Gordon Böer 7063bba4b3
fix typos in zh.json 2025-05-07 13:24:54 +02:00
Gordon Böer bdbd7dcfbc
fix typos in ui.py 2025-05-07 13:23:31 +02:00
KUNJ SHAH a64940def7 update 2025-05-05 13:19:46 +00:00
KUNJ SHAH fe4a87e8f2 update 2025-05-05 13:19:29 +00:00
KUNJ SHAH 9ecd2dab83 changes 2025-05-05 13:10:00 +00:00
KUNJ SHAH c9f36eb350
Update __init__.py 2025-05-05 18:29:44 +05:30
maheshreddyy345 0cc4a2216f Fix CUDA configuration issue #1140 - add better error handling and fallback 2025-04-30 06:15:13 -07:00
7 changed files with 226 additions and 45 deletions

46
locales/de.json 100644
View File

@ -0,0 +1,46 @@
{
"Source x Target Mapper": "Quelle x Ziel Zuordnung",
"select a source image": "Wähle ein Quellbild",
"Preview": "Vorschau",
"select a target image or video": "Wähle ein Zielbild oder Video",
"save image output file": "Bildausgabedatei speichern",
"save video output file": "Videoausgabedatei speichern",
"select a target image": "Wähle ein Zielbild",
"source": "Quelle",
"Select a target": "Wähle ein Ziel",
"Select a face": "Wähle ein Gesicht",
"Keep audio": "Audio beibehalten",
"Face Enhancer": "Gesichtsverbesserung",
"Many faces": "Mehrere Gesichter",
"Show FPS": "FPS anzeigen",
"Keep fps": "FPS beibehalten",
"Keep frames": "Frames beibehalten",
"Fix Blueish Cam": "Bläuliche Kamera korrigieren",
"Mouth Mask": "Mundmaske",
"Show Mouth Mask Box": "Mundmaskenrahmen anzeigen",
"Start": "Starten",
"Live": "Live",
"Destroy": "Beenden",
"Map faces": "Gesichter zuordnen",
"Processing...": "Verarbeitung läuft...",
"Processing succeed!": "Verarbeitung erfolgreich!",
"Processing ignored!": "Verarbeitung ignoriert!",
"Failed to start camera": "Kamera konnte nicht gestartet werden",
"Please complete pop-up or close it.": "Bitte das Pop-up komplettieren oder schließen.",
"Getting unique faces": "Einzigartige Gesichter erfassen",
"Please select a source image first": "Bitte zuerst ein Quellbild auswählen",
"No faces found in target": "Keine Gesichter im Zielbild gefunden",
"Add": "Hinzufügen",
"Clear": "Löschen",
"Submit": "Absenden",
"Select source image": "Quellbild auswählen",
"Select target image": "Zielbild auswählen",
"Please provide mapping!": "Bitte eine Zuordnung angeben!",
"At least 1 source with target is required!": "Mindestens eine Quelle mit einem Ziel ist erforderlich!",
"At least 1 source with target is required!": "Mindestens eine Quelle mit einem Ziel ist erforderlich!",
"Face could not be detected in last upload!": "Im letzten Upload konnte kein Gesicht erkannt werden!",
"Select Camera:": "Kamera auswählen:",
"All mappings cleared!": "Alle Zuordnungen gelöscht!",
"Mappings successfully submitted!": "Zuordnungen erfolgreich übermittelt!",
"Source x Target Mapper is already open.": "Quell-zu-Ziel-Zuordnung ist bereits geöffnet."
}

View File

@ -1,11 +1,11 @@
{
"Source x Target Mapper": "Source x Target Mapper",
"select an source image": "选择一个源图像",
"select a source image": "选择一个源图像",
"Preview": "预览",
"select an target image or video": "选择一个目标图像或视频",
"select a target image or video": "选择一个目标图像或视频",
"save image output file": "保存图像输出文件",
"save video output file": "保存视频输出文件",
"select an target image": "选择一个目标图像",
"select a target image": "选择一个目标图像",
"source": "源",
"Select a target": "选择一个目标",
"Select a face": "选择一张脸",
@ -36,11 +36,11 @@
"Select source image": "请选取源图像",
"Select target image": "请选取目标图像",
"Please provide mapping!": "请提供映射",
"Atleast 1 source with target is required!": "至少需要一个来源图像与目标图像相关!",
"At least 1 source with target is required!": "至少需要一个来源图像与目标图像相关!",
"At least 1 source with target is required!": "至少需要一个来源图像与目标图像相关!",
"Face could not be detected in last upload!": "最近上传的图像中没有检测到人脸!",
"Select Camera:": "选择摄像头",
"All mappings cleared!": "所有映射均已清除!",
"Mappings successfully submitted!": "成功提交映射!",
"Source x Target Mapper is already open.": "源 x 目标映射器已打开。"
}
}

View File

@ -0,0 +1,18 @@
import os
import cv2
import numpy as np
# Utility function to support unicode characters in file paths for reading
def imread_unicode(path, flags=cv2.IMREAD_COLOR):
return cv2.imdecode(np.fromfile(path, dtype=np.uint8), flags)
# Utility function to support unicode characters in file paths for writing
def imwrite_unicode(path, img, params=None):
root, ext = os.path.splitext(path)
if not ext:
ext = ".png"
result, encoded_img = cv2.imencode(ext, img, params if params else [])
result, encoded_img = cv2.imencode(f".{ext}", img, params if params is not None else [])
encoded_img.tofile(path)
return True
return False

View File

@ -114,8 +114,46 @@ def encode_execution_providers(execution_providers: List[str]) -> List[str]:
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)]
try:
available_providers = onnxruntime.get_available_providers()
encoded_available_providers = encode_execution_providers(available_providers)
selected_providers = []
unavailable_providers = []
for execution_provider in execution_providers:
provider_found = False
for provider, encoded_provider in zip(available_providers, encoded_available_providers):
if execution_provider in encoded_provider:
selected_providers.append(provider)
provider_found = True
break
if not provider_found:
unavailable_providers.append(execution_provider)
if 'cuda' in [p.lower() for p in unavailable_providers]:
# CUDA was requested but not available
cuda_path = os.environ.get('CUDA_PATH')
if cuda_path:
update_status(f"Warning: CUDA_PATH is set ({cuda_path}) but CUDA wasn't able to be loaded. Check your CUDA installation.", "DLC.CORE")
if os.path.exists(cuda_path):
# CUDA path exists but couldn't be loaded - likely missing DLLs or incorrect configuration
update_status("CUDA path exists but CUDA libraries couldn't be loaded. Check if the CUDA runtime is properly installed.", "DLC.CORE")
else:
update_status("CUDA_PATH is set but the directory doesn't exist. Check your environment variables.", "DLC.CORE")
else:
update_status("CUDA was requested but no CUDA_PATH is set in environment variables.", "DLC.CORE")
# If no providers were selected, fall back to CPU
if not selected_providers:
update_status("Falling back to CPU execution provider.", "DLC.CORE")
selected_providers = ['CPUExecutionProvider']
return selected_providers
except Exception as e:
update_status(f"Error determining execution providers: {str(e)}. Falling back to CPU.", "DLC.CORE")
return ['CPUExecutionProvider']
def suggest_max_memory() -> int:
@ -160,6 +198,56 @@ def release_resources() -> None:
torch.cuda.empty_cache()
def check_cuda_configuration() -> None:
"""
Check CUDA configuration and provide diagnostic information.
This helps users identify issues with their CUDA setup.
"""
if 'cuda' in [p.lower() for p in encode_execution_providers(modules.globals.execution_providers)]:
update_status("CUDA execution provider requested, checking configuration...", "DLC.CUDA")
# Check for CUDA environment variables
cuda_path = os.environ.get('CUDA_PATH')
if cuda_path:
update_status(f"CUDA_PATH is set to: {cuda_path}", "DLC.CUDA")
# Check if the directory exists
if os.path.exists(cuda_path):
update_status("CUDA_PATH directory exists", "DLC.CUDA")
# Check for critical CUDA DLLs on Windows
if platform.system().lower() == 'windows':
cuda_dll_path = os.path.join(cuda_path, 'bin', 'cudart64_*.dll')
import glob
cuda_dlls = glob.glob(cuda_dll_path)
if cuda_dlls:
update_status(f"CUDA Runtime DLLs found: {', '.join(os.path.basename(dll) for dll in cuda_dlls)}", "DLC.CUDA")
else:
update_status("Warning: No CUDA Runtime DLLs found in CUDA_PATH/bin", "DLC.CUDA")
update_status("This may cause CUDA initialization failures", "DLC.CUDA")
else:
update_status("Warning: CUDA_PATH is set but directory doesn't exist", "DLC.CUDA")
else:
update_status("Warning: CUDA_PATH environment variable is not set", "DLC.CUDA")
# Check if CUDA is in PATH
path_env = os.environ.get('PATH', '')
if cuda_path and cuda_path + '\\bin' in path_env:
update_status("CUDA bin directory is in PATH", "DLC.CUDA")
else:
update_status("Warning: CUDA bin directory not found in PATH", "DLC.CUDA")
update_status("This may prevent CUDA libraries from being found", "DLC.CUDA")
# Try CUDA provider availability directly from onnxruntime
available_providers = onnxruntime.get_available_providers()
if 'CUDAExecutionProvider' in available_providers:
update_status("CUDA provider is available in ONNX Runtime", "DLC.CUDA")
else:
update_status("Warning: CUDA provider is not available in ONNX Runtime", "DLC.CUDA")
update_status("Available providers: " + ', '.join(available_providers), "DLC.CUDA")
def pre_check() -> bool:
if sys.version_info < (3, 9):
update_status('Python version is not supported - please upgrade to 3.9 or higher.')
@ -167,6 +255,10 @@ def pre_check() -> bool:
if not shutil.which('ffmpeg'):
update_status('ffmpeg is not installed.')
return False
# Check CUDA configuration if requested
check_cuda_configuration()
return True

View File

@ -19,8 +19,26 @@ def get_face_analyser() -> Any:
global FACE_ANALYSER
if FACE_ANALYSER is None:
FACE_ANALYSER = insightface.app.FaceAnalysis(name='buffalo_l', providers=modules.globals.execution_providers)
FACE_ANALYSER.prepare(ctx_id=0, det_size=(640, 640))
try:
FACE_ANALYSER = insightface.app.FaceAnalysis(name='buffalo_l', providers=modules.globals.execution_providers)
FACE_ANALYSER.prepare(ctx_id=0, det_size=(640, 640))
except Exception as e:
error_msg = str(e)
print(f"[DLC.FACE-ANALYSER] Error initializing face analyser with providers {modules.globals.execution_providers}: {error_msg}")
# If error is CUDA-related, try with CPU provider as fallback
if "cuda" in error_msg.lower() or "gpu" in error_msg.lower():
print("[DLC.FACE-ANALYSER] CUDA error detected. Falling back to CPU provider.")
modules.globals.execution_providers = ['CPUExecutionProvider']
try:
FACE_ANALYSER = insightface.app.FaceAnalysis(name='buffalo_l', providers=modules.globals.execution_providers)
FACE_ANALYSER.prepare(ctx_id=0, det_size=(640, 640))
print("[DLC.FACE-ANALYSER] Successfully initialized with CPU provider as fallback.")
except Exception as fallback_error:
print(f"[DLC.FACE-ANALYSER] Failed to initialize even with fallback provider: {str(fallback_error)}")
raise
else:
raise
return FACE_ANALYSER

View File

@ -61,9 +61,29 @@ def get_face_swapper() -> Any:
with THREAD_LOCK:
if FACE_SWAPPER is None:
model_path = os.path.join(models_dir, "inswapper_128_fp16.onnx")
FACE_SWAPPER = insightface.model_zoo.get_model(
model_path, providers=modules.globals.execution_providers
)
try:
FACE_SWAPPER = insightface.model_zoo.get_model(
model_path, providers=modules.globals.execution_providers
)
update_status(f"Successfully loaded model with providers: {modules.globals.execution_providers}", NAME)
except Exception as e:
error_msg = str(e)
update_status(f"Error loading model with selected providers: {error_msg}", NAME)
# If the error is related to CUDA, provide more helpful information
if "cuda" in error_msg.lower() or "gpu" in error_msg.lower():
update_status("CUDA error detected. Trying to load with CPU provider instead.", NAME)
modules.globals.execution_providers = ['CPUExecutionProvider']
try:
FACE_SWAPPER = insightface.model_zoo.get_model(
model_path, providers=modules.globals.execution_providers
)
update_status("Successfully loaded model with CPU provider as fallback.", NAME)
except Exception as fallback_error:
update_status(f"Failed to load model even with fallback provider: {str(fallback_error)}", NAME)
raise
else:
raise
return FACE_SWAPPER
@ -430,37 +450,24 @@ def draw_mouth_mask_visualization(
feathered_mask = cv2.GaussianBlur(
mask_region.astype(float), (kernel_size, kernel_size), 0
)
feathered_mask = (feathered_mask / feathered_mask.max() * 255).astype(np.uint8)
# Remove the feathered mask color overlay
# color_feathered_mask = cv2.applyColorMap(feathered_mask, cv2.COLORMAP_VIRIDIS)
feathered_mask = feathered_mask / feathered_mask.max()
# Ensure shapes match before blending feathered mask
# if vis_region.shape == color_feathered_mask.shape:
# blended_feathered = cv2.addWeighted(vis_region, 0.7, color_feathered_mask, 0.3, 0)
# vis_frame[min_y:max_y, min_x:max_x] = blended_feathered
face_mask_roi = face_mask[min_y:max_y, min_x:max_x]
combined_mask = feathered_mask * (face_mask_roi / 255.0)
# Add labels
cv2.putText(
vis_frame,
"Lower Mouth Mask",
(min_x, min_y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(255, 255, 255),
1,
)
cv2.putText(
vis_frame,
"Feathered Mask",
(min_x, max_y + 20),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(255, 255, 255),
1,
combined_mask = combined_mask[:, :, np.newaxis]
blended = (
color_corrected_mouth * combined_mask + vis_region * (1 - combined_mask)
).astype(np.uint8)
# Apply face mask to blended result
face_mask_3channel = (
np.repeat(face_mask_roi[:, :, np.newaxis], 3, axis=2) / 255.0
)
final_blend = blended * face_mask_3channel + vis_region * (1 - face_mask_3channel)
return vis_frame
return frame
vis_frame[min_y:max_y, min_x:max_x] = final_blend.astype(np.uint8)
return vis_frame
def apply_mouth_area(

View File

@ -429,7 +429,7 @@ def create_source_target_popup(
POPUP.destroy()
select_output_path(start)
else:
update_pop_status("Atleast 1 source with target is required!")
update_pop_status("At least 1 source with target is required!")
scrollable_frame = ctk.CTkScrollableFrame(
POPUP, width=POPUP_SCROLL_WIDTH, height=POPUP_SCROLL_HEIGHT
@ -489,7 +489,7 @@ def update_popup_source(
global source_label_dict
source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"),
title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft],
)
@ -584,7 +584,7 @@ def select_source_path() -> None:
PREVIEW.withdraw()
source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"),
title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft],
)
@ -627,7 +627,7 @@ def select_target_path() -> None:
PREVIEW.withdraw()
target_path = ctk.filedialog.askopenfilename(
title=_("select an target image or video"),
title=_("select a target image or video"),
initialdir=RECENT_DIRECTORY_TARGET,
filetypes=[img_ft, vid_ft],
)
@ -1108,7 +1108,7 @@ def update_webcam_source(
global source_label_dict_live
source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"),
title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft],
)
@ -1160,7 +1160,7 @@ def update_webcam_target(
global target_label_dict_live
target_path = ctk.filedialog.askopenfilename(
title=_("select an target image"),
title=_("select a target image"),
initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft],
)