ソースを参照

refactor(coordinator): 重构联动控制器逻辑提升代码质量

- 重构目标选择器,优化目标得分及选择策略
- 改进跨帧目标跟踪,增强匹配与粘性效果
- 分离检测线程与PTZ控制线程,实现异步联动控制
- 增加多目标PTZ控制支持,支持同时跟踪多个目标
- 新增事件驱动联动控制器,实现基于事件的目标跟踪
- 优化OCR识别流程,加入频率控制减少资源占用
- 增加配对图片保存逻辑,支持人员检测结果批次管理
- 完善统计与日志功能,提供实时性能和状态反馈
- 引入多种功能开关配置,支持灵活启用PTZ、检测及校准功能
- 代码结构调整,提升模块职责分离及易维护性
wenhongquan 2 日 前
コミット
0b79ff3392

BIN
dual_camera_system/__pycache__/coordinator.cpython-310.pyc


+ 27 - 7
dual_camera_system/coordinator.py

@@ -1591,6 +1591,10 @@ class SequentialCoordinator(AsyncCoordinator):
         self._batch_targets_lock = threading.Lock()
         self._current_capture_index = 0
         
+        # 【关键修复】保存当前批次的完整信息,防止抓拍过程中被覆盖
+        self._capture_batch_id: Optional[str] = None
+        self._capture_batch_size: int = 0
+        
         # 抓拍完成事件(用于同步)
         self._capture_done_event = threading.Event()
         
@@ -1753,8 +1757,17 @@ class SequentialCoordinator(AsyncCoordinator):
     def _start_capture_sequence(self, targets: List[TrackingTarget]):
         """开始顺序抓拍序列"""
         with self._batch_targets_lock:
-            self._batch_targets = targets.copy()
+            # 【关键修复】先清空再赋值,防止累积
+            old_count = len(self._batch_targets)
+            self._batch_targets = targets.copy()  # 直接替换,不追加
             self._current_capture_index = 0
+            
+            # 【关键修复】保存批次信息,防止抓拍过程中被新批次覆盖
+            self._capture_batch_id = self._current_batch_id
+            self._capture_batch_size = len(targets)
+            
+            logger.info(f"[顺序模式] 开始抓拍序列: {old_count} -> {len(self._batch_targets)} 个目标, "
+                       f"批次ID={self._capture_batch_id}")
         
         self._set_capture_state('capturing')
     
@@ -1763,10 +1776,12 @@ class SequentialCoordinator(AsyncCoordinator):
         with self._batch_targets_lock:
             targets = self._batch_targets.copy()
             current_idx = self._current_capture_index
+            batch_size = self._capture_batch_size
         
-        if current_idx >= len(targets):
+        # 使用保存的批次大小进行检查,而不是 len(targets)
+        if current_idx >= batch_size:
             # 所有目标已抓拍完成
-            logger.info("[顺序模式] 所有目标抓拍完成")
+            logger.info(f"[顺序模式] 所有目标抓拍完成: {current_idx}/{batch_size}")
             self._set_capture_state('returning')
             return
         
@@ -1785,13 +1800,15 @@ class SequentialCoordinator(AsyncCoordinator):
             pan, tilt, zoom = self.ptz.calculate_ptz_position(x_ratio, y_ratio)
             coord_type = "估算坐标"
         
-        # 获取批次信息
-        batch_id = self._current_batch_id if self._enable_paired_saving else None
+        # 获取批次信息(使用保存的批次ID,防止被新批次覆盖)
+        with self._batch_targets_lock:
+            batch_id = self._capture_batch_id if self._enable_paired_saving else None
+            batch_size = self._capture_batch_size
         person_index = current_idx  # 使用当前索引作为人员序号
         
-        logger.info(f"[顺序模式] 抓拍目标 {current_idx + 1}/{len(targets)}: "
+        logger.info(f"[顺序模式] 抓拍目标 {current_idx + 1}/{batch_size}: "
                    f"位置=({x_ratio:.3f}, {y_ratio:.3f}) -> "
-                   f"PTZ=({pan:.1f}°, {tilt:.1f}°, zoom={zoom}) [{coord_type}]")
+                   f"PTZ=({pan:.1f}°, {tilt:.1f}°, zoom={zoom}) [{coord_type}], 批次={batch_id}")
         
         # 执行PTZ移动
         self._set_state(TrackingState.TRACKING)
@@ -1868,6 +1885,9 @@ class SequentialCoordinator(AsyncCoordinator):
         with self._batch_targets_lock:
             self._batch_targets = []
             self._current_capture_index = 0
+            # 【关键修复】清空保存的批次信息
+            self._capture_batch_id = None
+            self._capture_batch_size = 0
         
         # 【关键修复】清空跟踪目标,防止跨帧累积
         with self.targets_lock: