|
|
@@ -0,0 +1,983 @@
|
|
|
+# 施工现场安全行为智能识别系统 v2.0 — 技术实现架构
|
|
|
+
|
|
|
+> 基于 Python 的施工现场安全行为智能识别系统,支持全景+球机双摄像头联动、YOLO11 实时检测、大模型安全分析、事件推送。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 目录
|
|
|
+
|
|
|
+1. [系统概览](#1-系统概览)
|
|
|
+2. [架构分层与模块职责](#2-架构分层与模块职责)
|
|
|
+3. [核心工作流](#3-核心工作流)
|
|
|
+4. [模块详解](#4-模块详解)
|
|
|
+5. [数据流图](#5-数据流图)
|
|
|
+6. [部署架构](#6-部署架构)
|
|
|
+7. [模型量化与 RKNN 部署](#7-模型量化与-rknn-部署)
|
|
|
+8. [关键技术决策](#8-关键技术决策)
|
|
|
+9. [配置体系](#9-配置体系)
|
|
|
+10. [扩展设计](#10-扩展设计)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. 系统概览
|
|
|
+
|
|
|
+### 1.1 系统上下文 (C4 Context)
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "系统边界"
|
|
|
+ DSS["双摄像头联动系统<br/>Dual-Camera System"]
|
|
|
+ end
|
|
|
+
|
|
|
+ PanoramaCamera["📷 全景摄像头<br/>(Panorama)"]
|
|
|
+ PTZCamera["📷 球机<br/>(PTZ / Dome)"]
|
|
|
+
|
|
|
+ DSS -->|RTSP / SDK| PanoramaCamera
|
|
|
+ DSS -->|RTSP / SDK / PTZ| PTZCamera
|
|
|
+
|
|
|
+ subgraph "外部依赖"
|
|
|
+ LLM["🧠 llama-server<br/>Qwen2.5-VL-7B<br/>安全分析"]
|
|
|
+ BIZ["🏢 业务平台<br/>jtjai.device.wenhq.top:8583"]
|
|
|
+ YOLO["🎯 YOLO11<br/>Ultralytics"]
|
|
|
+ end
|
|
|
+
|
|
|
+ DSS -->|base64 image| LLM
|
|
|
+ DSS -->|HTTP POST| BIZ
|
|
|
+
|
|
|
+ subgraph "操作者"
|
|
|
+ Admin["👤 运维人员<br/>(交互命令行)"]
|
|
|
+ end
|
|
|
+
|
|
|
+ Admin -->|键盘命令| DSS
|
|
|
+```
|
|
|
+
|
|
|
+### 1.2 工作模式
|
|
|
+
|
|
|
+| 入口 | 核心功能 |
|
|
|
+|------|----------|
|
|
|
+| `safety_main.py` | 实时视频监控 → YOLO11 检测(安全帽/反光衣/人) → LLM/规则安全判断 → 事件推送 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. 架构分层与模块职责
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "Entry Layer 入口层"
|
|
|
+ Safety_Main["safety_main.py<br/>安全模式入口"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "Orchestration Layer 编排层"
|
|
|
+ SafetyMonitor["SafetyMonitorSystem<br/>安全监控系统"]
|
|
|
+ SafetyCoord["SafetyCoordinator<br/>安全联动控制器"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "Core Domain Layer 核心领域层"
|
|
|
+ Camera["SimpleCamera<br/>摄像头管理"]
|
|
|
+ ObjectDetector["ObjectDetector / LLMSafetyDetector<br/>YOLO11 安全检测"]
|
|
|
+ PTZCam["PTZCamera<br/>球机 PTZ 控制(可选)"]
|
|
|
+ Calibrator["CameraCalibrator<br/>坐标校准器"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "Infrastructure Layer 基础设施层"
|
|
|
+ SDK["DahuaSDK<br/>大华SDK ctypes 封装"]
|
|
|
+ EventPusher["EventPusher<br/>事件推送"]
|
|
|
+ LLMService["llm_service.py<br/>大模型服务"]
|
|
|
+ ThirdParty["third_party_pusher.py<br/>第三方推送"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "Config Layer 配置层"
|
|
|
+ Config["config/ 模块化配置"]
|
|
|
+ end
|
|
|
+
|
|
|
+ %% 编排关系
|
|
|
+ Safety_Main --> SafetyMonitor
|
|
|
+ Safety_Main --> SafetyCoord
|
|
|
+
|
|
|
+ %% 核心依赖
|
|
|
+ SafetyMonitor --> Camera
|
|
|
+ SafetyMonitor --> ObjectDetector
|
|
|
+ SafetyMonitor --> PTZCam
|
|
|
+ SafetyMonitor --> SDK
|
|
|
+
|
|
|
+ %% 基础设施
|
|
|
+ EventPusher -.->|HTTP| BIZ
|
|
|
+ LLMService -.->|HTTP| LLM
|
|
|
+
|
|
|
+ %% 配置
|
|
|
+ SafetyMonitor -.-> Config
|
|
|
+```
|
|
|
+
|
|
|
+### 2.1 各层职责
|
|
|
+
|
|
|
+| 层 | 职责 | 关键设计原则 |
|
|
|
+|----|------|-------------|
|
|
|
+| **入口层** | CLI 参数解析、信号处理、模式选择 | 统一配置体系 |
|
|
|
+| **编排层** | 组件初始化、生命周期管理、功能开关 | 先 YOLO 后 SDK(避免内存映射冲突) |
|
|
|
+| **核心领域层** | 摄像头控制、YOLO 安全检测推理、PTZ 控制、坐标校准 | 依赖倒置,面向接口 |
|
|
|
+| **基础设施层** | SDK 封装、网络通信、文件系统 | 函数可选绑定、自动降级 |
|
|
|
+| **配置层** | 按功能拆分的模块化配置 | 命令行参数可覆盖配置项 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. 核心工作流
|
|
|
+
|
|
|
+### 3.1 安全模式完整流程
|
|
|
+
|
|
|
+```mermaid
|
|
|
+sequenceDiagram
|
|
|
+ participant Main as safety_main.py
|
|
|
+ participant System as SafetyMonitorSystem
|
|
|
+ participant Camera as SimpleCamera
|
|
|
+ participant Detector as LLMSafetyDetector
|
|
|
+ participant Pusher as EventPusher
|
|
|
+ participant LLM as llama-server
|
|
|
+ participant BIZ as 业务平台
|
|
|
+
|
|
|
+ Main->>System: initialize(camera_source)
|
|
|
+ System->>Camera: connect()
|
|
|
+ System->>Detector: LLMSafetyDetector(yolo, llm_config)
|
|
|
+ System->>Pusher: EventPusher(config)
|
|
|
+
|
|
|
+ Main->>System: start()
|
|
|
+ System->>Pusher: start()
|
|
|
+ System->>System: _detection_worker()
|
|
|
+
|
|
|
+ loop 每 0.5 秒
|
|
|
+ System->>Camera: get_frame()
|
|
|
+ Camera-->>System: frame
|
|
|
+ System->>Detector: detect(frame)
|
|
|
+ Detector->>Detector: YOLO11 inference (安全帽/反光衣/人)
|
|
|
+ Detector-->>System: [SafetyDetection, ...]
|
|
|
+ System->>Detector: check_safety(frame, detections)
|
|
|
+
|
|
|
+ alt 规则模式 (rule)
|
|
|
+ Detector->>Detector: 规则判断: 人和安全帽/反光衣的 IoU 匹配
|
|
|
+ else LLM 模式 (llm)
|
|
|
+ System->>LLM: 发送裁剪后的人体图像
|
|
|
+ LLM-->>System: 安全状态分析结果
|
|
|
+ else 混合模式 (hybrid)
|
|
|
+ Detector->>Detector: 规则初步判断 → LLM 二次验证
|
|
|
+ end
|
|
|
+
|
|
|
+ Detector-->>System: [PersonSafetyStatus, ...]
|
|
|
+
|
|
|
+ loop 每个违规
|
|
|
+ System->>Pusher: push_safety_violation(description, image, ...)
|
|
|
+ Pusher->>BIZ: POST /api/resource/oss/upload (图片)
|
|
|
+ BIZ-->>Pusher: image_url
|
|
|
+ Pusher->>BIZ: POST /api/system/event (事件)
|
|
|
+ BIZ-->>Pusher: ✓
|
|
|
+ end
|
|
|
+ end
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 校准流程
|
|
|
+
|
|
|
+```mermaid
|
|
|
+sequenceDiagram
|
|
|
+ participant System as DualCameraSystem
|
|
|
+ participant Coordinator as AsyncCoordinator
|
|
|
+ participant Calibrator as CameraCalibrator
|
|
|
+ participant Panorama as PanoramaCamera
|
|
|
+ participant PTZ as PTZCamera
|
|
|
+
|
|
|
+ System->>System: _auto_calibrate(force)
|
|
|
+ System->>Coordinator: pause_detection()
|
|
|
+
|
|
|
+ System->>Panorama: connect()
|
|
|
+ System->>PTZ: connect()
|
|
|
+ System->>Panorama: start_stream_rtsp()
|
|
|
+ System->>PTZ: start_stream_rtsp()
|
|
|
+
|
|
|
+ Note over System: 等待视频流稳定 (最长 15s)
|
|
|
+
|
|
|
+ System->>Calibrator: CameraCalibrator(ptz, get_frame, ptz_capture)
|
|
|
+
|
|
|
+ Note over Calibrator: 阶段 1: 视野重叠区域发现
|
|
|
+ Calibrator->>PTZ: 按 (pan_step, tilt_step) 扫描
|
|
|
+ PTZ->>PTZ: goto_exact_position(pan, tilt, 1)
|
|
|
+ Note over PTZ: 等待 stabilize_time(2.0s)
|
|
|
+ Calibrator->>Panorama: get_frame() (移动前)
|
|
|
+ Calibrator->>PTZ: get_frame() (移动后)
|
|
|
+ Calibrator->>Panorama: 帧差法 → 运动区域中心
|
|
|
+ Calibrator->>Calibrator: SIFT/ORB 特征匹配 → 匹配点中心
|
|
|
+ Calibrator->>Calibrator: 加权融合 → 保存校准点
|
|
|
+
|
|
|
+ Note over Calibrator: 阶段 2: 建立坐标映射查找表
|
|
|
+ Calibrator->>Calibrator: 插值生成 (x_ratio, y_ratio) → (pan, tilt) 映射
|
|
|
+ Calibrator->>Calibrator: 保存 calibration.json
|
|
|
+
|
|
|
+ Calibrator-->>System: CalibrationResult
|
|
|
+ alt 成功
|
|
|
+ System->>Coordinator: set_calibrator(calibrator)
|
|
|
+ else 失败
|
|
|
+ System->>System: 日志告警,回退到线性映射
|
|
|
+ end
|
|
|
+
|
|
|
+ System->>Coordinator: resume_detection()
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. 模块详解
|
|
|
+
|
|
|
+### 4.1 联动控制器体系 (coordinator.py)
|
|
|
+
|
|
|
+联动控制器采用**继承+策略模式**,形成清晰的控制器家族:
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ Coordinator["Coordinator<br/>联动控制器基类"] -->|继承| EventDriven["EventDrivenCoordinator<br/>事件驱动模式"]
|
|
|
+ Coordinator -->|继承| AsyncCoord["AsyncCoordinator<br/>异步双线程模式"]
|
|
|
+ AsyncCoord -->|继承| SeqCoord["SequentialCoordinator<br/>顺序抓拍模式"]
|
|
|
+
|
|
|
+ Coordinator -->|组合| TargetSelector["TargetSelector<br/>目标选择策略"]
|
|
|
+
|
|
|
+ subgraph "TargetSelector 策略"
|
|
|
+ TS_area["面积优先<br/>strategy='area'"]
|
|
|
+ TS_conf["置信度优先<br/>strategy='confidence'"]
|
|
|
+ TS_hybrid["混合模式<br/>strategy='hybrid'"]
|
|
|
+ end
|
|
|
+
|
|
|
+ TargetSelector --- TS_area
|
|
|
+ TargetSelector --- TS_conf
|
|
|
+ TargetSelector --- TS_hybrid
|
|
|
+
|
|
|
+ subgraph "TrackingState 状态机"
|
|
|
+ IDLE["IDLE 空闲"]
|
|
|
+ SEARCHING["SEARCHING<br/>搜索目标"]
|
|
|
+ TRACKING["TRACKING 跟踪中"]
|
|
|
+ ZOOMING["ZOOMING 变焦中"]
|
|
|
+ IDLE --> SEARCHING
|
|
|
+ SEARCHING --> TRACKING
|
|
|
+ TRACKING --> ZOOMING
|
|
|
+ ZOOMING --> IDLE
|
|
|
+```
|
|
|
+
|
|
|
+#### 三种控制器模式对比
|
|
|
+
|
|
|
+| 特性 | `Coordinator` (单线程) | `AsyncCoordinator` (异步) | `SequentialCoordinator` (顺序) |
|
|
|
+|------|----------------------|--------------------------|-------------------------------|
|
|
|
+| 线程模型 | 1 个工作线程 | 检测线程 + PTZ 线程 | 检测线程 + PTZ 线程 |
|
|
|
+| 通信方式 | 直接调用 | queue.Queue 命令队列 | queue.Queue + 状态锁 |
|
|
|
+| 目标处理 | 每次选最优目标 | 所有有效目标入队 | 批量捕获后逐个抓拍 |
|
|
|
+| 停顿 | 无 | 无 | PTZ 抓拍时检测暂停 |
|
|
|
+| 适用场景 | 简单联动 | 持续多目标跟踪 | 高质量抓拍 |
|
|
|
+
|
|
|
+#### AsyncCoordinator 关键设计
|
|
|
+
|
|
|
+```
|
|
|
+┌─────────────────────────────────────────────────────┐
|
|
|
+│ AsyncCoordinator │
|
|
|
+│ │
|
|
|
+│ ┌─────────────────────┐ ┌──────────────────────┐ │
|
|
|
+│ │ detection_worker │ │ ptz_worker │ │
|
|
|
+│ │ (检测线程) │ │ (PTZ控制线程) │ │
|
|
|
+│ │ │ │ │ │
|
|
|
+│ │ 1. 读全景帧 │ │ 1. 等待 PTZ 命令 │ │
|
|
|
+│ │ 2. YOLO 推理 │───┼──> 2. 坐标变换 │ │
|
|
|
+│ │ 3. 目标跟踪更新 │ │ 3. goto_exact_position│ │
|
|
|
+│ │ 4. 发 PTZ 命令 │ │ 4. 等待到位(0.3s) │ │
|
|
|
+│ │ 5. 性能日志 │ │ 5. 球机端自检测 │ │
|
|
|
+│ └─────────────────────┘ │ 6. 自动变焦 │ │
|
|
|
+│ │ 7. 获取清晰帧 │ │
|
|
|
+│ │ 8. 保存配对图片 │ │
|
|
|
+│ └──────────────────────┘ │
|
|
|
+│ │
|
|
|
+│ ┌────────────────────────────────────────────────┐ │
|
|
|
+│ │ 共享状态: │ │
|
|
|
+│ │ - tracking_targets: Dict[int, TrackingTarget] │ │
|
|
|
+│ │ - ptz_queue: Queue(maxsize=10) │ │
|
|
|
+│ │ - state: TrackingState (带锁访问) │ │
|
|
|
+│ │ - _paused_event: threading.Event (暂停同步) │ │
|
|
|
+│ └────────────────────────────────────────────────┘ │
|
|
|
+└─────────────────────────────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+#### 目标选择策略 (TargetSelector)
|
|
|
+
|
|
|
+```python
|
|
|
+# 支持三种选择策略
|
|
|
+strategies = {
|
|
|
+ 'area': # 面积优先 — 选择画面中最大目标(默认)
|
|
|
+ 'confidence': # 置信度优先 — 选择检测最可靠目标
|
|
|
+ 'hybrid': # 混合模式 — 面积×权重 + 置信度×权重
|
|
|
+}
|
|
|
+
|
|
|
+# 核心特性
|
|
|
+- 粘性(stickiness): 当前目标得分需显著低于最优目标才切换,避免抖动
|
|
|
+- 中心偏好(prefer_center): 靠近画面中心的目标获得额外分数
|
|
|
+- 面积归一化: log10 对数缩放,避免大目标压倒小目标
|
|
|
+```
|
|
|
+
|
|
|
+### 4.2 大华 SDK 封装 (dahua_sdk.py)
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ SDK["DahuaSDK"] -->|ctypes.CDLL| lib["libdhnetsdk.so"]
|
|
|
+ SDK --> Login["CLIENT_LoginWithHighLevelSecurity"]
|
|
|
+ SDK --> RealPlay["CLIENT_RealPlay / RealPlayEx"]
|
|
|
+ SDK --> PTZCtrl["CLIENT_DHPTZControlEx"]
|
|
|
+ SDK --> Snap["CLIENT_SnapPicture"]
|
|
|
+ SDK --> VideoCallback["CLIENT_SetVideoProcCallBack<br/>(可选绑定)"]
|
|
|
+
|
|
|
+ subgraph "类型映射 (Linux)"
|
|
|
+ DWORD["c_uint32 (4B)"]
|
|
|
+ LONG["c_int (4B)"]
|
|
|
+ LLONG["c_long (8B, LP64)"]
|
|
|
+ BOOL["c_int (非0=真, 0=假)"]
|
|
|
+ end
|
|
|
+
|
|
|
+ SDK -.-> DWORD
|
|
|
+ SDK -.-> LONG
|
|
|
+ SDK -.-> LLONG
|
|
|
+ SDK -.-> BOOL
|
|
|
+
|
|
|
+ subgraph "内存安全"
|
|
|
+ InitOrder["初始化顺序: YOLO → SDK"]
|
|
|
+ OptionalBind["可选函数: 缺失时设为 None"]
|
|
|
+ CBRef["回调引用: 防止 GC"]
|
|
|
+ end
|
|
|
+
|
|
|
+ SDK -.-> InitOrder
|
|
|
+ SDK -.-> OptionalBind
|
|
|
+ SDK -.-> CBRef
|
|
|
+```
|
|
|
+
|
|
|
+**关键设计决策:**
|
|
|
+
|
|
|
+1. **初始化顺序**:先加载 YOLO/PyTorch,再初始化大华 SDK。因为 `CLIENT_Init` 会修改进程内存映射,如果先于 PyTorch 加载会导致 segfault。
|
|
|
+2. **类型映射严格对齐**:Linux 上 `BOOL = int (4 bytes)` 而非 `c_bool (1 byte)`,结构体字段顺序和大小必须与 SDK 头文件完全一致。
|
|
|
+3. **可选函数绑定**:ARM64 版 SDK 缺少 `CLIENT_SetVideoProcCallBack` 等函数,用 `_bind_optional` 处理,缺失时设为 `None` 而非崩溃。
|
|
|
+4. **断线重连**:`CLIENT_Init` 注册断线回调,配合 `auto_reconnect=True` 重连逻辑。
|
|
|
+
|
|
|
+### 4.3 校准模块 (calibration.py)
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "校准方法"
|
|
|
+ Motion["运动检测法<br/>帧差定位球机移动区域"]
|
|
|
+ Feature["特征匹配法<br/>SIFT/ORB 匹配球机与全景画面"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "融合逻辑"
|
|
|
+ Weighted["加权融合<br/>动态权重"]
|
|
|
+ Fallback["降级方案<br/>→ 角度估算"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "校准输出"
|
|
|
+ LUT["校准查找表<br/>[(x_ratio, y_ratio) → (pan, tilt)]"]
|
|
|
+ Interp["双线性插值<br/>非网格点插值"]
|
|
|
+ end
|
|
|
+
|
|
|
+ Motion --> Weighted
|
|
|
+ Feature --> Weighted
|
|
|
+ Weighted -->|成功| LUT
|
|
|
+ Weighted -->|失败| Fallback
|
|
|
+
|
|
|
+ LUT --> Interp
|
|
|
+```
|
|
|
+
|
|
|
+**视野重叠发现机制:**
|
|
|
+
|
|
|
+校准时球机会按 `pan_step=20°, tilt_step=15°` 在 `pan_range=(0,360), tilt_range=(-20,50)` 范围内逐格扫描,在每个位置抓拍并与全景画面做特征匹配,自动发现两台摄像头的视野重叠区域。避免球机指向无重叠区域导致校准失败。
|
|
|
+
|
|
|
+### 4.4 安全检测器 (safety_detector.py)
|
|
|
+
|
|
|
+三种判断策略(`config/system.py → safety_strategy`):
|
|
|
+
|
|
|
+| 策略 | 描述 | 延迟 | 准确率 |
|
|
|
+|------|------|------|--------|
|
|
|
+| `rule` | 规则判断:人和安全帽/反光衣的 IoU 匹配 | 低 | 中等 |
|
|
|
+| `llm` | 仅大模型:发送裁剪图像给 llama-server 分析 | 高 | 高 |
|
|
|
+| `hybrid` | 混合模式:规则初筛 → LLM 二次验证 | 中等 | 最高 |
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph LR
|
|
|
+ Frame["全景帧"] --> YOLO["YOLO11<br/>推理"]
|
|
|
+ YOLO -->|person class| Person["人员检测"]
|
|
|
+ YOLO -->|hat class| Hat["安全帽检测"]
|
|
|
+ YOLO -->|reflective class| Reflective["反光衣检测"]
|
|
|
+
|
|
|
+ Person --> Rule["规则引擎<br/>IoU匹配"]
|
|
|
+
|
|
|
+ Hat --> Rule
|
|
|
+ Reflective --> Rule
|
|
|
+
|
|
|
+ Rule -->|有违规嫌疑| LLM["LLM 二次验证<br/>(hybrid模式)"]
|
|
|
+ Rule -->|明确合规| OK["✓ 合规"]
|
|
|
+ Rule -->|明确违规| Violation["⚠️ 违规"]
|
|
|
+
|
|
|
+ LLM -->|确认违规| Violation
|
|
|
+ LLM -->|确认合规| OK
|
|
|
+
|
|
|
+ Violation --> EventPusher["事件推送"]
|
|
|
+```
|
|
|
+
|
|
|
+**类别映射(YOLO11 安全模型):** `0=安全帽, 3=人, 4=反光衣`
|
|
|
+
|
|
|
+### 4.5 事件推送
|
|
|
+
|
|
|
+```mermaid
|
|
|
+sequenceDiagram
|
|
|
+ participant System as SafetyMonitorSystem
|
|
|
+ participant Pusher as EventPusher
|
|
|
+ participant oSS as OSS Uploader
|
|
|
+ participant BIZ as 业务平台
|
|
|
+
|
|
|
+ System->>Pusher: push_safety_violation(desc, image)
|
|
|
+
|
|
|
+ Pusher->>Pusher: 频率控制 (upload_interval=2.0s)
|
|
|
+
|
|
|
+ Pusher->>oSS: POST /api/resource/oss/upload
|
|
|
+ oSS->>BIZ: 图片二进制
|
|
|
+ BIZ-->>oSS: {url: "https://...jpg"}
|
|
|
+ oSS-->>Pusher: image_url
|
|
|
+
|
|
|
+ Pusher->>BIZ: POST /api/system/event
|
|
|
+ Note over Pusher, BIZ: {eventType, description, imageUrl, trackId, timestamp}
|
|
|
+
|
|
|
+ BIZ-->>Pusher: 200 OK
|
|
|
+
|
|
|
+ alt 推送失败
|
|
|
+ Pusher->>Pusher: 重试 (retry_count=3, retry_delay=1.0s)
|
|
|
+ end
|
|
|
+```
|
|
|
+
|
|
|
+### 4.6 多组摄像头并行管理
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "MultiGroupSystem"
|
|
|
+ SDK_Shared["SDK 共享实例"]
|
|
|
+ Detector_Shared["Detector 共享实例"]
|
|
|
+ Groups["摄像头组列表"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "CameraGroup #1"
|
|
|
+ P1["全景 #1"]
|
|
|
+ Z1["球机 #1"]
|
|
|
+ C1["校准器 #1"]
|
|
|
+ CO1["协调器 #1"]
|
|
|
+ PS1["配对保存器 #1"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "CameraGroup #2"
|
|
|
+ P2["全景 #2"]
|
|
|
+ Z2["球机 #2"]
|
|
|
+ C2["校准器 #2"]
|
|
|
+ CO2["协调器 #2"]
|
|
|
+ PS2["配对保存器 #2"]
|
|
|
+ end
|
|
|
+
|
|
|
+ Groups --> CameraGroup #1
|
|
|
+ Groups --> CameraGroup #2
|
|
|
+
|
|
|
+ SDK_Shared --> P1
|
|
|
+ SDK_Shared --> Z1
|
|
|
+ SDK_Shared --> P2
|
|
|
+ SDK_Shared --> Z2
|
|
|
+
|
|
|
+ Detector_Shared --> CO1
|
|
|
+ Detector_Shared --> CO2
|
|
|
+```
|
|
|
+
|
|
|
+每组(全景+球机)在独立线程中运行,共享 SDK 实例(只需初始化一次)和 YOLO 检测器(模型只加载一次)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. 数据流图
|
|
|
+
|
|
|
+### 5.0 图例说明
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph LR
|
|
|
+ subgraph "图例"
|
|
|
+ A["实体/模块"] -->|"数据流<br/>箭头方向=流向"| B["另一实体"]
|
|
|
+ C[(数据库/存储)]
|
|
|
+ D{"判断/分流"}
|
|
|
+ E["外部服务"]
|
|
|
+ end
|
|
|
+```
|
|
|
+
|
|
|
+### 5.1 安全模式数据流
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ Camera["摄像头源<br/>(索引/RTSP/视频)"] -->|帧| Frame["当前帧"]
|
|
|
+
|
|
|
+ Frame -->|每 0.5s| YOLO["YOLO11 安全推理"]
|
|
|
+ YOLO --> dets["检测列表<br/>安全帽/人/反光衣"]
|
|
|
+
|
|
|
+ dets --> SafetyCheck{"安全判断"}
|
|
|
+ SafetyCheck -->|规则模式| Rule["IoU 匹配<br/>人和 PPE 重合度"]
|
|
|
+ SafetyCheck -->|LLM 模式| LLM["llama-server<br/>图像分析"]
|
|
|
+ SafetyCheck -->|混合模式| Hybrid["规则初筛 → LLM 验证"]
|
|
|
+
|
|
|
+ Rule --> status["PersonSafetyStatus"]
|
|
|
+ LLM --> status
|
|
|
+ Hybrid --> status
|
|
|
+
|
|
|
+ status -->|is_violation| Violation["违规处理"]
|
|
|
+ Violation --> Cooldown{"冷却检查<br/>(3s/违规类型)"}
|
|
|
+ Cooldown -->|通过| Push["推送队列"]
|
|
|
+
|
|
|
+ Push --> PersonCrop["裁剪人体区域"]
|
|
|
+ PersonCrop --> Image["缩放到 640x640"]
|
|
|
+
|
|
|
+ Image --> Upload["OSS 上传<br/>POST /oss/upload"]
|
|
|
+ Upload -->|image_url| Event["事件推送<br/>POST /system/event"]
|
|
|
+
|
|
|
+ Event -->|失败| Retry["重试<br/>(最多3次)"]
|
|
|
+ Event -->|成功| Log["日志记录"]
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. 部署架构
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "服务器端 (x86_64 Linux / RK3588 ARM64)"
|
|
|
+ subgraph "进程边界"
|
|
|
+ subgraph "Python 主进程"
|
|
|
+ Main["safety_main.py<br/>安全模式"]
|
|
|
+ SDK[DahuaSDK<br/>ctypes]
|
|
|
+ YOLO[YOLO11<br/>GPU/NPU]
|
|
|
+ Pusher[事件推送线程]
|
|
|
+ Calib[校准管理线程]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "LLM 推理进程"
|
|
|
+ LlamaServer["llama-server<br/>Qwen2.5-VL-7B-Instruct"]
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "文件系统"
|
|
|
+ CalibFile["calibration.json"]
|
|
|
+ Images["paired_images/"]
|
|
|
+ Models["yolo11m_safety.pt/rknn"]
|
|
|
+ Logs["日志文件<br/>(RotatingFileHandler)"]
|
|
|
+ end
|
|
|
+
|
|
|
+ Main -->|ctypes| SDK
|
|
|
+ Main -->|ultralytics| YOLO
|
|
|
+ Main -->|file I/O| CalibFile
|
|
|
+ Main -->|file I/O| Images
|
|
|
+ Main -->|cv2.imwrite| Images
|
|
|
+ Main -->|httpx| LlamaServer
|
|
|
+ Main -->|logging| Logs
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "网络设备"
|
|
|
+ Pan["📷 全景摄像头<br/>SDK:37777 / RTSP:554"]
|
|
|
+ Dome["📷 球机<br/>SDK:37777 / RTSP:554"]
|
|
|
+ end
|
|
|
+
|
|
|
+ SDK -->|CLIENT_Login / RealPlay / PTZControl| Pan
|
|
|
+ SDK -->|CLIENT_Login / RealPlay / PTZControl| Dome
|
|
|
+ Main -->|RTSP| Pan
|
|
|
+ Main -->|RTSP| Dome
|
|
|
+
|
|
|
+ Main ---->|"场景 1 (有网)"| BIZ["业务平台<br/>jtjai.device.wenhq.top:8583"]
|
|
|
+
|
|
|
+ LlamaServer -->|GPU| GPU["NVIDIA GPU<br/>/ NPU (RK3588)"]
|
|
|
+ YOLO -->|GPU| GPU
|
|
|
+```
|
|
|
+
|
|
|
+### 6.1 硬件规格
|
|
|
+
|
|
|
+| 部署场景 | 处理器 | 加速 | 内存 | SDK 路径 |
|
|
|
+|----------|--------|------|------|----------|
|
|
|
+| 开发机 | macOS (x86_64) | - | - | `dh/Bin` (参考用, .so 不可用) |
|
|
|
+| 服务器 | Linux x86_64 | NVIDIA GPU | ≥16GB | `/home/wen/dsh/dh/Bin` |
|
|
|
+| 测试设备 | Orange Pi (aarch64) | NPU | ≥8GB | `/home/admin/dsh/dh/arm/Bin` |
|
|
|
+
|
|
|
+### 6.2 进程间关系
|
|
|
+
|
|
|
+| 进程 | 通信方式 | 端口 | 职责 |
|
|
|
+|------|----------|------|------|
|
|
|
+| `safety_main.py` | - | - | 主程序(检测→安全判断→推送全链路) |
|
|
|
+| `llama-server` | HTTP REST | 8111 | 视觉语言模型推理(安全分析) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. 模型量化与 RKNN 部署
|
|
|
+
|
|
|
+> ⚠️ 本节内容涉及 RK3588 平台专属的模型量化与 NPU 部署。在 x86_64 服务器上使用 YOLO (.pt) 或 ONNX 推理时,只需参考 [7.4 推理性能](#74-推理性能)。
|
|
|
+
|
|
|
+### 7.1 部署流水线
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph LR
|
|
|
+ subgraph "PC 开发环境"
|
|
|
+ PT["YOLO11 .pt 权重<br/>ultralytics 训练"] -->|export| ONNX["ONNX 模型<br/>(float32 NCHW)"]
|
|
|
+ ONNX -->|onnx2rknn.py| RKNN_tool["RKNN 工具链<br/>rknn-toolkit2"]
|
|
|
+ RKNN_tool -->|build| RKNN["RKNN 模型<br/>(w8a8 量化)"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "RK3588 目标板"
|
|
|
+ RKNN -->|scp 部署| RKNN_Deploy["yolo11m_safety.rknn<br/>~50MB"]
|
|
|
+ RKNN_Deploy -->|rknnlite| Runtime["RKNNLite 运行时"]
|
|
|
+ Runtime -->|NPU_CORE_0_1_2| NPU["NPU 推理<br/>3 核并行"]
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "推理流程"
|
|
|
+ Frame["摄像头帧<br/>BGR uint8"] -->|letterbox| Resized["640×640<br/>保持宽高比"]
|
|
|
+ Resized -->|BGR→RGB /255.0| Normalized["float32 [0,1]<br/>NHWC (1,640,640,3)"]
|
|
|
+ Normalized -->|rknn.inference| NPU
|
|
|
+ NPU -->|output (1,84,8400)| Post["后处理<br/>NMS + 坐标映射"]
|
|
|
+ Post --> dets["检测列表<br/>安全帽/人/反光衣"]
|
|
|
+ end
|
|
|
+```
|
|
|
+
|
|
|
+### 7.2 模型导出与量化
|
|
|
+
|
|
|
+YOLO11 安全检测模型(`yolo11m_safety.pt`)需从 ultralytics 格式转换为 RKNN 格式,使用 `testrk3588/onnx2rknn.py`:
|
|
|
+
|
|
|
+**第一步:ONNX 导出(在 PC 上)**
|
|
|
+
|
|
|
+```bash
|
|
|
+yolo export model=yolo11m_safety.pt format=onnx
|
|
|
+# → 输出 yolo11m_safety.onnx (NCHW, float32)
|
|
|
+```
|
|
|
+
|
|
|
+**第二步:RKNN 量化构建(在 PC 上)**
|
|
|
+
|
|
|
+```python
|
|
|
+from rknn.api import RKNN
|
|
|
+
|
|
|
+rknn = RKNN(verbose=True)
|
|
|
+rknn.config(
|
|
|
+ target_platform='rk3588',
|
|
|
+ mean_values=[[0, 0, 0]], # 不做均值归一化(由应用层处理)
|
|
|
+ std_values=[[1, 1, 1]], # 不做标准差归一化
|
|
|
+ quantized_dtype='w8a8', # 权重量化 int8,激活量化 int8
|
|
|
+ optimization_level=3 # 最高优化等级
|
|
|
+)
|
|
|
+rknn.load_onnx(model='yolo11m_safety.onnx', input_size_list=[[3, 640, 640]])
|
|
|
+rknn.build(dataset='dataset.txt', do_quantization=False) # float32 推理
|
|
|
+rknn.export_rknn('./yolo11m_safety.rknn')
|
|
|
+```
|
|
|
+
|
|
|
+**量化选项决策:**
|
|
|
+
|
|
|
+| 选项 | 配置 | 推理精度 | NPU 加速 | 适用场景 |
|
|
|
+|------|------|----------|----------|----------|
|
|
|
+| float32 (当前) | `do_quantization=False` | 最高 | 中等 | 精度优先 |
|
|
|
+| int8 混合量化 | `do_quantization=True, asymmetric_quantized-u8` | 略低 | 最高 | 性能优先 |
|
|
|
+
|
|
|
+当前采用 **float32 推理 + w8a8 权重量化**,不做激活量化,以保证安全检测的精度。
|
|
|
+
|
|
|
+### 7.3 RK3588 板端推理
|
|
|
+
|
|
|
+**模型加载:**
|
|
|
+
|
|
|
+```python
|
|
|
+from rknnlite.api import RKNNLite
|
|
|
+
|
|
|
+rknn = RKNNLite()
|
|
|
+rknn.load_rknn('yolo11m_safety.rknn')
|
|
|
+rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0_1_2) # 3 核并行
|
|
|
+```
|
|
|
+
|
|
|
+| 参数 | 值 | 说明 |
|
|
|
+|------|-----|------|
|
|
|
+| `core_mask` | `NPU_CORE_0_1_2` | 使用全部 3 个 NPU 核心并行推理 |
|
|
|
+| 模型大小 | ~50MB | yolo11m 级别,约 25M 参数 |
|
|
|
+| 输入尺寸 | 640×640 | letterbox 保持宽高比,不足补 114 灰边 |
|
|
|
+| 输入格式 | NHWC (1,H,W,C) | RKNN 统一 NHWC,与 ONNX 的 NCHW 由工具链自动转换 |
|
|
|
+| 输入类型 | float32 [0,1] | 应用层负责归一化 |
|
|
|
+
|
|
|
+**预处理(`BaseDetector.letterbox`):**
|
|
|
+1. 按比例缩放图像到 640×640 画布内
|
|
|
+2. 剩余区域用 114 灰度填充(保持宽高比)
|
|
|
+3. BGR → RGB 通道转换
|
|
|
+4. `/ 255.0` 归一化到 [0, 1]
|
|
|
+
|
|
|
+**后处理(`BaseDetector.postprocess`):**
|
|
|
+1. 解析输出张量 `(1, 84, 8400)` → 8400 个候选框
|
|
|
+2. 类别过滤(仅保留 class_id ∈ {0, 3, 4})
|
|
|
+3. 置信度阈值过滤(人 ≥ 0.8,安全帽/反光衣 ≥ 0.5)
|
|
|
+4. 非极大值抑制 NMS(IoU 阈值 0.45)
|
|
|
+5. 移除 letterbox padding,缩放到原始图像尺寸
|
|
|
+
|
|
|
+### 7.4 推理性能
|
|
|
+
|
|
|
+| 部署方式 | 设备 | 吞吐量 | 备注 |
|
|
|
+|----------|------|--------|------|
|
|
|
+| YOLO (.pt) | x86_64 + NVIDIA GPU | ~30 FPS | CUDA 加速 |
|
|
|
+| YOLO (.pt) | x86_64 CPU | ~3-5 FPS | 仅 CPU 推理 |
|
|
|
+| RKNN | RK3588 NPU (3 核) | ~15-20 FPS | 实测值,与模型复杂度相关 |
|
|
|
+| ONNX | RK3588 CPU | ~2-3 FPS | 不推荐,仅作为备选 |
|
|
|
+
|
|
|
+系统在 `safety_detector.py` 中通过 `SafetyDetector` 统一封装三种推理后端:
|
|
|
+
|
|
|
+```python
|
|
|
+class SafetyDetector:
|
|
|
+ def __init__(self, model_path, model_type='auto'):
|
|
|
+ # model_type 自动检测:.rknn → rknn, .onnx → onnx, 其他 → yolo
|
|
|
+ if model_type == 'rknn':
|
|
|
+ self.rknn_detector = RKNNDetector(model_path)
|
|
|
+ elif model_type == 'onnx':
|
|
|
+ self.rknn_detector = ONNXDetector(model_path)
|
|
|
+ else:
|
|
|
+ self.model = YOLO(model_path)
|
|
|
+```
|
|
|
+
|
|
|
+### 7.5 测试与验证
|
|
|
+
|
|
|
+测试脚本位于 `testrk3588/` 目录:
|
|
|
+
|
|
|
+| 脚本 | 用途 |
|
|
|
+|------|------|
|
|
|
+| `onnx2rknn.py` | ONNX → RKNN 量化导出 |
|
|
|
+| `test_detection.py` | 单图检测验证 |
|
|
|
+| `rtsp_person_detection.py` | RTSP 实时流检测(含安全判断) |
|
|
|
+| `test_model.py` | 模型加载与推理正确性测试 |
|
|
|
+
|
|
|
+连接到 RK3588 测试设备:
|
|
|
+```bash
|
|
|
+ssh admin@192.168.20.84
|
|
|
+conda activate rknn
|
|
|
+cd /home/admin/dsh/testrk3588
|
|
|
+python rtsp_person_detection.py
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. 关键技术决策
|
|
|
+
|
|
|
+### 8.1 线程模型
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ subgraph "线程模型"
|
|
|
+ MainThread["主线程<br/>CLI / 信号处理"] -->|启动| DetThread["检测线程<br/>(detection_worker)"]
|
|
|
+ MainThread -->|启动| PTZThread["PTZ 线程<br/>(ptz_worker)"]
|
|
|
+ MainThread -->|启动| CalibThread["定时校准线程<br/>(每日 08:00)"]
|
|
|
+ MainThread -->|启动| LogCleanup["日志清理线程<br/>(每 6 小时)"]
|
|
|
+
|
|
|
+ DetThread -->|queue.Queue| PTZThread
|
|
|
+ DetThread -.->|_paused_event| PTZThread
|
|
|
+ MainThread -->|pause/resume| DetThread
|
|
|
+ end
|
|
|
+
|
|
|
+ subgraph "同步原语"
|
|
|
+ Lock["threading.Lock<br/>(targets_lock, state_lock)"]
|
|
|
+ Event["threading.Event<br/>(_paused_event)"]
|
|
|
+ Queue["queue.Queue<br/>(ptz_queue, result_queue)"]
|
|
|
+ end
|
|
|
+```
|
|
|
+
|
|
|
+| 原语 | 用途 | 保护对象 |
|
|
|
+|------|------|---------|
|
|
|
+| `threading.Lock` | 互斥访问 | `tracking_targets`, `state`, `stats`, `frame` |
|
|
|
+| `threading.Event` | 暂停/恢复同步 | `_paused_event` — 校准时暂停检测 |
|
|
|
+| `queue.Queue` | 线程间通信 | `_ptz_queue` (检测→PTZ 命令) |
|
|
|
+
|
|
|
+### 8.2 暂停/恢复协议
|
|
|
+
|
|
|
+校准期间需要暂停检测线程,避免校准移动球机时检测线程也发 PTZ 命令造成争抢:
|
|
|
+
|
|
|
+```
|
|
|
+pause_detection() → _paused = True, _paused_event.clear()
|
|
|
+ → 检测线程: _paused_event.wait() 阻塞
|
|
|
+ → PTZ 线程: 检查 _paused 后跳过处理
|
|
|
+
|
|
|
+resume_detection() → _paused = False, _paused_event.set()
|
|
|
+ → 检测线程: 恢复运行
|
|
|
+ → PTZ 线程: 恢复处理命令
|
|
|
+```
|
|
|
+
|
|
|
+### 8.3 坐标映射体系
|
|
|
+
|
|
|
+```
|
|
|
+全景画面坐标 (x_ratio, y_ratio) 球机 PTZ 角度 (pan, tilt, zoom)
|
|
|
+ │ ▲
|
|
|
+ │ │
|
|
|
+ ▼ │
|
|
|
+┌──────────────────────┐ ┌────────────────────┐
|
|
|
+│ 标定阶段: │ │ 运行时: │
|
|
|
+│ - 运动检测 │────>│ - 查找表查询 │
|
|
|
+│ - 特征匹配 │ │ - 双线性插值 │
|
|
|
+│ - 加权融合 │ │ - tilt 线性重映射 │
|
|
|
+│ → 校准查找表 │ │ - pan 边缘曲线补偿 │
|
|
|
+└──────────────────────┘ └────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+**PTZ 坐标计算(`PTZ_CONFIG` 中的关键参数):**
|
|
|
+
|
|
|
+| 参数 | 默认值 | 作用 |
|
|
|
+|------|--------|------|
|
|
|
+| `tilt_linear_enabled` | `True` | 使用线性 tilt 映射替代查找表(查找表 tilt 不稳定) |
|
|
|
+| `tilt_y0 / tilt_y1` | `15 / 55` | y_ratio=0 和 y_ratio=1 对应的 tilt 角度 |
|
|
|
+| `tilt_curve_power` | `0.8` | tilt 曲线指数,控制中间区域 tilt 变化率 |
|
|
|
+| `pan_flip` | `False` | 球机与全景朝向相反时翻转 pan 方向 |
|
|
|
+| `pan_edge_offset` | `25` | 画面边缘处 pan 额外补偿度数 |
|
|
|
+| `pan_curve_power` | `2.0` | pan 边缘曲线指数,>1 时边缘补偿更大 |
|
|
|
+
|
|
|
+### 8.4 图像清晰度评估
|
|
|
+
|
|
|
+PTZ 到位后获取球机帧时,使用**拉普拉斯算子方差**评估清晰度:
|
|
|
+
|
|
|
+```python
|
|
|
+gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
|
|
+laplacian_var = cv2.Laplacian(gray, cv2.CV_64F).var()
|
|
|
+# min_clarity=200, 高于此值认为清晰
|
|
|
+```
|
|
|
+
|
|
|
+获取策略:最多尝试 8 次(间隔 0.2s),返回清晰度最高的帧。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. 配置体系
|
|
|
+
|
|
|
+### 9.1 配置层级
|
|
|
+
|
|
|
+```mermaid
|
|
|
+graph TB
|
|
|
+ Default["config/*.py<br/>默认配置"] -->|被覆盖| CLI["命令行参数<br/>--panorama-ip ..."]
|
|
|
+ CLI -->|构建| ConfigDict["运行期配置字典"]
|
|
|
+ ConfigDict -->|读取| Modules["各个模块"]
|
|
|
+
|
|
|
+ subgraph "配置模块"
|
|
|
+ camera["camera.py<br/>摄像头 + SDK + 日志"]
|
|
|
+ detection["detection.py<br/>YOLO + 安全检测参数"]
|
|
|
+ ptz["ptz.py<br/>PTZ 控制 + 自动变焦"]
|
|
|
+ coordinator["coordinator.py<br/>联动 + 校准"]
|
|
|
+ event["event.py<br/>事件推送"]
|
|
|
+ llm["llm.py<br/>大模型"]
|
|
|
+ system["system.py<br/>系统开关 + 工作模式"]
|
|
|
+ oss["oss.py<br/>OSS 上传"]
|
|
|
+ device["device.py<br/>第三方平台 + 设备"]
|
|
|
+ end
|
|
|
+
|
|
|
+ Modules --> camera
|
|
|
+ Modules --> detection
|
|
|
+ Modules --> ptz
|
|
|
+ Modules --> coordinator
|
|
|
+ Modules --> event
|
|
|
+ Modules --> llm
|
|
|
+ Modules --> system
|
|
|
+ Modules --> oss
|
|
|
+ Modules --> device
|
|
|
+```
|
|
|
+
|
|
|
+### 9.2 功能开关矩阵 (`config/system.py`)
|
|
|
+
|
|
|
+| 开关 | 安全模式 | 说明 |
|
|
|
+|------|----------|------|
|
|
|
+| `enable_panorama_camera` | ✓ | 全景摄像头启用 |
|
|
|
+| `enable_ptz_camera` | ✓ (可选) | 球机 PTZ 启用 |
|
|
|
+| `enable_detection` | ✓ | 人体/安全检测 |
|
|
|
+| `enable_safety_detection` | ✓ | 安全帽/反光衣检测 |
|
|
|
+| `enable_calibration` | ✗ | 全景-球机校准 |
|
|
|
+| `enable_ptz_tracking` | ✓ (可选) | PTZ 联动跟踪 |
|
|
|
+| `enable_llm` | ✓ | 大模型安全判断 |
|
|
|
+| `enable_event_push` | ✓ | 事件推送 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. 扩展设计
|
|
|
+
|
|
|
+### 10.1 多组摄像头扩展
|
|
|
+
|
|
|
+通过 `CameraGroup` 和 `MultiGroupSystem` 支持 N 组全景+球机并行运行:
|
|
|
+
|
|
|
+```python
|
|
|
+# config/camera.py 中配置多组
|
|
|
+CAMERA_GROUPS = [
|
|
|
+ {
|
|
|
+ 'group_id': 'group_1',
|
|
|
+ 'enabled': True,
|
|
|
+ 'panorama': { ... },
|
|
|
+ 'ptz': { ... },
|
|
|
+ 'calibration_file': '/home/admin/dsh/calibration_group1.json',
|
|
|
+ 'paired_image_dir': '/home/admin/dsh/paired_images_group1',
|
|
|
+ },
|
|
|
+ # 可继续添加 group_2, group_3, ...
|
|
|
+]
|
|
|
+```
|
|
|
+
|
|
|
+### 10.2 扩展新联动控制器
|
|
|
+
|
|
|
+继承 `Coordinator` 基类,重写 `_coordinator_worker()` 和 `start()/stop()`:
|
|
|
+
|
|
|
+```python
|
|
|
+class CustomCoordinator(Coordinator):
|
|
|
+ def _coordinator_worker(self):
|
|
|
+ # 自定义联动逻辑
|
|
|
+ pass
|
|
|
+```
|
|
|
+
|
|
|
+### 10.3 扩展新安全检测策略
|
|
|
+
|
|
|
+`safety_strategy` 支持 `rule`/`llm`/`hybrid` 三种,可扩展:
|
|
|
+
|
|
|
+```python
|
|
|
+# config/system.py
|
|
|
+'safety_strategy': 'hybrid' # 可扩展为 'custom'
|
|
|
+```
|
|
|
+
|
|
|
+### 10.4 模型推理后端扩展
|
|
|
+
|
|
|
+`model_type` 支持 `auto`/`yolo`/`rknn`/`onnx`,可添加新类型:
|
|
|
+
|
|
|
+```python
|
|
|
+# DETECTION_CONFIG.model_type
|
|
|
+'auto': # 自动检测(.pt→yolo, .rknn→rknn, .onnx→onnxruntime)
|
|
|
+'yolo': # Ultralytics YOLO
|
|
|
+'rknn': # RK3588 NPU 推理
|
|
|
+'onnx': # ONNX Runtime
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 附录
|
|
|
+
|
|
|
+### A. 项目文件清单
|
|
|
+
|
|
|
+| 文件 | 行数 | 职责 |
|
|
|
+|------|------|------|
|
|
|
+| `safety_main.py` | 822 | 安全模式主程序入口 |
|
|
|
+| `coordinator.py` | 2177 | 联动控制器(三种策略) |
|
|
|
+| `dahua_sdk.py` | 527 | 大华 SDK ctypes 封装 |
|
|
|
+| `panorama_camera.py` | 909 | 全景摄像头 + YOLO 检测 |
|
|
|
+| `ptz_camera.py` | ~600 | 球机 PTZ 控制 |
|
|
|
+| `calibration.py` | 1668 | 全景-球机坐标校准 |
|
|
|
+| `safety_detector.py` | ~500 | 安全检测 + LLM 混合 + RKNN推理 |
|
|
|
+| `safety_coordinator.py` | ~400 | 安全联动控制器 |
|
|
|
+| `event_pusher.py` | 460 | 事件推送 + OSS 上传 |
|
|
|
+| `llm_service.py` | ~300 | 大模型服务封装 |
|
|
|
+| `camera_group.py` | 419 | 摄像头组封装 |
|
|
|
+| `multi_group_system.py` | 308 | 多组并行管理 |
|
|
|
+| `calibration.py` | 1668 | 校准器 + 视野发现 |
|
|
|
+| `paired_image_saver.py` | ~200 | 配对图片保存 |
|
|
|
+| `third_party_pusher.py` | ~200 | 第三方平台推送 |
|
|
|
+| `ptz_person_tracker.py` | ~300 | 球机端人体检测 + 自动变焦 |
|
|
|
+| `config/__init__.py` | 52 | 配置汇总导出 |
|
|
|
+| `config/camera.py` | 113 | 摄像头 + SDK + 日志 |
|
|
|
+| `config/detection.py` | 69 | 检测参数 |
|
|
|
+| `config/ptz.py` | 58 | PTZ 控制参数 |
|
|
|
+| `config/coordinator.py` | 59 | 联动 + 校准配置 |
|
|
|
+| `config/event.py` | 36 | 事件推送配置 |
|
|
|
+| `config/llm.py` | ~40 | 大模型配置 |
|
|
|
+| `config/system.py` | 39 | 系统开关 + 工作模式 |
|
|
|
+| `config/oss.py` | ~20 | OSS 上传配置 |
|
|
|
+| `config/device.py` | ~30 | 第三方平台配置 |
|
|
|
+
|
|
|
+### B. 外部依赖清单
|
|
|
+
|
|
|
+| 依赖 | 用途 | 安装方式 |
|
|
|
+|------|------|----------|
|
|
|
+| `ultralytics` | YOLO11 检测推理 | `pip install ultralytics` |
|
|
|
+| `opencv-python` | 图像处理、RTSP、显示 | `pip install opencv-python` |
|
|
|
+| `opencv-contrib-python` | SIFT 特征匹配 | `pip install opencv-contrib-python` |
|
|
|
+| `numpy` | 数值计算 | `pip install numpy` |
|
|
|
+| `requests` / `httpx` | HTTP API 调用 | `pip install requests httpx` |
|
|
|
+| `llama-server` | 视觉语言模型推理(安全分析) | 单独部署(GGUF 模型) |
|
|
|
+| 大华 NetSDK | 摄像头 SDK | 厂商提供 `.so` 文件 |
|
|
|
+| `rknnlite2` / `rknn-toolkit2` | RK3588 NPU 推理 / 模型量化 | 板载:`pip install rknnlite2` |
|
|
|
+| `onnxruntime` | ONNX 推理(备选) | `pip install onnxruntime` |
|