perf(face-swapper): optimize opacity handling and frame copies
Move opacity calculation before frame copy to skip the copy when opacity is 1.0 (common case). Add early return path for full opacity. Clear PREVIOUS_FRAME_RESULT instead of caching when interpolation is disabled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -137,7 +137,9 @@ def swap_face(source_face: Face, target_face: Face, temp_frame: Frame) -> Frame:
|
|||||||
return temp_frame
|
return temp_frame
|
||||||
|
|
||||||
# Store a copy of the original frame before swapping for opacity blending
|
# Store a copy of the original frame before swapping for opacity blending
|
||||||
original_frame = temp_frame.copy()
|
opacity = getattr(modules.globals, "opacity", 1.0)
|
||||||
|
opacity = max(0.0, min(1.0, opacity))
|
||||||
|
original_frame = temp_frame if opacity >= 1.0 else temp_frame.copy()
|
||||||
|
|
||||||
# Pre-swap Input Check with optimization
|
# Pre-swap Input Check with optimization
|
||||||
if temp_frame.dtype != np.uint8:
|
if temp_frame.dtype != np.uint8:
|
||||||
@@ -240,19 +242,13 @@ def swap_face(source_face: Face, target_face: Face, temp_frame: Frame) -> Frame:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Poisson blending failed: {e}")
|
print(f"Poisson blending failed: {e}")
|
||||||
|
|
||||||
# Apply opacity blend between the original frame and the swapped frame
|
# Apply opacity blend between the original frame and the swapped frame
|
||||||
opacity = getattr(modules.globals, "opacity", 1.0)
|
if opacity >= 1.0:
|
||||||
# Ensure opacity is within valid range [0.0, 1.0]
|
return swapped_frame.astype(np.uint8)
|
||||||
opacity = max(0.0, min(1.0, opacity))
|
|
||||||
|
|
||||||
# Blend the original_frame with the (potentially mouth-masked) swapped_frame
|
# Blend the original_frame with the (potentially mouth-masked) swapped_frame
|
||||||
# Ensure both frames are uint8 before blending
|
|
||||||
final_swapped_frame = gpu_add_weighted(original_frame.astype(np.uint8), 1 - opacity, swapped_frame.astype(np.uint8), opacity, 0)
|
final_swapped_frame = gpu_add_weighted(original_frame.astype(np.uint8), 1 - opacity, swapped_frame.astype(np.uint8), opacity, 0)
|
||||||
|
return final_swapped_frame.astype(np.uint8)
|
||||||
# Ensure final frame is uint8 after blending (addWeighted should preserve it, but belt-and-suspenders)
|
|
||||||
final_swapped_frame = final_swapped_frame.astype(np.uint8)
|
|
||||||
|
|
||||||
return final_swapped_frame
|
|
||||||
|
|
||||||
|
|
||||||
# --- START: Mac M1-M5 Optimized Face Detection ---
|
# --- START: Mac M1-M5 Optimized Face Detection ---
|
||||||
@@ -363,10 +359,8 @@ def apply_post_processing(current_frame: Frame, swapped_face_bboxes: List[np.nda
|
|||||||
pass
|
pass
|
||||||
PREVIOUS_FRAME_RESULT = processed_frame.copy()
|
PREVIOUS_FRAME_RESULT = processed_frame.copy()
|
||||||
else:
|
else:
|
||||||
# If interpolation is off or weight is invalid, just use the current frame
|
# Interpolation is off or weight is invalid — no need to cache
|
||||||
# Update state with the current (potentially sharpened) frame
|
PREVIOUS_FRAME_RESULT = None
|
||||||
# Reset previous frame state if interpolation was just turned off or weight is invalid
|
|
||||||
PREVIOUS_FRAME_RESULT = processed_frame.copy()
|
|
||||||
|
|
||||||
|
|
||||||
return final_frame
|
return final_frame
|
||||||
|
|||||||
Reference in New Issue
Block a user