☰
YOLOv5+DeepSORT车辆跟踪实战:从检测到部署的避坑指南
2026/10/7 18:56:35 网站建设 项目流程

简介:本资源为毕业设计《基于yolov5+deepsort实现车辆目标跟踪与应用》的完整Python项目源码与文档说明,面向计算机、人工智能、通信工程、自动化等专业的在校学生、教师及企业员工,适合作为毕设、课程设计、作业或项目初期立项演示,也适合小白进阶学习。项目功能涵盖摄像头视频播放、目标检测与多目标跟踪、车流量统计、车辆违停检测、车辆逆行检测以及信息栏控制等模块,代码均经过测试运行成功。压缩包共134个文件,约43.71MB,以64个py源码、30个yaml配置、9个png与2个jpg图示、7个xml标注、6个sh脚本及3个md说明为主,另含Dockerfile、license等工程化文件,目录结构清晰便于按模块检索。目前已有108人学习下载。下载后建议先阅读README.md,可在此基础上修改扩展实现其他功能,仅供学习参考,切勿用于商业用途。

1. 从一段路口视频说起:YOLOv5 + DeepSORT 到底在车流里干了什么

一段普通的城市路口监控,画面里十几辆车同时移动,有遮挡、有并线、有掉头。如果只跑 YOLOv5,你拿到的是每一帧里一堆独立的检测框,帧与帧之间没有任何身份关联——第 10 帧的 3 号框和第 11 帧的 3 号框是不是同一辆车,模型自己也不知道。车辆目标跟踪要解决的正是这个问题:给每一辆车分配一个稳定的 ID,让它在整个视频里被持续跟住。YOLOv5 负责“看见”,DeepSORT 负责“记住并认人”,两者串起来就是一套能落地的多目标跟踪方案。这套组合之所以成为毕业设计和工程入门的常见选择,是因为检测端开箱即用、跟踪端逻辑清晰、Python 生态完整,一台带显卡的机器就能跑通全流程。适合做智能交通统计、停车场车流分析、无人小车感知模块的从业者,也适合需要一份完整可复现项目的学生。下面按“先跑通、再调优、最后避坑”的顺序拆开讲。

2. YOLOv5 检测端:从权重加载到车辆类别过滤

2.1 为什么检测端选 YOLOv5 而不是别的

跟踪效果的上限由检测质量决定。DeepSORT 本身不做检测,它只负责把当前帧的检测框和已有轨迹做匹配。如果检测框抖动严重、漏检频繁,跟踪 ID 就会频繁跳变,也就是常说的“ID switch”。YOLOv5 在这个环节的优势是推理速度快、对小目标有一定召回、模型体积从 n 到 x 可调,方便在精度和速度之间取舍。车辆跟踪场景里,路口画面通常 1080P 甚至更高,车辆在画面中占比不小,用 yolov5s 或 yolov5m 就能拿到不错的召回。如果部署在树莓派或 RK3568 这类边缘设备上,一般会选 yolov5n 并配合量化,这个后面单独说。

COCO 数据集里和车辆相关的类别主要是 car、bus、truck、motorcycle,对应类别索引是 2、5、7、3。做车辆跟踪时,通常只保留这几类,把行人和其它类别过滤掉,减少 DeepSORT 的匹配负担。

2.2 加载模型并只保留车辆类的最小代码

import torch import cv2 import numpy as np # 加载 YOLOv5 模型,weights 换成自己训练或官方下载的权重 model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) model.conf = 0.4 # 置信度阈值,低于此值的框丢弃 model.iou = 0.45 # NMS 的 IoU 阈值,控制重叠框合并 model.classes = [2, 3, 5, 7] # 只保留 car/motorcycle/bus/truck def detect(frame): # YOLOv5 接受 RGB,OpenCV 读进来是 BGR,需要转换 img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = model(img_rgb, size=640) # 取出 xyxy 坐标、置信度、类别 dets = results.xyxy[0].cpu().numpy() boxes = [] for x1, y1, x2, y2, conf, cls in dets: boxes.append([x1, y1, x2, y2, conf, int(cls)]) return np.array(boxes)

