fix: Resolve circular import between core and face_swapper

Refactors the usage of the update_status function to break a
circular import dependency.

- In modules/processors/frame/face_swapper.py:
  - Removed direct import of update_status from modules.core.
  - Modified pre_start(), process_image(), and process_video()
    to accept update_status as a Callable parameter
    (status_fn_callback).
  - Internal calls now use this passed callback.
- In modules/core.py:
  - Updated the calls to pre_start(), process_image(), and
    process_video() for frame processors (specifically face_swapper)
    to pass the core.update_status function as the
    status_fn_callback argument.

This change ensures that face_swapper.py no longer needs to import
modules.core directly for status updates, resolving the ImportError.
pull/1298/head
google-labs-jules[bot] 2025-06-18 16:53:21 +00:00
parent d7139d5c6e
commit 8a03fccb59
2 changed files with 21 additions and 16 deletions

View File

@ -176,9 +176,12 @@ def update_status(message: str, scope: str = 'DLC.CORE') -> None:
ui.update_status(message) ui.update_status(message)
def start() -> None: def start() -> None:
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors): # Note: pre_start is called in run() before start() now.
if not frame_processor.pre_start(): # If it were to be called here, it would also need the status_fn_callback.
return # For example:
# for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
# if not frame_processor.pre_start(status_fn_callback=update_status): # If pre_start was here
# return
update_status('Processing...') update_status('Processing...')
# process image to image # process image to image
if has_image_extension(modules.globals.target_path): if has_image_extension(modules.globals.target_path):
@ -190,7 +193,7 @@ def start() -> None:
print("Error copying file:", str(e)) print("Error copying file:", str(e))
for frame_processor in get_frame_processors_modules(modules.globals.frame_processors): for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME) update_status('Progressing...', frame_processor.NAME)
frame_processor.process_image(modules.globals.source_path, modules.globals.output_path, modules.globals.output_path) frame_processor.process_image(modules.globals.source_path, modules.globals.output_path, modules.globals.output_path, status_fn_callback=update_status)
release_resources() release_resources()
if is_image(modules.globals.target_path): if is_image(modules.globals.target_path):
update_status('Processing to image succeed!') update_status('Processing to image succeed!')
@ -210,7 +213,7 @@ def start() -> None:
temp_frame_paths = get_temp_frame_paths(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): for frame_processor in get_frame_processors_modules(modules.globals.frame_processors):
update_status('Progressing...', frame_processor.NAME) update_status('Progressing...', frame_processor.NAME)
frame_processor.process_video(modules.globals.source_path, temp_frame_paths) frame_processor.process_video(modules.globals.source_path, temp_frame_paths, status_fn_callback=update_status)
release_resources() release_resources()
# handles fps # handles fps
if modules.globals.keep_fps: if modules.globals.keep_fps:
@ -249,7 +252,9 @@ def run() -> None:
if not pre_check(): 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(): # pre_check in face_swapper does not use update_status
return
if hasattr(frame_processor, 'pre_start') and not frame_processor.pre_start(status_fn_callback=update_status): # Pass callback here
return return
limit_resources() limit_resources()
if modules.globals.headless: if modules.globals.headless:

View File

@ -1,4 +1,4 @@
from typing import Any, List, Optional, Tuple from typing import Any, List, Optional, Tuple, Callable # Added Callable
import cv2 import cv2
import insightface import insightface
import threading import threading
@ -6,7 +6,7 @@ import numpy as np
import modules.globals import modules.globals
import logging import logging
import modules.processors.frame.core import modules.processors.frame.core
from modules.core import update_status # from modules.core import update_status # Removed import
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.hair_segmenter import segment_hair from modules.hair_segmenter import segment_hair
@ -63,19 +63,19 @@ def pre_check() -> bool:
return True return True
def pre_start() -> bool: def pre_start(status_fn_callback: Callable[[str, str], None]) -> 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) status_fn_callback("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) status_fn_callback("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) status_fn_callback("Select an image or video for target path.", NAME)
return False return False
return True return True
@ -569,7 +569,7 @@ def process_frames(
progress.update(1) progress.update(1)
def process_image(source_path: str, target_path: str, output_path: str) -> None: def process_image(source_path: str, target_path: str, output_path: str, status_fn_callback: Callable[[str, str], None]) -> None:
source_img = cv2.imread(source_path) source_img = cv2.imread(source_path)
if source_img is None: if source_img is None:
logging.error(f"Failed to read source image from {source_path}") logging.error(f"Failed to read source image from {source_path}")
@ -593,7 +593,7 @@ def process_image(source_path: str, target_path: str, output_path: str) -> None:
result = process_frame(source_face_obj, source_img, original_target_frame) result = process_frame(source_face_obj, source_img, original_target_frame)
else: else:
if modules.globals.many_faces: if modules.globals.many_faces:
update_status( status_fn_callback(
"Many faces enabled. Using first source image. Progressing...", NAME "Many faces enabled. Using first source image. Progressing...", NAME
) )
result = process_frame_v2(source_img, original_target_frame, target_path) result = process_frame_v2(source_img, original_target_frame, target_path)
@ -604,11 +604,11 @@ def process_image(source_path: str, target_path: str, output_path: str) -> None:
logging.error(f"Processing image {target_path} failed, result was None.") logging.error(f"Processing image {target_path} failed, result was None.")
def process_video(source_path: str, temp_frame_paths: List[str]) -> None: def process_video(source_path: str, temp_frame_paths: List[str], status_fn_callback: Callable[[str, str], None]) -> None:
reset_tracker_state() # Ensure fresh state for each video processing reset_tracker_state() # Ensure fresh state for each video processing
if modules.globals.map_faces and modules.globals.many_faces: if modules.globals.map_faces and modules.globals.many_faces:
update_status( status_fn_callback(
"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(