Deep-Live-Cam/modules/performance_optimizer.py

76 lines
3.1 KiB
Python

"""
Performance optimization module for Deep-Live-Cam
Provides frame caching, adaptive quality, and FPS optimization
"""
import cv2
import numpy as np
import time
from typing import Dict, Any, Optional, Tuple
import threading
from collections import deque
import modules.globals
class PerformanceOptimizer:
def __init__(self):
self.frame_cache = {}
self.face_cache = {}
self.last_detection_time = 0
self.detection_interval = 0.1 # Detect faces every 100ms
self.adaptive_quality = True
self.target_fps = 30
self.frame_times = deque(maxlen=10)
self.current_fps = 0
self.quality_level = 1.0
self.min_quality = 0.5
self.max_quality = 1.0
def should_detect_faces(self) -> bool:
"""Determine if we should run face detection based on timing"""
current_time = time.time()
if current_time - self.last_detection_time > self.detection_interval:
self.last_detection_time = current_time
return True
return False
def update_fps_stats(self, frame_time: float):
"""Update FPS statistics and adjust quality accordingly"""
self.frame_times.append(frame_time)
if len(self.frame_times) >= 5:
avg_frame_time = sum(self.frame_times) / len(self.frame_times)
self.current_fps = 1.0 / avg_frame_time if avg_frame_time > 0 else 0
if self.adaptive_quality:
self._adjust_quality()
def _adjust_quality(self):
"""Dynamically adjust processing quality based on FPS"""
if self.current_fps < self.target_fps * 0.8: # Below 80% of target
self.quality_level = max(self.min_quality, self.quality_level - 0.1)
self.detection_interval = min(0.2, self.detection_interval + 0.02)
elif self.current_fps > self.target_fps * 0.95: # Above 95% of target
self.quality_level = min(self.max_quality, self.quality_level + 0.05)
self.detection_interval = max(0.05, self.detection_interval - 0.01)
def get_optimal_resolution(self, original_size: Tuple[int, int]) -> Tuple[int, int]:
"""Get optimal processing resolution based on current quality level"""
width, height = original_size
scale = self.quality_level
return (int(width * scale), int(height * scale))
def preprocess_frame(self, frame: np.ndarray) -> np.ndarray:
"""Preprocess frame for optimal performance"""
if self.quality_level < 1.0:
height, width = frame.shape[:2]
new_height = int(height * self.quality_level)
new_width = int(width * self.quality_level)
frame = cv2.resize(frame, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
return frame
def postprocess_frame(self, frame: np.ndarray, target_size: Tuple[int, int]) -> np.ndarray:
"""Postprocess frame to target resolution"""
if frame.shape[:2][::-1] != target_size:
frame = cv2.resize(frame, target_size, interpolation=cv2.INTER_CUBIC)
return frame
# Global optimizer instance
performance_optimizer = PerformanceOptimizer()