这段代码做了三件事:加载权重、设置过滤参数、把检测结果整理成 DeepSORT 能吃的格式。model.conf和model.iou是最常调的两个参数,conf 调低召回高但误检多,调高则漏检多。size=640是推理分辨率,路口远景车辆小的时候可以提到 1280,但速度会明显下降。classes过滤是车辆跟踪的必备步骤,不过滤的话行人轨迹会混进来,统计车流量时数字会虚高。

2.3 检测端参数怎么定:三个必调项

参数作用车辆场景建议值调整影响
conf置信度阈值0.35 ~ 0.5调低召回升、误检增,ID 跳变可能变多
iouNMS 重叠阈值0.4 ~ 0.5调低重叠框合并更狠,密集车流可能丢车
size推理分辨率640 或 1280远景小车用 1280,边缘设备用 640 甚至 416

这三个参数没有万能值,取决于你的画面里车有多大、车流有多密。我一般会先固定 iou=0.45,然后拿一段典型视频,把 conf 从 0.5 往下调到 0.3,看哪个值下漏检和误检的平衡最好。如果画面里车辆密集且互相遮挡,iou 可以适当降到 0.4,让 NMS 更激进地合并重叠框,但要注意别把并排的两辆车合成一个。

3. DeepSORT 跟踪端:卡尔曼滤波、匈牙利匹配和级联策略

3.1 DeepSORT 凭什么能记住一辆车

DeepSORT 的核心是“运动预测 + 外观特征 + 匹配”。它给每条轨迹维护一个卡尔曼滤波器,用上一帧的位置和速度预测当前帧的位置,这叫运动信息。同时,它用一个 ReID 网络提取每个检测框的外观特征向量,存进轨迹的特征库,这叫外观信息。匹配的时候,先把预测框和当前检测框做级联匹配,优先匹配最近出现过的轨迹,再用 IoU 匹配兜底。外观特征的作用是在两辆车交叉、遮挡时,靠“长得像不像”来区分,而不是只靠位置。

车辆跟踪里,外观特征对同色同款车效果会打折扣,但运动预测能补上。卡尔曼滤波在匀速直线运动下很准,车辆突然变道或急刹时预测会偏,这时候外观特征和 IoU 匹配就起作用了。

3.2 把 YOLOv5 检测结果喂给 DeepSORT

from deep_sort_realtime.deepsort_tracker import DeepSort # 初始化 DeepSORT,max_age 是轨迹丢失后保留的帧数 tracker = DeepSort( max_age=30, # 轨迹丢失 30 帧后删除 n_init=3, # 连续 3 帧匹配上才确认轨迹 max_iou_distance=0.7, # IoU 匹配阈值 embedder="mobilenet", # 外观特征提取网络 embedder_gpu=True ) def track(frame, detections): # detections 格式: [[x1,y1,w,h,conf,cls], ...] ds_dets = [] for x1, y1, x2, y2, conf, cls in detections: w, h = x2 - x1, y2 - y1 ds_dets.append(([x1, y1, w, h], conf, int(cls))) tracks = tracker.update_tracks(ds_dets, frame=frame) results = [] for t in tracks: if not t.is_confirmed(): continue x1, y1, x2, y2 = t.to_ltrb() results.append([x1, y1, x2, y2, t.track_id]) return results

这里max_age和n_init是两个关键参数。max_age=30意味着一辆车被遮挡 30 帧以内,轨迹还保留着,重新出现时能接上同一个 ID;设太小,遮挡后 ID 就断了。n_init=3是确认阈值,连续 3 帧匹配上才给正式 ID,能过滤掉一闪而过的误检。max_iou_distance=0.7控制 IoU 匹配的宽松程度,调大匹配更容易但可能错配,调小则容易断轨。

3.3 级联匹配和 IoU 匹配的分工

