README.md 9.0 KB

双摄像头联动抓拍系统

系统简介

本系统实现多组全景摄像头和可变焦球机的联动抓拍功能:

  • 多组全景摄像头实时监控,检测画面中的人体
  • 对应球机按扫描点位轮询定位并抓拍
  • 保存全景+球机配对图片,支持上传至业务平台

注意:本版本已移除 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等)。

使用方法

1. 修改配置

编辑 config/camera.py 配置摄像头组。系统默认使用示例环境:

  • 枪机:Hikvision 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 调整人体检测模型与阈值。

2. 运行系统

# 启动扫描轮询模式
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

本地冒烟测试(无需 Dahua SDK)

在 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

该脚本会:

  1. 打开 Hikvision 枪机 RTSP 流
  2. 加载 YOLO 人体检测模型
  3. 对若干帧进行检测,并打印每个人的坐标
  4. 根据球机 mount_type / pan_flip 等配置计算应转动的 PTZ 角度(不实际转动)

关键功能说明

人体检测

使用 YOLO11 模型检测画面中的人体,支持 GPU 加速。

模型尺寸选项:

  • n (nano) - 最快,精度较低
  • s (small) - 平衡速度和精度
  • m (medium) - 中等
  • l (large) - 高精度
  • x (extra-large) - 最高精度,速度最慢

扫描轮询模式

当前系统通过 app.pycreate_app() 启动多组摄像头扫描轮询模式

  • 共享一次大华 SDK 初始化、一个检测器服务(DetectorService)和一个视频流管理器(StreamManager
  • 每组摄像头独立注册枪机/球机 RTSP 流
  • SpatialScanner 可选执行 360° 空间扫描建模
  • PollingScheduler 按扫描点位轮询球机 PTZ,到位后由枪机/球机检测线程触发抓拍
  • CaptureUploader 负责本地存储与可选 OSS/第三方平台上传
  • Web 服务通过 web/routes.py 暴露状态查看、扫描控制等 HTTP 接口

PTZ控制

支持大华球机的 PTZ 控制:

  • 三维精确定位 (DH_EXTPTZ_EXACTGOTO)
  • 预置点设置/调用
  • 平滑移动跟踪

坐标映射与校准

系统使用基于标定文件的坐标映射:

{
  "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.pycalibration_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

配对图片保存

  • 全景图与球机抓拍图按时间窗口归入同一目录
  • 支持 OSS 上传与第三方平台推送
  • 配置位于 config/device.py

全景分辨率配置

每组全景摄像头可独立配置期望分辨率:

'panorama': {
    ...
    'resolution': (3840, 1080),  # 或 "3840x1080" / "3840*1080"
}

支持格式:

  • 元组/列表:(3840, 1080)[2560, 1440]
  • 字符串:"3840x1080""2560*1440""1920x1080"

系统不会拉伸 RTSP 流帧;模型推理时通过 letterbox(灰度填充)将画面按比例缩放并补到模型输入尺寸,避免丢精度。配置的分辨率用于生成模拟帧与分辨率校验。

注意事项

  1. 确保大华 SDK 库文件路径正确
  2. 球机需要支持 PTZ 控制功能
  3. 坐标映射需要根据实际场景校准
  4. 所有摄像头组在 config/camera.py 中配置,main.py 仅作为 uvicorn 服务入口