优化性能;解决图像反转问题

This commit is contained in:
Tian jianyong 2025-12-26 15:34:25 +08:00
parent a01f8aa386
commit c1803c16f1

View File

@ -57,6 +57,10 @@ class FaceRecognitionSystem:
# 识别记录(防止重复识别)
self.recognition_history = {} # {person_id: last_recognition_time}
# 定期清理机制
self.last_cleanup_time = time.time()
self.cleanup_interval = 60 # 清理间隔(秒)
# 显示相关变量
self.current_display_frame = None
self.last_detection_result = None # 最后的检测结果
@ -107,7 +111,7 @@ class FaceRecognitionSystem:
self.stream_retry_cooldown = 10 # 重试冷却时间(秒)
# 添加异步推流队列和线程
self.stream_frame_queue = queue.Queue(maxsize=10) # 限制队列大小防止内存溢出
self.stream_frame_queue = queue.Queue(maxsize=30) # 增加到30帧缓冲
self.stream_thread = None
self.stream_thread_running = False
@ -119,6 +123,9 @@ class FaceRecognitionSystem:
self.camera_retry_cooldown = 3 # 重试冷却时间(秒)
self.camera_max_failures = 5 # 触发重新初始化的失败次数阈值
# 缓存屏幕尺寸,避免每帧重新获取
self._cache_screen_size()
# 二维码显示相关
self.qrcode_image_path = self.config.get('qrcode', {}).get('image_path', 'qrcode.png')
self.qrcode_display_duration = self.config.get('qrcode', {}).get('display_duration', 10)
@ -139,6 +146,22 @@ class FaceRecognitionSystem:
self.stderr_thread = None
self.stderr_thread_running = False
# 缓存屏幕尺寸,避免每帧重新获取
self._cache_screen_size()
def _cache_screen_size(self):
"""缓存屏幕尺寸,提高性能"""
self.screen_width = 1920
self.screen_height = 1080
try:
import screeninfo
screen = screeninfo.get_monitors()[0]
self.screen_width = screen.width
self.screen_height = screen.height
self.logger.info(f"屏幕尺寸已缓存: {self.screen_width}x{self.screen_height}")
except Exception as e:
self.logger.debug(f"无法获取屏幕尺寸,使用默认尺寸: {e}")
def _force_cleanup_ffmpeg(self):
"""强制清理所有FFmpeg相关资源 - 防止多进程推流"""
self.logger.info("=== 开始清理FFmpeg资源 ===")
@ -361,17 +384,8 @@ class FaceRecognitionSystem:
# 在视频帧上绘制机器人状态
frame_with_status = self._draw_robot_status_on_video(frame)
# 获取屏幕尺寸并拉伸视频帧到全屏
try:
import screeninfo
screen = screeninfo.get_monitors()[0]
screen_width, screen_height = screen.width, screen.height
# 拉伸视频帧到屏幕尺寸
frame_with_status = cv2.resize(frame_with_status, (screen_width, screen_height), interpolation=cv2.INTER_LINEAR)
except:
# 如果获取屏幕信息失败,使用默认尺寸
frame_with_status = cv2.resize(frame_with_status, (1920, 1080), interpolation=cv2.INTER_LINEAR)
# 使用缓存的屏幕尺寸拉伸视频帧到全屏
frame_with_status = cv2.resize(frame_with_status, (self.screen_width, self.screen_height), interpolation=cv2.INTER_LINEAR)
# 显示视频帧
cv2.imshow(self.video_window_name, frame_with_status)
@ -678,20 +692,11 @@ class FaceRecognitionSystem:
# 创建二维码窗口
cv2.namedWindow(self.qrcode_window_name, cv2.WINDOW_NORMAL | cv2.WINDOW_GUI_NORMAL)
qr_height, qr_width = qr_image.shape[:2]
try:
import screeninfo
screen = screeninfo.get_monitors()[0]
canvas_width = int(screen.width)
canvas_height = int(screen.height)
x_pos = 0
y_pos = 0
except Exception as e:
self.logger.warning(f"无法获取屏幕信息,使用默认尺寸: {e}")
canvas_width = max(qr_width * 2, 1920)
canvas_height = max(qr_height, 1080)
x_pos = 0
y_pos = 0
# 使用缓存的屏幕尺寸
canvas_width = self.screen_width
canvas_height = self.screen_height
x_pos = 0
y_pos = 0
rendered = self._build_qrcode_instruction_canvas(qr_image, (canvas_width, canvas_height))
if rendered is None:
@ -1098,8 +1103,8 @@ class FaceRecognitionSystem:
if self.ffmpeg_process.stdin and not self.ffmpeg_process.stdin.closed:
# 简单的写入依赖较小的缓冲区和flush_packets
self.ffmpeg_process.stdin.write(frame_bytes)
# 关键定期flush避免缓冲区堆积
if total_frames % 30 == 0: # 每30帧flush一次
# 每5帧flush一次避免缓冲区堆积
if total_frames % 5 == 0:
self.ffmpeg_process.stdin.flush()
consecutive_failures = 0
@ -1372,6 +1377,28 @@ class FaceRecognitionSystem:
return elapsed >= cooldown
def cleanup_expired_records(self):
"""清理过期的识别记录,防止内存无限增长"""
current_time = time.time()
if current_time - self.last_cleanup_time < self.cleanup_interval:
return
self.last_cleanup_time = current_time
# 清理超过1小时的记录
expiry_seconds = 3600
expired_keys = []
for person_id, last_time in self.recognition_history.items():
if isinstance(last_time, datetime):
elapsed = (datetime.now() - last_time).total_seconds()
if elapsed > expiry_seconds:
expired_keys.append(person_id)
if expired_keys:
for key in expired_keys:
del self.recognition_history[key]
self.logger.debug(f"清理了 {len(expired_keys)} 条过期识别记录")
def cv2_add_chinese_text(self, img: np.ndarray, text: str, position: Tuple[int, int],
font: ImageFont.FreeTypeFont, text_color: Tuple[int, int, int]) -> np.ndarray:
"""在OpenCV图像上添加中文文本"""
@ -1698,6 +1725,9 @@ class FaceRecognitionSystem:
try:
while True:
# 定期清理过期记录,防止内存无限增长
self.cleanup_expired_records()
# 检查机器人角色并显示/隐藏视频
self._check_role_and_display_video()
@ -1879,19 +1909,13 @@ class FaceRecognitionSystem:
# 绘制信息
display_frame = self.draw_info_on_frame(frame)
# 使用缓存的屏幕尺寸拉伸视频帧到全屏
display_frame = cv2.resize(display_frame, (self.screen_width, self.screen_height), interpolation=cv2.INTER_LINEAR)
# 获取屏幕尺寸并拉伸视频帧到全屏
try:
import screeninfo
screen = screeninfo.get_monitors()[0]
screen_width, screen_height = screen.width, screen.height
# 拉伸视频帧到屏幕尺寸
display_frame = cv2.resize(display_frame, (screen_width, screen_height), interpolation=cv2.INTER_LINEAR)
except:
# 如果获取屏幕信息失败,使用默认尺寸
display_frame = cv2.resize(display_frame, (1920, 1080), interpolation=cv2.INTER_LINEAR)
# 镜像翻转:使画面与实际场景一致(取消默认的左右镜像)
display_frame = cv2.flip(display_frame, 1)
cv2.imshow(window_name, display_frame)
# 检查二维码显示是否超时