wenhongquan преди 1 седмица
родител
ревизия
d7bcb6dbd7
променени са 4 файла, в които са добавени 138 реда и са изтрити 70 реда
  1. 20 6
      dual_camera_system/config/system.py
  2. 47 30
      dual_camera_system/coordinator.py
  3. 15 3
      dual_camera_system/safety_coordinator.py
  4. 56 31
      dual_camera_system/safety_main.py

+ 20 - 6
dual_camera_system/config/system.py

@@ -10,16 +10,30 @@ SYSTEM_CONFIG = {
     'name': '施工现场安全行为智能识别系统',
     'version': '2.0.0',
     
-    # 功能开关
-    'enable_safety_detection': True,     # 启用安全检测
-    'enable_event_push': True,           # 启用事件推送
-    'enable_voice_announce': True,       # 启用语音播报
+    # === 功能开关 ===
+    # 摄像头模块
+    'enable_panorama_camera': True,      # 启用全景摄像头
+    'enable_ptz_camera': True,           # 启用 PTZ 球机
+    
+    # 检测模块
+    'enable_detection': True,            # 启用人体检测 (YOLO)
+    'enable_safety_detection': True,     # 启用安全检测 (安全帽/反光衣)
+    
+    # 联动与校准
+    'enable_calibration': True,          # 启用自动校准
+    'enable_ptz_tracking': True,         # 启用 PTZ 跟踪联动
+    
+    # OCR 与大模型
     'enable_ocr': True,                  # 启用 OCR 编号识别
     'enable_llm': True,                  # 启用大模型判断
     
-    # 工作模式
+    # 事件与播报
+    'enable_event_push': True,           # 启用事件推送
+    'enable_voice_announce': True,       # 启用语音播报
+    
+    # === 工作模式 ===
     'mode': 'safety',                    # 工作模式: 'safety'(安全检测), 'ocr'(编号识别)
     
-    # 安全判断策略
+    # === 安全判断策略 ===
     'safety_strategy': 'hybrid',         # 'llm'(仅大模型), 'rule'(仅规则), 'hybrid'(混合)
 }

+ 47 - 30
dual_camera_system/coordinator.py

@@ -12,7 +12,7 @@ from enum import Enum
 
 import numpy as np
 
-from config import COORDINATOR_CONFIG
+from config import COORDINATOR_CONFIG, SYSTEM_CONFIG
 from panorama_camera import PanoramaCamera, ObjectDetector, PersonTracker, DetectedObject
 from ptz_camera import PTZCamera, PTZController
 from ocr_recognizer import NumberDetector, PersonInfo
@@ -65,6 +65,13 @@ class Coordinator:
         
         self.config = COORDINATOR_CONFIG
         
+        # 功能开关 - 从 SYSTEM_CONFIG 读取
+        self.enable_ptz_camera = SYSTEM_CONFIG.get('enable_ptz_camera', True)
+        self.enable_ptz_tracking = SYSTEM_CONFIG.get('enable_ptz_tracking', True)
+        self.enable_calibration = SYSTEM_CONFIG.get('enable_calibration', True)
+        self.enable_detection = SYSTEM_CONFIG.get('enable_detection', True)
+        self.enable_ocr = SYSTEM_CONFIG.get('enable_ocr', True)
+        
         # 跟踪器
         self.tracker = PersonTracker()
         
@@ -124,7 +131,7 @@ class Coordinator:
         Returns:
             (pan, tilt, zoom)
         """
-        if self.calibrator and self.calibrator.is_calibrated():
+        if self.enable_calibration and self.calibrator and self.calibrator.is_calibrated():
             # 使用校准结果进行转换
             pan, tilt = self.calibrator.transform(x_ratio, y_ratio)
             zoom = 8  # 默认变倍
@@ -140,21 +147,26 @@ class Coordinator:
         Returns:
             是否成功
         """
-        # 连接摄像头
+        # 连接全景摄像头
         if not self.panorama.connect():
             print("连接全景摄像头失败")
             return False
         
