Update ui.py
DETECT_EVERY_N = 2 reuses cached face positions on alternate frames
This commit is contained in:
+42
-1
@@ -9,10 +9,12 @@ import time
|
|||||||
import json
|
import json
|
||||||
import queue
|
import queue
|
||||||
import threading
|
import threading
|
||||||
|
import numpy as np
|
||||||
import modules.globals
|
import modules.globals
|
||||||
import modules.metadata
|
import modules.metadata
|
||||||
from modules.face_analyser import (
|
from modules.face_analyser import (
|
||||||
get_one_face,
|
get_one_face,
|
||||||
|
get_many_faces,
|
||||||
get_unique_faces_from_target_image,
|
get_unique_faces_from_target_image,
|
||||||
get_unique_faces_from_target_video,
|
get_unique_faces_from_target_video,
|
||||||
add_blank_map,
|
add_blank_map,
|
||||||
@@ -971,16 +973,28 @@ def _capture_thread_func(cap, capture_queue, stop_event):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# How often to run full face detection. On intermediate frames the last
|
||||||
|
# detected face positions are reused, which significantly reduces the
|
||||||
|
# per-frame cost of the processing thread.
|
||||||
|
DETECT_EVERY_N = 2
|
||||||
|
|
||||||
|
|
||||||
def _processing_thread_func(capture_queue, processed_queue, stop_event):
|
def _processing_thread_func(capture_queue, processed_queue, stop_event):
|
||||||
"""Processing thread: takes raw frames from capture_queue, applies face
|
"""Processing thread: takes raw frames from capture_queue, applies face
|
||||||
processing, and puts results into processed_queue. Drops processed frames
|
processing, and puts results into processed_queue. Drops processed frames
|
||||||
when the output queue is full so the UI always gets the latest result."""
|
when the output queue is full so the UI always gets the latest result.
|
||||||
|
|
||||||
|
Uses DETECT_EVERY_N to skip expensive face detection on intermediate
|
||||||
|
frames, reusing cached face positions instead."""
|
||||||
frame_processors = get_frame_processors_modules(modules.globals.frame_processors)
|
frame_processors = get_frame_processors_modules(modules.globals.frame_processors)
|
||||||
source_image = None
|
source_image = None
|
||||||
prev_time = time.time()
|
prev_time = time.time()
|
||||||
fps_update_interval = 0.5
|
fps_update_interval = 0.5
|
||||||
frame_count = 0
|
frame_count = 0
|
||||||
fps = 0
|
fps = 0
|
||||||
|
proc_frame_index = 0
|
||||||
|
cached_target_face = None # cached single-face result
|
||||||
|
cached_many_faces = None # cached many-faces result
|
||||||
|
|
||||||
while not stop_event.is_set():
|
while not stop_event.is_set():
|
||||||
try:
|
try:
|
||||||
@@ -989,6 +1003,8 @@ def _processing_thread_func(capture_queue, processed_queue, stop_event):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
temp_frame = frame.copy()
|
temp_frame = frame.copy()
|
||||||
|
run_detection = (proc_frame_index % DETECT_EVERY_N == 0)
|
||||||
|
proc_frame_index += 1
|
||||||
|
|
||||||
if modules.globals.live_mirror:
|
if modules.globals.live_mirror:
|
||||||
temp_frame = cv2.flip(temp_frame, 1)
|
temp_frame = cv2.flip(temp_frame, 1)
|
||||||
@@ -997,10 +1013,35 @@ def _processing_thread_func(capture_queue, processed_queue, stop_event):
|
|||||||
if source_image is None and modules.globals.source_path:
|
if source_image is None and modules.globals.source_path:
|
||||||
source_image = get_one_face(cv2.imread(modules.globals.source_path))
|
source_image = get_one_face(cv2.imread(modules.globals.source_path))
|
||||||
|
|
||||||
|
# Update face detection cache on detection frames
|
||||||
|
if run_detection or (cached_target_face is None and cached_many_faces is None):
|
||||||
|
if modules.globals.many_faces:
|
||||||
|
cached_many_faces = get_many_faces(temp_frame)
|
||||||
|
cached_target_face = None
|
||||||
|
else:
|
||||||
|
cached_target_face = get_one_face(temp_frame)
|
||||||
|
cached_many_faces = None
|
||||||
|
|
||||||
for frame_processor in frame_processors:
|
for frame_processor in frame_processors:
|
||||||
if frame_processor.NAME == "DLC.FACE-ENHANCER":
|
if frame_processor.NAME == "DLC.FACE-ENHANCER":
|
||||||
if modules.globals.fp_ui["face_enhancer"]:
|
if modules.globals.fp_ui["face_enhancer"]:
|
||||||
temp_frame = frame_processor.process_frame(None, temp_frame)
|
temp_frame = frame_processor.process_frame(None, temp_frame)
|
||||||
|
elif frame_processor.NAME == "DLC.FACE-SWAPPER":
|
||||||
|
# Use cached face positions to skip redundant detection
|
||||||
|
swapped_bboxes = []
|
||||||
|
if modules.globals.many_faces and cached_many_faces:
|
||||||
|
result = temp_frame.copy()
|
||||||
|
for t_face in cached_many_faces:
|
||||||
|
result = frame_processor.swap_face(source_image, t_face, result)
|
||||||
|
if hasattr(t_face, 'bbox') and t_face.bbox is not None:
|
||||||
|
swapped_bboxes.append(t_face.bbox.astype(int))
|
||||||
|
temp_frame = result
|
||||||
|
elif cached_target_face is not None:
|
||||||
|
temp_frame = frame_processor.swap_face(source_image, cached_target_face, temp_frame)
|
||||||
|
if hasattr(cached_target_face, 'bbox') and cached_target_face.bbox is not None:
|
||||||
|
swapped_bboxes.append(cached_target_face.bbox.astype(int))
|
||||||
|
# Apply post-processing (sharpening, interpolation)
|
||||||
|
temp_frame = frame_processor.apply_post_processing(temp_frame, swapped_bboxes)
|
||||||
else:
|
else:
|
||||||
temp_frame = frame_processor.process_frame(source_image, temp_frame)
|
temp_frame = frame_processor.process_frame(source_image, temp_frame)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user