优化性能;解决图像反转问题
This commit is contained in:
parent
a01f8aa386
commit
c1803c16f1
104
face_rec.py
104
face_rec.py
@ -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)
|
||||
|
||||
# 检查二维码显示是否超时
|
||||
|
||||
Loading…
Reference in New Issue
Block a user