-        if not self.ptz.connect():
-            print("连接球机失败")
-            self.panorama.disconnect()
-            return False
+        # 连接 PTZ 球机 (可选)
+        if self.enable_ptz_camera:
+            if not self.ptz.connect():
+                print("连接球机失败")
+                self.panorama.disconnect()
+                return False
+        else:
+            print("PTZ 球机功能已禁用")
         
         # 启动视频流
         if not self.panorama.start_stream():
             print("启动视频流失败")
             self.panorama.disconnect()
-            self.ptz.disconnect()
+            if self.enable_ptz_camera:
+                self.ptz.disconnect()
             return False
         
         # 启动联动线程
@@ -173,7 +185,9 @@ class Coordinator:
             self.coordinator_thread.join(timeout=3)
         
         self.panorama.disconnect()
-        self.ptz.disconnect()
+        
+        if self.enable_ptz_camera:
+            self.ptz.disconnect()
         
         # 打印统计信息
         self._print_stats()
@@ -265,7 +279,7 @@ class Coordinator:
     
     def _detect_persons(self, frame: np.ndarray) -> List[DetectedObject]:
         """检测人体"""
-        if self.detector is None:
+        if not self.enable_detection or self.detector is None:
             return []
         return self.detector.detect_persons(frame)
     
@@ -320,29 +334,31 @@ class Coordinator:
                 self.current_target = self.tracking_targets[target_id]
         
         if self.current_target:
-            # 移动球机到目标位置
-            self._set_state(TrackingState.TRACKING)
-            
-            x_ratio, y_ratio = self.current_target.position
-            
-            # 检查位置是否变化超过阈值
-            should_move = True
-            if self.last_ptz_position is not None:
-                last_x, last_y = self.last_ptz_position
-                if (abs(x_ratio - last_x) < self.ptz_position_threshold and
-                    abs(y_ratio - last_y) < self.ptz_position_threshold):
-                    should_move = False
-            
-            if should_move:
-                self.ptz.track_target(x_ratio, y_ratio)
-                self.last_ptz_position = (x_ratio, y_ratio)
+            # 移动球机到目标位置 (仅在 PTZ 跟踪启用时)
+            if self.enable_ptz_tracking and self.enable_ptz_camera:
+                self._set_state(TrackingState.TRACKING)
+                
+                x_ratio, y_ratio = self.current_target.position
+                
+                # 检查位置是否变化超过阈值
+                should_move = True
+                if self.last_ptz_position is not None:
+                    last_x, last_y = self.last_ptz_position
+                    if (abs(x_ratio - last_x) < self.ptz_position_threshold and
+                        abs(y_ratio - last_y) < self.ptz_position_threshold):
+                        should_move = False
+                
+                if should_move:
+                    self.ptz.track_target(x_ratio, y_ratio)
+                    self.last_ptz_position = (x_ratio, y_ratio)
             
-            # 执行OCR识别
-            self._perform_ocr(frame, self.current_target)
+            # 执行OCR识别 (仅在 OCR 启用时)
+            if self.enable_ocr:
+                self._perform_ocr(frame, self.current_target)
     
     def _perform_ocr(self, frame: np.ndarray, target: TrackingTarget):
         """执行OCR识别"""
-        if self.number_detector is None:
+        if not self.enable_ocr or self.number_detector is None:
             return
         
         # 频率控制 - 避免过于频繁调用OCR API
@@ -454,7 +470,8 @@ class Coordinator:
             y_ratio: Y方向比例
             zoom: 变倍
         """
-        self.ptz.move_to_target(x_ratio, y_ratio, zoom)
+        if self.enable_ptz_tracking and self.enable_ptz_camera:
+            self.ptz.move_to_target(x_ratio, y_ratio, zoom)
     
     def capture_snapshot(self) -> Optional[np.ndarray]:
         """

+ 15 - 3
dual_camera_system/safety_coordinator.py

@@ -114,8 +114,14 @@ class SafetyCoordinator:
     
     def _init_components(self):
         """初始化各组件"""
+        # 从 SYSTEM_CONFIG 读取功能开关
+        enable_detection = SYSTEM_CONFIG.get('enable_detection', True)
+        enable_safety_detection = SYSTEM_CONFIG.get('enable_safety_detection', True)
+        enable_event_push = SYSTEM_CONFIG.get('enable_event_push', True)
+        enable_voice_announce = SYSTEM_CONFIG.get('enable_voice_announce', True)
+        
         # 安全检测器
