YOLOv10 速度估计实战:基于对象跟踪与区域判定实现实时车速测算
【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10
速度估计是计算机视觉中通过目标在视频帧间的位移与时间差计算其运动速率的经典任务,常用于交通流量监控、无人驾驶导航与安防预警等场景。本文以仓库内的 speed-estimation.md 指南为核心,结合 SpeedEstimator 源码 与 model.track 跟踪接口,完整讲解如何在 YOLOv10 项目中搭建一套"检测 → 跟踪 → 区域判定 → 速度计算"的端到端速度估计流水线,并深入剖析每个参数与关键算法的底层实现。
什么是速度估计
速度估计(Speed Estimation)指在给定场景上下文中计算对象移动速率的过程,是计算机视觉中的常见任务。基于对象跟踪技术,配合距离与时间数据即可计算目标速度,这在交通与安防等场景中至关重要。速度估计的准确性直接影响各类应用系统的效率与可靠性,是智能系统实时决策能力的关键组成部分。
在 YOLOv10 项目中,该功能由解决方案模块 speed_estimation.py 提供,核心类是SpeedEstimator。从源码结构看,其工作链路为:
- 通过
model.track()对视频帧执行目标检测与多目标跟踪,获得每个对象的边界框与跟踪 ID(见 model.py 的 track 方法); SpeedEstimator.extract_tracks()从跟踪结果中提取边界框坐标、类别与跟踪 ID(speed_estimation.py 第 78-87 行);store_track_info()记录每个跟踪目标的中心点轨迹历史(第 89-105 行);calculate_speed()在目标跨越预设测速区域时,利用时间差与 Y 轴位移差计算速度(第 125-155 行)。
速度估计的优势
- 高效交通管控:精确的速度估计有助于管理车流、提升道路安全性并缓解交通拥堵。
- 精准自主导航:在自动驾驶等自主系统中,可靠的速度估计可确保车辆安全、准确地导航。
- 增强安防监控:安防分析中的速度估计有助于识别异常行为或潜在威胁,提升安保措施的有效性。
真实世界应用
速度估计在交通场景中应用广泛,例如在公路上测算车辆行驶速度、在桥梁上监控车速以辅助交通调度与超速预警等。仓库指南中还提供了完整的视频演示(Speed Estimation using Ultralytics YOLOv8),读者可配合下文代码实例对照学习。
快速开始:完整可运行示例
下面是在 YOLOv10 项目中实现速度估计的完整 Python 脚本,可直接复制运行。其核心流程为:加载检测模型 → 打开视频 → 初始化SpeedEstimator→ 逐帧跟踪并估算速度 → 写入输出视频。
from ultralytics import YOLO from ultralytics.solutions import speed_estimation import cv2 model = YOLO("yolov8n.pt") names = model.model.names cap = cv2.VideoCapture("path/to/video/file.mp4") assert cap.isOpened(), "Error reading video file" w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS)) # Video writer video_writer = cv2.VideoWriter("speed_estimation.avi", cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h)) line_pts = [(0, 360), (1280, 360)] # Init speed-estimation obj speed_obj = speed_estimation.SpeedEstimator() speed_obj.set_args(reg_pts=line_pts, names=names, view_img=True) while cap.isOpened(): success, im0 = cap.read() if not success: print("Video frame is empty or video processing has been successfully completed.") break tracks = model.track(im0, persist=True, show=False) im0 = speed_obj.estimate_speed(im0, tracks) video_writer.write(im0) cap.release() video_writer.release() cv2.destroyAllWindows()代码分步解读
- 模型与类别名:
YOLO("yolov8n.pt")加载预训练模型(也可替换为仓库 cfg/models/v10 下对应的yolov10n.yaml权重),model.model.names获取类别名映射字典,供速度标签显示使用。 - 视频读取:
cv2.VideoCapture打开视频文件,并通过CAP_PROP_FRAME_WIDTH / CAP_PROP_FRAME_HEIGHT / CAP_PROP_FPS读取宽、高与帧率,用于初始化输出写入器。 - 测速区域:
line_pts = [(0, 360), (1280, 360)]定义了一条水平测速线(两个端点坐标),该线将叠加绘制在画面上。坐标是像素坐标,需根据实际视频分辨率调整。 - 跟踪推理:
model.track(im0, persist=True, show=False)对当前帧执行跟踪,persist=True表示跨帧持续保留跟踪 ID,这是速度计算能够成立的前提(详见下文model.track参数表)。 - 速度估算:
speed_obj.estimate_speed(im0, tracks)返回叠加了边界框、跟踪轨迹、测速线与速度标签的帧图像,随后由video_writer写入输出视频。
⚠️速度是估算值计算得到的速度为估算值,可能不完全精确;此外,估算结果会随 GPU 速度等因素产生波动。
速度标签的显示逻辑
在源码plot_box_and_track(第 107-123 行)中,若某跟踪 ID 已完成速度计算(存在于dist_data),其边界框标签显示为"{int(speed)}km/ph"形式的车速;否则显示原始类别名。同时,目标的历史轨迹会以绿色折线绘制,当前中心点以彩色圆点标出,便于可视化验证测速结果。
速度计算的底层原理
速度并非由帧数直接换算,而是基于"时间戳 + 像素位移"的估算,核心逻辑位于calculate_speed(第 125-155 行):
- 横向范围预筛选:仅当目标中心点的 X 坐标落在
reg_pts[0][0]与reg_pts[1][0]之间时才继续计算(第 134 行),即只统计测速线水平跨度内的目标。 - 纵向接近判定:判断目标中心点 Y 坐标是否落入测速线端点 Y 值 ±
spdl_dist_thresh的带状范围内。命中则direction = "known",否则为"unknown"(第 136-143 行)。这是"触发测速"的关键门控条件。 - 首次越线记录:当方向为
"known"且该 ID 尚未被记录时,将其加入trk_idslist,并以time()时间差与中心点 Y 坐标差计算speed = dist_difference / time_difference,存入dist_data[trk_id](第 145-152 行)。每个目标只计算一次,避免重复测速。 - 更新历史:每次调用都会更新该 ID 的上一时间戳与上一中心点,用于后续帧的位移差计算。
从源码可以推断:速度值实际为"像素/秒"量级,最终以int()取整后拼上km/ph文本展示。要得到真实物理速度,需在reg_pts与实际世界尺度之间建立换算关系(例如已知测速线对应的真实距离),这属于基于代码结构的合理推断,请结合自身场景标定。
参数详解
SpeedEstimator.set_args可选参数
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
reg_pts | list | [(20, 400), (1260, 400)] | 定义测速区域的点(两点定义一条测速线) |
names | dict | None | 类别名称映射字典 |
view_img | bool | False | 是否实时显示带标注的帧画面 |
line_thickness | int | 2 | 边界框线宽 |
region_thickness | int | 5 | 测速区域(线)的绘制粗细 |
spdl_dist_thresh | int | 10 | 速度判定线的欧氏距离阈值 |
源码中set_args(第 48-76 行)的实现要点:
- 若
reg_pts为None,会打印提示并使用默认值[(20, 400), (1260, 400)](第 68-71 行); - 构造器中
region_thickness默认值为3(第 26 行),而set_args的签名默认值为5,显式传参后以传入值为准; spdl_dist_thresh同时用于calculate_speed中的纵向接近判定(第 136-139 行):该值越小,触发测速的带状区域越窄,对越线判定越敏感。
测速线由Annotator.draw_region(plotting.py 第 342-351 行)通过cv2.polylines以闭合折线形式绘制,颜色由estimate_speed的region_color参数控制(默认(255, 0, 0)红色,第 157 行)。
model.track参数
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
source | im0 | None | 图像或视频的输入源 |
persist | bool | False | 是否在帧之间持续保留跟踪状态(速度估计场景必须设为True) |
tracker | str | botsort.yaml | 跟踪方法:bytetrack或botsort |
conf | float | 0.3 | 置信度阈值 |
iou | float | 0.5 | IOU 阈值 |
classes | list | None | 按类别过滤结果,如classes=0或classes=[0,2,3] |
verbose | bool | True | 是否显示跟踪结果输出 |
model.track是引擎层方法(model.py 第 443 行起),会通过 predictor 注册跟踪器后返回封装在Results类中的跟踪结果列表。若未设置persist=True,跟踪器状态不会跨帧保留,跟踪 ID 可能不稳定,导致SpeedEstimator无法将同一目标的历史轨迹关联起来,速度计算将失去意义。
关键注意点与调优建议
persist=True必不可少:速度估计依赖稳定的跨帧跟踪 ID,务必在model.track中开启该参数。- 测速线与视频分辨率匹配:
reg_pts使用像素坐标,示例中(0, 360)与(1280, 360)适用于 1280×720 左右的画面;分辨率变化时需重新标定坐标。 - 选择合适的跟踪器:仓库 cfg/trackers 提供了
botsort.yaml与bytetrack.yaml两种配置,可通过tracker参数切换。ByteTrack 需要较低置信度输入,官方在model.track中为此设置了专门的默认置信度(见 model.py 第 458-459 行)。 - 速度值是像素级估算:源码输出单位实为像素/秒量级并直接展示为
km/ph,如需物理意义上的真实速度,应根据实际场景做像素—世界坐标标定。 - 无跟踪 ID 时的行为:
estimate_speed中若tracks[0].boxes.id is None,则跳过计算仅返回原帧(第 167-170 行),因此务必确保跟踪链路正常输出 ID。
扩展阅读
- 解决方案模块参考:speed_estimation.md(
SpeedEstimator的 API 文档) - 跟踪模式说明:track.md 与跟踪器配置 botsort.yaml、bytetrack.yaml
- 仓库还提供多种可视化解决方案,可对比参考:object_counter.py、heatmap.py、speed_estimation.py 同位于 solutions 目录
【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考