足部录像版本优化

This commit is contained in:
zhaozilong12 2025-08-21 12:04:14 +08:00
parent 70cf89501a
commit 97ccc120d7
2 changed files with 78 additions and 78 deletions

View File

@ -12,7 +12,7 @@ import base64
import numpy as np
from typing import Optional, Dict, Any, Tuple
import logging
from collections import deque
import queue
import gc
try:
@ -60,7 +60,7 @@ class CameraManager(BaseDevice):
# 流控制
self.streaming_thread = None
# 减小缓存长度保留最近2帧即可避免累计占用
self.frame_cache = deque(maxlen=int(config.get('frame_cache_len', 2)))
self.frame_cache = queue.Queue(maxsize=int(config.get('frame_cache_len', 2)))
self.last_frame = None
self.frame_count = 0
self.dropped_frames = 0
@ -82,11 +82,8 @@ class CameraManager(BaseDevice):
'dropped_frames': 0
}
# 全局帧缓存(用于录制)
self.global_frame_cache = {}
self.frame_cache_lock = threading.Lock()
self.max_cache_size = 10
self.cache_timeout = 5.0 # 5秒超时
# 全局帧队列(用于录制)
self.frame_queue = queue.Queue(maxsize=10) # 最大长度10自动丢弃旧帧
# OpenCV优化开关
try:
@ -334,15 +331,29 @@ class CameraManager(BaseDevice):
# 重置丢帧计数
self.dropped_frames = 0
# 保存原始帧到全局缓存(用于录制)
self._save_frame_to_cache(frame, 'camera')
# 保存原始帧到队列(用于录制)
try:
self.frame_queue.put_nowait({
'frame': frame.copy(),
'timestamp': time.time()
})
except queue.Full:
# 队列满时丢弃最旧的帧,添加新帧
try:
self.frame_queue.get_nowait() # 移除最旧的帧
self.frame_queue.put_nowait({
'frame': frame.copy(),
'timestamp': time.time()
})
except queue.Empty:
pass # 队列为空,忽略
# 处理帧(降采样以优化传输负载)
processed_frame = self._process_frame(frame)
# 缓存帧(不复制,减少内存占用)
self.last_frame = processed_frame
self.frame_cache.append(processed_frame)
# # 缓存帧(不复制,减少内存占用)
# self.last_frame = processed_frame
# self.frame_cache.append(processed_frame)
# 发送帧数据
self._send_frame_data(processed_frame)
@ -530,15 +541,7 @@ class CameraManager(BaseDevice):
self.logger.error(f"捕获图像异常: {e}")
return None
def get_latest_frame(self) -> Optional[np.ndarray]:
"""
获取最新帧
Returns:
Optional[np.ndarray]: 最新帧无帧返回None
"""
# 对外提供拷贝,内部保持原对象,避免重复持有
return self.last_frame.copy() if self.last_frame is not None else None
def disconnect(self):
"""
@ -574,12 +577,20 @@ class CameraManager(BaseDevice):
pass
self.cap = None
self.frame_cache.clear()
# 清理帧缓存
while not self.frame_cache.empty():
try:
self.frame_cache.get_nowait()
except queue.Empty:
break
self.last_frame = None
# 清理全局帧缓存
with self.frame_cache_lock:
self.global_frame_cache.clear()
# 清理帧队列
while not self.frame_queue.empty():
try:
self.frame_queue.get_nowait()
except queue.Empty:
break
super().cleanup()
self.logger.info("相机资源清理完成")
@ -618,48 +629,34 @@ class CameraManager(BaseDevice):
self.logger.error(f'保存帧到缓存失败: {e}')
def _get_latest_frame_from_cache(self, frame_type='camera'):
"""缓存获取最新帧"""
"""队列获取最新帧"""
try:
with self.frame_cache_lock:
if frame_type not in self.global_frame_cache:
self.logger.debug(f'缓存中不存在帧类型: {frame_type}, 可用类型: {list(self.global_frame_cache.keys())}')
return None, None
if not self.global_frame_cache[frame_type]:
self.logger.debug(f'帧类型 {frame_type} 的缓存为空')
return None, None
# 清理过期帧
self._cleanup_expired_frames()
if not self.global_frame_cache[frame_type]:
self.logger.debug(f'清理过期帧后,帧类型 {frame_type} 的缓存为空')
return None, None
# 获取最新帧
latest_timestamp = max(self.global_frame_cache[frame_type].keys())
frame_data = self.global_frame_cache[frame_type][latest_timestamp]
return frame_data['frame'].copy(), frame_data['timestamp']
except Exception as e:
self.logger.error(f'从缓存获取帧失败: {e}')
return None, None
def _cleanup_expired_frames(self):
"""清理过期的缓存帧"""
try:
current_time = time.time()
if self.frame_queue.empty():
self.logger.debug('帧队列为空')
return None, None
for frame_type in list(self.global_frame_cache.keys()):
expired_keys = []
for timestamp in self.global_frame_cache[frame_type].keys():
if current_time - timestamp > self.cache_timeout:
expired_keys.append(timestamp)
# 获取队列中的所有帧,保留最新的一个
frames = []
while not self.frame_queue.empty():
try:
frames.append(self.frame_queue.get_nowait())
except queue.Empty:
break
if not frames:
return None, None
# 获取最新帧(最后一个)
latest_frame = frames[-1]
# 将最新帧重新放回队列
try:
self.frame_queue.put_nowait(latest_frame)
except queue.Full:
pass # 队列满时忽略
return latest_frame['frame'].copy(), latest_frame['timestamp']
# 删除过期帧
for key in expired_keys:
del self.global_frame_cache[frame_type][key]
except Exception as e:
self.logger.error(f'清理过期帧失败: {e}')
self.logger.error(f'从队列获取帧失败: {e}')
return None, None

View File

@ -173,14 +173,17 @@ class RecordingManager:
# 初始化屏幕录制写入器
# record_size = self.screen_region[2:4] if self.screen_region else self.screen_size
# print('屏幕写入器的宽高..............',record_size)
self.screen_video_writer = cv2.VideoWriter(
screen_video_path, fourcc, fps, (self.screen_size[0],self.screen_size[1])
)
# self.screen_video_writer = cv2.VideoWriter(
# screen_video_path, fourcc, fps, (self.screen_size[0],self.screen_size[1])
# )
if self.screen_video_writer.isOpened():
# 检查屏幕视频写入器状态(仅在初始化时)
if self.screen_video_writer and self.screen_video_writer.isOpened():
self.logger.info(f'屏幕视频写入器初始化成功: {screen_video_path}')
else:
elif self.screen_video_writer:
self.logger.error(f'屏幕视频写入器初始化失败: {screen_video_path}')
else:
self.logger.info('屏幕录制功能暂时禁用')
# 重置停止事件
self.recording_stop_event.clear()
@ -195,13 +198,13 @@ class RecordingManager:
)
self.feet_recording_thread.start()
if self.screen_video_writer:
self.screen_recording_thread = threading.Thread(
target=self._screen_recording_thread,
daemon=True,
name='ScreenRecordingThread'
)
self.screen_recording_thread.start()
# if self.screen_video_writer:
# self.screen_recording_thread = threading.Thread(
# target=self._screen_recording_thread,
# daemon=True,
# name='ScreenRecordingThread'
# )
# self.screen_recording_thread.start()
result['success'] = True
result['recording_start_time'] = self.recording_start_time.isoformat()