YOLO 人员距离速度检测
基于 YOLO 人员检测 + ByteTrack 跟踪 + 摄像机地面标定,实现稳定的人员距离、速度、靠近/远离摄像头方向判断。适用于固定摄像头的厂区监控场景。
支持两种使用方式:
- 命令行:
main.py本地 OpenCV 窗口实时预览 - Web 界面:标定 + 浏览器实时监控(MJPEG 流 + 人员列表)
功能
- 人员检测:YOLOv8 检测
person类别 - 多目标跟踪:ByteTrack 为每个人分配稳定 ID
- 地面定位:检测框底部中心点作为脚点,Homography 映射到地面坐标
- 距离计算:人员到摄像头地面投影点 O 的地面距离(米)
- 速度计算:滑动窗口内距离变化率,卡尔曼滤波平滑
- 方向判断:距离持续减少 → 靠近摄像头;持续增加 → 远离摄像头
- RTSP 优化:TCP 传输、小缓冲、读帧失败自动重连
- 画面标注:OpenCV 英文叠加(低延迟,无 PIL 整帧转换)
系统架构
摄像头 (RTSP) / 本地视频
│
▼
视频解码 (VideoSource,可选自动重连)
│
▼
YOLO 人员检测 + ByteTrack 跟踪
│
▼
脚点计算 (bbox 底部中心)
│
▼
Homography 透视变换
│
├──────────────┐
▼ ▼
距离 D=√(X²+Y²) 距离变化率 → 速度
│ │
└──────┬───────┘
▼
靠近 / 远离判断
│
├─────────────┬──────────────┐
▼ ▼ ▼
OpenCV 画面标注 JSON 事件 Web MJPEG 流
(main.py) (output/) (/monitor)
距离定义
距离不是「人体框越大越近」,而是:
摄像头 📷
│
▼
O 摄像头地面投影点 (0, 0)
│
│ D 米
│
● 👤 人员脚点 P(X, Y)
D = √(X² + Y²)
即:摄像头正下方地面投影点 → 人员脚点 的地面直线距离。
环境要求
- Python 3.10+
- Windows / Linux
- 可选:NVIDIA GPU + CUDA(显著加速 YOLO 推理)
安装
cd yolo判断距离速度
pip install -r requirements.txt
首次运行会自动下载 YOLOv8 模型权重(默认 yolov8n.pt)。
依赖概览:
| 包 | 用途 |
|---|---|
| ultralytics | YOLOv8 检测与 ByteTrack |
| opencv-python | 视频读写、画面标注 |
| filterpy | 卡尔曼滤波 |
| fastapi / uvicorn | Web 标定与实时监控 |
| pyyaml | 配置文件 |
快速开始
1. 配置视频源
编辑 config/config.yaml:
camera:
rtsp_url: "rtsp://admin:密码@192.168.1.64:554/Streaming/Channels/101"
# 本地视频优先于 RTSP(非空时使用 video_file)
video_file: ""
rtsp_transport: tcp # RTSP 建议 tcp,更稳定
video_file非空时优先使用本地文件,便于离线调试。
2. 摄像机标定(必做)
标定建立「像素坐标 → 地面坐标」映射,是距离计算的基础。O 点为坐标原点 (0, 0),通常在画面外,无需在画面上点击。
方式一:Web 标定(推荐)
python web/server.py
浏览器打开 http://127.0.0.1:8080
- 点击「从视频源抓拍」或「上传图片」加载画面
- 在地面用卷尺从 O(摄像头正下方地面点)量出距离
- 在画面上点击该可见地面位置,输入卷尺实测距离(如 5m / 10m / 15m / 20m)
- 可选填写横向偏移(左负右正,提高透视精度)
- 至少 4 个点后点击「保存标定」
自定义端口:
python web/server.py --host 0.0.0.0 --port 8080
方式二:OpenCV 窗口标定
python calibrate.py
# 或指定配置 / 视频源
python calibrate.py --config config/config.yaml --source test.mp4
标定步骤:
- 在地面用卷尺从 O 量距离,在画面上点击该位置并输入实测距离
- 建议沿主视野方向标 5m / 10m / 15m / 20m,并在同一距离加左右横向点
- 至少 4 个点后按
s保存
操作键:
| 键 | 功能 |
|---|---|
| 左键 | 添加标定点(终端输入距离) |
s | 保存标定(至少 4 点) |
r | 重置 |
q | 退出 |
标定结果:
config/homography_matrix.npy— 单应性矩阵config/homography_matrix.json— 标定点元数据
无摄像头时生成示例标定:
python generate_sample_calibration.py
3. 运行检测
方式 A:命令行(OpenCV 窗口)
python main.py
# 或指定配置
python main.py --config config/config.yaml
按 q 退出。可选保存视频与 JSON 事件(见配置 output.*)。
方式 B:Web 实时监控
python web/server.py
打开 http://127.0.0.1:8080/monitor
- 确认已完成标定
- 点击「开始检测」
- 左侧为 MJPEG 实时画面,右侧为当前检测到的人员列表(距离 / 速度 / 方向)
Web 服务同时提供标定页(/)与监控页(/monitor),共用 config/config.yaml 中的视频源与标定文件。
画面标注说明
视频叠加文字使用 OpenCV putText(英文),避免 PIL 整帧转换带来的延迟。
叠加示例:
#12
Dist 7.40m
Speed 1.32m/s (4.8km/h)
Approaching
框与文字颜色:
| 颜色 | 含义 |
|---|---|
| 红色 | 靠近摄像头(Approaching) |
| 绿色 | 远离摄像头(Retreating) |
| 灰色 | 静止(Stationary) |
| 黄色 | 方向未确认(Unknown) |
| 青色圆点 | 脚点位置 |
| 橙色十字 | 摄像头地面投影点 O(若在画面内) |
配置说明
主配置文件:config/config.yaml
camera — 视频源
| 参数 | 说明 | 默认 |
|---|---|---|
rtsp_url | RTSP 地址 | — |
video_file | 本地视频路径(非空时优先) | "" |
width / height / fps | 参考分辨率与帧率 | 1920×1080 @ 25 |
rtsp_transport | RTSP 传输协议 | tcp |
max_read_fails | 连续读帧失败多少次后重连 | 5 |
reconnect_delay | 重连等待秒数 | 2 |
detection — YOLO 检测
| 参数 | 说明 | 默认 |
|---|---|---|
model | 模型权重 | yolov8n.pt |
confidence | 检测置信度阈值 | 0.5 |
classes | 检测类别 ID 列表 | [0](person) |
imgsz | 推理输入尺寸,越小越快 | 640 |
skip_frames | 每推理 1 帧额外跳过的读帧数;1 表示隔帧检测 | 0 |
tracking — ByteTrack
| 参数 | 说明 | 默认 |
|---|---|---|
tracker | 跟踪器配置 | bytetrack.yaml |
persist | 跨帧保持跟踪 ID | true |
calibration — 标定
| 参数 | 说明 | 默认 |
|---|---|---|
homography_file | 标定矩阵路径 | config/homography_matrix.npy |
motion — 运动分析
| 参数 | 说明 | 默认 |
|---|---|---|
speed_window_seconds | 速度滑动窗口(秒) | 1.0 |
distance_threshold | 静止阈值(米),|ΔD| 小于此值视为静止 | 0.3 |
direction_confirm_frames | 方向变更需连续满足的帧数 | 5 |
kalman_process_noise | 卡尔曼过程噪声 | 0.1 |
kalman_measurement_noise | 卡尔曼观测噪声 | 1.0 |
output — 命令行输出(main.py)
| 参数 | 说明 | 默认 |
|---|---|---|
show_window | 是否显示 OpenCV 窗口 | true |
save_video | 是否保存标注视频 | false |
video_output | 视频输出路径 | output/result.mp4 |
json_output | JSON 事件输出路径 | output/events.json |
输出示例
JSON 事件(Web /api/detect/status 与 main.py 均使用同一结构):
{
"person_id": 12,
"ground_x": 6.2,
"ground_y": 8.5,
"distance": 10.52,
"speed": 1.32,
"speed_kmh": 4.75,
"direction": "approaching",
"timestamp": "2026-08-31 10:30:21"
}
方向字段 direction:
| 值 | 含义 |
|---|---|
approaching | 靠近摄像头(距离持续减少) |
retreating | 远离摄像头(距离持续增加) |
stationary | 静止(距离变化 < 阈值) |
unknown | 尚未确认 |
性能调优
若画面或 Web 流延迟较大,可按优先级尝试:
- 使用 GPU:安装 CUDA 版 PyTorch,YOLO 会自动使用 GPU
- 降低推理尺寸:
detection.imgsz: 480或320 - 隔帧检测:
detection.skip_frames: 1(跟踪仍保持,适合 25fps 以上) - 换更小模型:
yolov8n.pt(已是最小);或确认未误用yolov8x - RTSP 子码流:改用
Channels/102降低解码压力(需重新标定或保证视角一致) - Web 场景:监控页为 MJPEG,编码与网络也会带来额外延迟;本地调试可用
main.py
算法说明
脚点
不使用检测框中心,使用底部中心点:
foot_x = (x1 + x2) / 2
foot_y = y2
该点近似对应人在地面上的位置。
速度
不用每帧瞬时速度(抖动大),采用滑动窗口内距离变化率:
v = |D(t₂) - D(t₁)| / (t₂ - t₁)
默认窗口 1 秒。地面坐标经卡尔曼滤波平滑后再参与计算。
靠近 / 远离
比较窗口内距离变化,并加阈值与连续确认,避免检测框抖动误判:
|ΔD| < 0.3m → 静止
ΔD < -0.3m → 靠近摄像头
ΔD > +0.3m → 远离摄像头
连续 5 帧满足 → 确认状态变更
阈值与确认帧数可在 motion.* 中调整。
项目结构
yolo判断距离速度/
├── config/
│ ├── config.yaml # 主配置
│ ├── homography_matrix.npy # 标定矩阵(运行后生成)
│ └── homography_matrix.json # 标定点元数据
├── src/
│ ├── detector.py # YOLO + ByteTrack + 脚点
│ ├── homography.py # 像素 ↔ 地面坐标变换
│ ├── kalman_filter.py # 位置卡尔曼滤波
│ ├── motion_analyzer.py # 距离 / 速度 / 方向
│ ├── visualizer.py # OpenCV 英文画面标注
│ ├── pipeline.py # 检测流水线(Web 与扩展共用)
│ ├── live_detection.py # Web 后台检测线程 + MJPEG
│ ├── video_source.py # RTSP 读帧与自动重连
│ └── calibration_service.py # Web 标定 API 逻辑
├── calibrate.py # OpenCV 窗口标定工具
├── main.py # 命令行主入口
├── generate_sample_calibration.py
├── web/
│ ├── server.py # FastAPI:标定 + 实时监控
│ └── static/ # 前端(标定页 / 监控页)
├── requirements.txt
└── README.md
Web API 摘要
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | / | 标定页面 |
| GET | /monitor | 实时监控页面 |
| GET | /api/status | 标定状态、视频源、检测是否运行 |
| POST | /api/capture | 从配置的视频源抓拍一帧 |
| POST | /api/upload | 上传标定用图片 |
| GET | /api/frame | 当前标定帧 JPEG |
| GET | /api/existing | 读取已有标定点 |
| POST | /api/validate | 校验标定点 |
| POST | /api/save | 保存标定 |
| POST | /api/detect/start | 启动后台检测 |
| POST | /api/detect/stop | 停止检测 |
| GET | /api/detect/status | FPS、人员列表、错误信息 |
| GET | /api/detect/stream | MJPEG 实时流 |
RTSP 地址格式
常见格式:
rtsp://admin:密码@IP:554/Streaming/Channels/101 # 主码流
rtsp://admin:密码@IP:554/Streaming/Channels/102 # 子码流
常见问题
标定文件不存在
先完成 Web 或 calibrate.py 标定,或运行 python generate_sample_calibration.py 生成示例(仅用于流程测试,距离不准)。
标定点几乎共线警告
仅在一条线上标定时 Homography 精度不足。请在同一距离处增加左右横向偏移点。
距离明显不准
- 确认卷尺实测距离准确,标定点覆盖人员活动区域
- 增加标定点数量,覆盖人员可能出现的区域
- 摄像头位置或俯仰角变化后需重新标定
RTSP 连接失败
- 确认 IP、端口、账号密码
- 用 VLC 先验证 RTSP 是否可播
- 检查
rtsp_transport(建议tcp) - 可改用
video_file本地视频测试
Web 监控黑屏或 FPS 很低
- 确认已标定且
/api/detect/status无error - 检查 YOLO 是否在 CPU 上运行(安装 GPU 版 PyTorch)
- 尝试
detection.imgsz、skip_frames调优 - 主码流 1080p 解码 + 推理压力大,可试子码流
画面延迟大
- 优先排查 YOLO 推理与 RTSP 缓冲(已默认
CAP_PROP_BUFFERSIZE=1) - Web MJPEG 比本地
main.py窗口延迟更高,属正常现象
