足部录像版本优化
This commit is contained in:
parent
70cf89501a
commit
97ccc120d7
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user