-        if SYSTEM_CONFIG.get('enable_safety_detection', True):
+        if enable_detection and enable_safety_detection:
             try:
                 self.detector = SafetyDetector(
                     model_path=SAFETY_DETECTION_CONFIG.get('model_path'),
@@ -126,17 +132,21 @@ class SafetyCoordinator:
                 print("安全检测器初始化成功")
             except Exception as e:
                 print(f"安全检测器初始化失败: {e}")
+        else:
+            print("安全检测功能已禁用")
         
         # 事件推送器
-        if SYSTEM_CONFIG.get('enable_event_push', True):
+        if enable_event_push:
             try:
                 self.event_pusher = EventPusher(EVENT_PUSHER_CONFIG)
                 print("事件推送器初始化成功")
             except Exception as e:
                 print(f"事件推送器初始化失败: {e}")
+        else:
+            print("事件推送功能已禁用")
         
         # 语音播报器
-        if SYSTEM_CONFIG.get('enable_voice_announce', True):
+        if enable_voice_announce:
             try:
                 self.voice_announcer = VoiceAnnouncer(
                     tts_config=VOICE_ANNOUNCER_CONFIG.get('tts', {}),
@@ -145,6 +155,8 @@ class SafetyCoordinator:
                 print("语音播报器初始化成功")
             except Exception as e:
                 print(f"语音播报器初始化失败: {e}")
+        else:
+            print("语音播报功能已禁用")
         
         # 事件监听器
         if EVENT_LISTENER_CONFIG.get('enabled', True):

+ 56 - 31
dual_camera_system/safety_main.py

@@ -94,9 +94,17 @@ class SafetyMonitorSystem:
         self.event_pusher = None      # 事件推送器
         self.voice_announcer = None   # 语音播报器
         
-        # 功能开关
-        self.use_llm = SYSTEM_CONFIG.get('enable_llm', True)
-        self.use_ocr = SYSTEM_CONFIG.get('enable_ocr', True)
+        # 功能开关 - 从 SYSTEM_CONFIG 读取
+        self.enable_panorama_camera = SYSTEM_CONFIG.get('enable_panorama_camera', True)
+        self.enable_ptz_camera = SYSTEM_CONFIG.get('enable_ptz_camera', True)
+        self.enable_detection = SYSTEM_CONFIG.get('enable_detection', True)
+        self.enable_safety_detection = SYSTEM_CONFIG.get('enable_safety_detection', True)
+        self.enable_calibration = SYSTEM_CONFIG.get('enable_calibration', True)
+        self.enable_ptz_tracking = SYSTEM_CONFIG.get('enable_ptz_tracking', True)
+        self.enable_ocr = SYSTEM_CONFIG.get('enable_ocr', True)
+        self.enable_llm = SYSTEM_CONFIG.get('enable_llm', True)
+        self.enable_event_push = SYSTEM_CONFIG.get('enable_event_push', True)
+        self.enable_voice_announce = SYSTEM_CONFIG.get('enable_voice_announce', True)
         
         # 状态
         self.running = False
@@ -136,16 +144,20 @@ class SafetyMonitorSystem:
         
         # 初始化摄像头
         self.camera_source = camera_source
-        self.camera = SimpleCamera(camera_source)
-        
-        if not self.camera.connect():
-            logger.error("连接摄像头失败")
-            return False
-        
-        logger.info(f"摄像头连接成功: {camera_source}")
+        if self.enable_panorama_camera:
+            self.camera = SimpleCamera(camera_source)
+            
+            if not self.camera.connect():
+                logger.error("连接摄像头失败")
+                return False
+            
+            logger.info(f"摄像头连接成功: {camera_source}")
+        else:
+            self.camera = None
+            logger.info("摄像头功能已禁用")
         
         # 初始化 LLM 大模型服务
-        if self.use_llm:
+        if self.enable_llm:
             try:
                 llm_config = {**LLM_CONFIG}
                 if 'llm_host' in self.config:
@@ -160,22 +172,26 @@ class SafetyMonitorSystem:
                 self.use_llm = False
         
         # 初始化安全检测器 (支持 LLM)
-        try:
-            llm_config = {**LLM_CONFIG} if self.use_llm else None
-            
-            self.detector = LLMSafetyDetector(
-                yolo_model_path=self.config.get('model_path', SAFETY_DETECTION_CONFIG.get('model_path')),
-                llm_config=llm_config,
-                use_gpu=self.config.get('use_gpu', SAFETY_DETECTION_CONFIG.get('use_gpu', True)),
-                use_llm=self.use_llm
-            )
-            logger.info("安全检测器初始化成功")
-        except Exception as e:
-            logger.error(f"安全检测器初始化失败: {e}")
-            return False
+        if self.enable_detection and self.enable_safety_detection:
+            try:
+                llm_config = {**LLM_CONFIG} if self.enable_llm else None
+                
+                self.detector = LLMSafetyDetector(
+                    yolo_model_path=self.config.get('model_path', SAFETY_DETECTION_CONFIG.get('model_path')),
+                    llm_config=llm_config,
+                    use_gpu=self.config.get('use_gpu', SAFETY_DETECTION_CONFIG.get('use_gpu', True)),
+                    use_llm=self.enable_llm
+                )
+                logger.info("安全检测器初始化成功")
+            except Exception as e:
+                logger.error(f"安全检测器初始化失败: {e}")
+                return False
+        else:
+            self.detector = None
+            logger.info("安全检测功能已禁用")
         
         # 初始化编号识别器
-        if self.use_ocr and self.use_llm:
+        if self.enable_ocr and self.enable_llm:
             try:
                 self.number_recognizer = NumberRecognizer(LLM_CONFIG)
                 logger.info("编号识别器初始化成功")
@@ -184,7 +200,7 @@ class SafetyMonitorSystem:
                 self.number_recognizer = None
         
         # 初始化事件推送器
-        if SYSTEM_CONFIG.get('enable_event_push', True):
+        if self.enable_event_push:
             try:
                 push_config = {**EVENT_PUSHER_CONFIG}
                 if 'api_host' in self.config:
@@ -198,7 +214,7 @@ class SafetyMonitorSystem:
                 logger.warning(f"事件推送器初始化失败: {e}")
         
         # 初始化语音播报器
-        if SYSTEM_CONFIG.get('enable_voice_announce', True):
+        if self.enable_voice_announce:
             try:
                 self.voice_announcer = VoiceAnnouncer(
                     tts_config=VOICE_ANNOUNCER_CONFIG.get('tts', {}),
@@ -264,6 +280,13 @@ class SafetyMonitorSystem:
     
     def _detection_worker(self):
         """检测工作线程"""
+        # 检查摄像头和检测是否启用
+        if not self.enable_panorama_camera or not self.enable_detection:
+            logger.info("摄像头或检测功能已禁用,检测线程休眠")
+            while self.running:
+                time.sleep(1)
+            return
+        
         detection_interval = SAFETY_DETECTION_CONFIG.get('detection_interval', 0.1)
         last_detection_time = 0
         
@@ -280,7 +303,7 @@ class SafetyMonitorSystem:
                 current_time = time.time()
                 
                 # 获取帧
-                frame = self.camera.get_frame()
+                frame = self.camera.get_frame() if self.camera else None
                 if frame is None:
                     time.sleep(0.01)
                     continue
@@ -693,18 +716,20 @@ def main():
             print("\n系统初始化失败!")
             return 1
         
-        # 禁用功能
+        # 禁用功能 (命令行参数覆盖配置)
         if args.no_llm:
-            system.use_llm = False
+            system.enable_llm = False
             print("大模型判断已禁用,使用规则判断")
         if args.no_ocr:
-            system.use_ocr = False
+            system.enable_ocr = False
             system.number_recognizer = None
             print("编号识别已禁用")
         if args.no_push:
+            system.enable_event_push = False
             system.event_pusher = None
             print("事件推送已禁用")
         if args.no_voice:
+            system.enable_voice_announce = False
             system.voice_announcer = None
             print("语音播报已禁用")