本文档为 AI 助手提供项目上下文,便于后续交互时快速理解项目结构和技术细节。
施工现场安全行为智能识别系统 v2.0.0 - 基于 Python 的双摄像头联动系统。
核心功能:
注:OCR 编号识别、LLM 判断、安全帽/反光衣检测已在本版本中移除。
dual_camera_system/
├── config/ # 模块化配置(已重构)
│ ├── __init__.py # 配置汇总导出
│ ├── camera.py # 摄像头 + 日志配置
│ ├── coordinator.py # 扫描轮询参数
│ ├── detection.py # 人体检测配置
│ ├── device.py # 设备元数据配置
│ ├── event.py # 事件推送配置
│ ├── oss.py # OSS 上传配置
│ ├── ptz.py # PTZ 控制参数
│ ├── system.py # 系统功能开关
│ └── tracking.py # 跟踪 + 轮询抓拍配置(库代码)
├── core/ # 新架构核心模块
│ ├── capture_uploader.py # 抓拍与上传核心逻辑
│ ├── coord_utils.py # 坐标/角度换算工具
│ ├── detector_service.py # 检测器服务封装
│ ├── group_state.py # 摄像头组状态管理
│ ├── polling_scheduler.py # 轮询调度器
│ ├── scan_point_store.py # 扫描点位存储
│ ├── spatial_scanner.py # 空间扫描建模
│ └── stream_manager.py # 视频流管理
├── scripts/ # 脚本工具
│ ├── local_test.py # 本地 RTSP/检测/PTZ 角度测试
│ └── manual_ptz_test.py # 手动 PTZ 控制测试脚本(原 test_ptz.py)
├── pytest.ini # pytest 仅收集 tests/ 目录
├── web/ # Web API 服务
│ ├── routes.py # HTTP 路由
│ └── state.py # Web 应用状态
├── web_static/ # 前端静态页面
│ ├── app.js # 前端交互脚本
│ ├── index.html # 前端入口页面
│ └── style.css # 前端样式
├── app.py # FastAPI 应用工厂与全局服务初始化
├── main.py # 服务入口(启动 uvicorn)
├── dahua_sdk.py # 大华 SDK ctypes 封装
├── panorama_camera.py # 全景摄像头 + 人体检测
├── ptz_camera.py # 球机 PTZ 控制
├── inference_backend.py # RKNN/ONNX 通用推理后端
└── README.md # 项目说明
dh/ # 大华 SDK(仅参考)
├── Bin/ # Linux .so 库(macOS 不可用)
├── Demo/ # C++ Qt 示例
└── Include/Common/ # SDK 头文件
cd dual_camera_system
python main.py
python main.py --demo
--host HOST # 服务监听地址(默认 0.0.0.0,也可通过 HOST 环境变量设置)
--port PORT # 服务监听端口(默认 8000,也可通过 PORT 环境变量设置)
--model-size {n,s,m,l,x} # YOLO11 模型尺寸
--no-gpu # 禁用 GPU
--model /path/to/model.pt # 显式指定检测模型
| 组件 | 技术 |
|---|---|
| 人体检测 | YOLO11 (ultralytics) |
| 摄像头 SDK | 大华 NetSDK (ctypes) |
| 图像处理 | OpenCV |
| PTZ 控制 | DH_EXTPTZ_EXACTGOTO |
| 事件推送 | HTTP API → jtjai.device.wenhq.top:8583 |
| Web 服务 | FastAPI + uvicorn |
enable_panorama_camera: 启用全景摄像头;为 False 时不注册枪机 RTSP 流enable_ptz_camera: 启用 PTZ 球机;为 False 时不连接球机、不注册球机流、不创建扫描器/调度器enable_detection: 启用人体检测;为 False 时不启动检测线程enable_event_push: 启用事件推送;为 False 时不启动第三方推送器app.py 在启动时会读取这些开关并跳过对应服务。
device_id: 设备编号project_id: 项目编号api_key: Web 控制接口 API Key;留空时不鉴权(向后兼容本地开发),配置后需在请求头中携带 X-API-Key受保护的写端点:/api/scan/*、/api/poll/*、/api/points/* 的 POST/DELETE。
读端点:/api/status、/api/live/*、/api/panorama/*、/api/scan/*/progress、/api/points/* 保持公开。
鉴权实现位于 web/auth.py。
PANORAMA_CAMERA: 全景摄像头 IP/端口/凭证/分辨率/品牌
brand: 摄像头品牌,'dahua' 使用 SDK 登录,'hikvision' 仅使用 RTSP 取流use_sdk: False 时跳过 SDK 登录,直接 RTSP 取流resolution: 期望分辨率,支持 (width, height) 或字符串 "3840x1080"、"2560*1440"、"1920x1080"PTZ_CAMERA: 球机 IP/端口/凭证CAMERA_GROUPS: 多组摄像头配置,每组 panorama 可独立配置 resolution/brandSDK_PATH: /home/wen/dsh/dh/Bin(Linux 路径)DETECTION_CONFIG: 人体检测(目标类别、置信度、检测间隔、模型路径)EVENT_PUSHER_CONFIG: 推送到 jtjai.device.wenhq.top:8583/api/resource/oss/upload - 图片上传/api/system/event - 事件创建TRACKING_CONFIG.model_path: 默认跟踪模型路径,按平台自动选择
/home/admin/dsh/yolo/yolo11.rknn(RK3588)/home/wen/dsh/yolo/yolo11n.pt/Users/wenhongquan/Desktop/阿里云同步/项目/dnn/sb/model/yolo11n.ptTRACKING_CONFIG.model_type: 'auto' | 'yolo' | 'rknn' | 'onnx'TRACKING_CONFIG.tracker_type: 'bytetrack' | 'botsort'TRACKING_CONFIG.max_tracking_targets: 最大同时跟踪目标数TRACKING_CONFIG.tracking_timeout: 目标丢失后保留 ID 的超时时间ptz_stabilize_time、ptz_command_cooldown、capture_dir、enable_uploadptz_stabilize_time: PTZ 到位后稳定等待时间(秒)ptz_command_cooldown: PTZ 命令最小间隔(秒)ssh admin@192.168.20.84conda activate rknn/home/admin/dsh/dual_camera_system/home/admin/dsh/dh/Binaarch64 → /home/admin/dsh/dh/arm/Bin(Orange Pi 测试设备)x86_64 → /home/wen/dsh/dh/Bin(x86 Linux 服务器)../dh/Bin(开发环境参考)CLIENT_SetVideoProcCallBack 等函数,dahua_sdk.py 已做可选绑定处理,缺失函数运行时降级而非崩溃DWORD=unsigned int(4B), LONG=int(4B), LLONG=long(8B),ctypes 绑定必须严格匹配,否则结构体对齐错误导致登录失败app.py 的生命周期中先初始化检测器服务,再初始化大华 SDK。大华 SDK 的 CLIENT_Init 会修改进程内存映射,如果先于 PyTorch 加载会导致 segfaultconfig/detection.py 中配置,默认 /home/wen/dsh/yolo/yolo11n.pt;macOS 本地测试建议将 config/tracking.py 中模型路径指向可用 .pt 文件app.py 的 create_app() 启动 多组摄像头扫描轮询模式,所有摄像头组在 config/camera.py 的 CAMERA_GROUPS 中配置,main.py 仅作为 uvicorn 服务入口port=37777, rtsp_port=554config/camera.py 中配置 resolution,支持 3840x1080、2560*1440、1920x1080 等;系统仅在 RTSP 不可用时按配置分辨率生成模拟帧,实际流帧不再拉伸缩放;模型推理时通过 letterbox(灰度填充)保持宽高比,避免丢精度brand='hikvision' 或 use_sdk=False),球机仍使用 Dahua SDK 控制 PTZpython scripts/local_test.py 验证 RTSP、检测与 PTZ 角度计算app.py 会检查 ptz.connect() 返回值;连接失败时记录错误,跳过该组的球机流/扫描器/调度器,并在 group_state 中设置 ptz_connected: false,枪机流与检测线程仍尽可能保留core/detector_service.py 使用 threading.Lock() 保护 detect(),避免多摄像头检测线程并发推理导致崩溃核心组件:
app.py:create_app() 负责全局服务初始化与 FastAPI 生命周期管理core/stream_manager.py:统一管理枪机/球机 RTSP 视频流core/spatial_scanner.py:执行 360° 空间扫描建模(可选)core/polling_scheduler.py:按扫描点位轮询控制球机 PTZcore/capture_uploader.py:抓拍保存与可选上传web/routes.py:暴露状态查看、扫描控制等 HTTP 接口工作流程:
config/camera.py 中 CAMERA_GROUPS
│
▼
create_app() / app.py
│
▼
初始化共享 SDK、检测器、视频流管理器
│
▼
为每组创建:
├── StreamManager:枪机/球机 RTSP 流
├── SpatialScanner:360° 空间扫描建模(可选)
├── PollingScheduler:扫描点位轮询
└── CaptureUploader:抓拍 + 上传
│
▼
枪机实时检测 + 球机轮询检测 ──> 抓拍 ──> 上传/事件推送
关键行为:
app.py 初始化一次大华 SDK、一个检测器服务(DetectorService)和一个视频流管理器(StreamManager)CAMERA_GROUPS 中每个启用的组注册枪机/球机 RTSP 流PollingScheduler 按扫描点位轮询球机 PTZ,到位后由枪机/球机检测线程抓拍CaptureUploader 负责本地存储与可选 OSS/第三方平台上传web/routes.py 暴露状态/控制接口头文件:dh/Include/Common/dhnetsdk.h
关键接口:
CLIENT_Init / CLIENT_CleanupCLIENT_LoginEx2 / CLIENT_LogoutCLIENT_RealPlayExCLIENT_DHPTZControlEx (DH_EXTPTZ_EXACTGOTO)