DeepSORT 的匹配分两步。第一步是级联匹配,按轨迹上次更新的时间排序,越近的轨迹优先级越高,用外观特征余弦距离做代价矩阵,再用匈牙利算法求解。第二步是 IoU 匹配,处理那些没匹配上的轨迹和检测,用 IoU 距离做代价。级联匹配保证了近期活跃的轨迹优先拿到检测框,减少 ID 跳变。车辆场景里,如果外观特征区分度不高,可以适当降低外观距离的权重,让 IoU 匹配承担更多。

4. 避坑与排查:车辆跟踪里最容易翻车的五个地方

4.1 现象:车辆 ID 频繁跳变,同一辆车几帧换一个 ID

原因通常是检测框抖动或漏检。YOLOv5 在车辆被遮挡时可能漏检,DeepSORT 的轨迹预测撑不过max_age就断了,重新检测到时分配新 ID。解决方法是把max_age调大,比如从 30 提到 50,同时把n_init降到 2,让轨迹更容易确认。另外检查检测端的 conf 是不是设太高,导致遮挡时直接漏检。

4.2 现象:两辆并排的车被跟成同一个 ID

这是匹配错配,常见于两车外观相似且距离很近。原因是 IoU 匹配时两个检测框和同一条轨迹的 IoU 都超过阈值,匈牙利算法选了代价小的那个,另一辆车就被合并。解决方法是降低max_iou_distance,比如从 0.7 降到 0.5,让匹配更严格;同时确认外观特征网络是否正常工作,embedder设成mobilenet或torchreid都可以,但要保证输入图像质量。

4.3 现象:跟踪框滞后于车辆,画面里框在车后面

卡尔曼滤波的预测和更新有延迟,尤其是车辆加速或急刹时。解决方法是检查检测频率和跟踪更新频率是否一致,如果检测每帧都跑但跟踪隔帧更新,滞后会更明显。另外可以调卡尔曼滤波的过程噪声参数,但 DeepSORT 封装后一般不改,更实际的做法是提高检测帧率或降低max_age让轨迹更快响应。

4.4 现象:GPU 显存爆了,跑几分钟就卡死

YOLOv5 和 DeepSORT 的 ReID 网络同时占显存,如果size设成 1280 且 batch 没控制,很容易爆。解决方法是把size降到 640,embedder_gpu设成 False 让 ReID 跑 CPU,或者换更小的 YOLOv5n。边缘设备上还要注意 PyTorch 版本和 CUDA 版本匹配,版本不对会直接报错。

4.5 现象:视频跑完统计的车流量和实际差很多

这通常是类别过滤没做好,或者轨迹去重逻辑有问题。检查model.classes是否只保留了车辆类,DeepSORT 的n_init是否太低导致误检被确认成轨迹。另外统计车流量时,一般用“轨迹首次确认时计数”或“轨迹穿过某条线时计数”,不要每帧都计数,否则同一辆车会被重复统计。

5. 进阶:把跟踪结果用起来,以及边缘部署的取舍

跑通检测加跟踪只是第一步,真正有价值的是把轨迹数据用起来。车辆跟踪的典型应用是车流量统计、平均速度估计、轨迹热力图。车流量统计可以用一条虚拟线,轨迹中心点从线的一侧移到另一侧时计数加一。速度估计需要像素到实际距离的标定,用车道线宽度或已知参照物换算。轨迹热力图把每条轨迹的中心点画到一张图上,能看出车流的主要走向。

边缘部署是另一个绕不开的话题。树莓派 4B 或 RK3568 上跑 YOLOv5 + DeepSORT,通常要把 YOLOv5 转成 ONNX 或 RKNN,DeepSORT 的 ReID 网络换成轻量模型或直接关掉外观特征只用 IoU 匹配。关掉外观特征后,跟踪效果在车辆密集时会下降,但速度能提上来。我的习惯是先在 PC 上把参数调好,记录一组基准值,再移植到边缘设备上逐项降配,每次只改一个参数,看跟踪 ID 跳变率的变化。这套方案值不值得做,取决于你的场景对实时性和精度的要求:如果只是离线分析视频,PC 上跑就够;如果要上路口设备,边缘优化的工作量不小,但路径是清晰的。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询