本系统实现多组全景摄像头和可变焦球机的联动抓拍功能:
注意:本版本已移除 OCR 编号识别、LLM 判断、安全帽/反光衣检测,仅保留人体检测与联动抓拍。
多组摄像头配置 (config/camera.py)
│
▼
app.py / create_app()
│
▼
初始化共享 SDK、检测器、视频流管理器
│
▼
为每组创建:
├── StreamManager:枪机/球机 RTSP 流
├── SpatialScanner:360° 空间扫描建模(可选)
├── PollingScheduler:扫描点位轮询
└── CaptureUploader:抓拍 + 上传
│
▼
枪机实时检测 + 球机轮询检测 ──> 抓拍 ──> 上传/事件推送
dual_camera_system/
├── config/ # 模块化配置
│ ├── __init__.py # 配置导出
│ ├── camera.py # 摄像头 + 日志配置
│ ├── detection.py # 人体检测配置
│ ├── ptz.py # PTZ 控制参数
│ ├── coordinator.py # 扫描轮询参数
│ ├── tracking.py # 跟踪 + 轮询抓拍配置(库代码)
│ ├── event.py # 事件推送配置
│ ├── system.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 # 视频流管理
├── 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 Python封装
├── panorama_camera.py # 全景摄像头模块(视频流、人体检测)
├── ptz_camera.py # 球机控制模块(PTZ控制、精确定位)
├── inference_backend.py # RKNN/ONNX 通用推理后端
├── scripts/ # 脚本工具
│ ├── local_test.py # 本地 RTSP/检测/PTZ 角度测试
│ └── manual_ptz_test.py # 手动 PTZ 控制测试脚本
├── pytest.ini # pytest 仅收集 tests/ 目录
└── README.md # 说明文档
# OpenCV
pip install opencv-python opencv-contrib-python
# YOLO11 (用于人体检测) - Ultralytics最新版本
pip install ultralytics
注意: YOLO11是Ultralytics的最新模型,首次运行时会自动下载预训练权重(yolo11n.pt等)。
编辑 config/camera.py 配置摄像头组。系统默认使用示例环境:
192.168.8.2,RTSP-only(不经过 Dahua SDK 登录)球机:Dahua 192.168.8.5,竖装且设备端已做倒影,代码层按 wall 处理,pan 不翻转
CAMERA_GROUPS = [
{
'group_id': 'group_1',
'name': '主入口',
'enabled': True,
'panorama': {
'ip': '192.168.8.2',
'port': 37777, # Hikvision 不使用 SDK 登录,此字段可忽略
'username': 'admin',
'password': 'QAZwsx12',
'channel': 1,
'brand': 'hikvision', # 或 use_sdk: False
# 全景分辨率,支持 (width, height) 或 "3840x1080" / "2560*1440" / "1920x1080"
'resolution': (2560, 1440),
'rtsp_url': 'rtsp://admin:QAZwsx12@192.168.8.2:554/Streaming/Channels/101',
},
'ptz': {
'ip': '192.168.8.5',
'port': 37777,
'username': 'admin',
'password': 'Aa1234567',
'channel': 0,
# 竖装+设备端倒影后,代码层按 wall 处理;若球机与枪机朝向相反则 pan_flip=True
'mount_type': 'wall',
'pan_flip': False,
'tilt_flip': False,
'rtsp_url': 'rtsp://admin:Aa1234567@192.168.8.5:554/cam/realmonitor?channel=1&subtype=1',
},
}
]
编辑 config/detection.py 调整人体检测模型与阈值。
# 启动扫描轮询模式
python main.py
# 演示模式 (不连接实际摄像头)
python main.py --demo
# 指定模型
python main.py --model /home/wen/dsh/yolo/yolo11n.pt --model-size n
# 禁用 GPU
python main.py --no-gpu
# 指定监听地址和端口
python main.py --host 0.0.0.0 --port 8080
在 macOS 等无法加载 libdhnetsdk.so 的环境,或只想快速验证枪机 RTSP / 检测 / PTZ 角度计算时:
cd dual_camera_system
python scripts/local_test.py --frames 10
# 显示检测窗口(按 q 退出)
python scripts/local_test.py --frames 10 --show
该脚本会:
mount_type / pan_flip 等配置计算应转动的 PTZ 角度(不实际转动)使用 YOLO11 模型检测画面中的人体,支持 GPU 加速。
模型尺寸选项:
n (nano) - 最快,精度较低s (small) - 平衡速度和精度m (medium) - 中等l (large) - 高精度x (extra-large) - 最高精度,速度最慢当前系统通过 app.py 的 create_app() 启动多组摄像头扫描轮询模式:
DetectorService)和一个视频流管理器(StreamManager)SpatialScanner 可选执行 360° 空间扫描建模PollingScheduler 按扫描点位轮询球机 PTZ,到位后由枪机/球机检测线程触发抓拍CaptureUploader 负责本地存储与可选 OSS/第三方平台上传web/routes.py 暴露状态查看、扫描控制等 HTTP 接口支持大华球机的 PTZ 控制:
系统使用基于标定文件的坐标映射:
{
"pan_lookup": [[0.15, 252.0], [0.55, 288.0], [0.80, 305.0]],
"tilt_lookup": [[0.45, -5.0], [0.50, -5.0], [0.65, -25.0]],
"mount_type": "wall",
"pan_flip": false,
"tilt_flip": false
}
pan_lookup 按 [[x_ratio, pan_angle], ...] 分段线性插值;tilt_lookup 同理。运行时 tilt_linear_enabled=True 会优先使用 config/ptz.py 中的 tilt_y0/tilt_y1 线性映射。校准文件路径在 config/camera.py 的 calibration_file 中配置。
当自动特征匹配不可靠时,可使用独立扫描脚本生成可人工复核的图片集,再基于确认的关键点生成校准文件。
# 1. 球机水平 360°、步长 20°,每个水平位置由下朝上扫描 tilt
# 每个位置保存球机图(文件名带 pan/tilt)和全景图
python scripts/calibration_scanner.py
# 2. 用 ORB 重新匹配已扫描图片,生成 lookup_table_orb.json 与复核 CSV
python scripts/re_match_orb.py
扫描结果保存在 calibration_scan/(可在脚本中修改路径)。人工确认图片后,编辑生成的 JSON 或手动编写 calibration_group1.json。
config/device.py每组全景摄像头可独立配置期望分辨率:
'panorama': {
...
'resolution': (3840, 1080), # 或 "3840x1080" / "3840*1080"
}
支持格式:
(3840, 1080)、[2560, 1440]"3840x1080"、"2560*1440"、"1920x1080"系统不会拉伸 RTSP 流帧;模型推理时通过 letterbox(灰度填充)将画面按比例缩放并补到模型输入尺寸,避免丢精度。配置的分辨率用于生成模拟帧与分辨率校验。
config/camera.py 中配置,main.py 仅作为 uvicorn 服务入口