news 2026/10/18 4:41:51

YOLOv5+DeepSORT车辆检测与跟踪:数据集构建及二次开发指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv5+DeepSORT车辆检测与跟踪:数据集构建及二次开发指南

简介:一套基于YOLOv5与DeepSORT的车辆检测与追踪项目配套资源,面向计算机视觉研究者和开发人员,解决实时车辆识别、多目标跟踪中数据集构建与算法验证难题。资源共2000个文件,核心是1588个XML标注文件,配合409个TXT标签/划分文件、2个Markdown说明文档和1个Python划分脚本,压缩包总大小仅29.76MB,结构清晰便于下载部署。目前已有150人学习浏览。使用这份资料,可直接基于处理好的标注数据训练YOLOv5,并集成DeepSORT算法,在遮挡、重叠等复杂场景下实现稳定追踪;提供的划分脚本支持自定义数据集分配,便于开展消融实验与模型调优。YOLOv5速度快、准确率高,适合实时视频流处理,结合DeepSORT可适应智能交通监控、停车场管理、无人驾驶环境感知等应用场景,有效降低二次开发和学术研究门槛。

1. 车辆检测与跟踪项目:YOLOv5 结合 DeepSORT,从数据集到二次开发一次讲透

先抛一个反直觉的结论:很多人以为 YOLOv5 和 DeepSORT 是两套独立的算法,推理时各跑各的再拼起来就行,实际上真正能用的车辆检测追踪项目,核心难点不在模型精度,而在两个算法之间的数据对接和跟踪器参数调优。如果你只想跑通一个车辆检测 Demo,随便找个目标检测模型就能出框;但如果你要的是“视频里每一辆车从进入到离开,ID 始终不变”的效果,那 DeepSORT 的级联匹配、马氏距离计算、卡尔曼滤波预测这些环节缺一不可。这个项目恰好把这两块都做完了,还附带已经划分好的车辆数据集,适合正在做智能交通、停车管理、车流统计的开发者,或者想研究检测与跟踪联合调优的学习者。下面我从数据集结构讲起,逐步拆到运行命令和二次开发改造点,保证你能照着把项目跑起来,也知道每一行关键代码在干什么。

2. 项目全貌与数据集结构:先看资源里有什么,再谈怎么跑

2.1 资源文件清单与作用

拿到这份资源,解压后第一眼会看到 README.md、split_train_val.py 脚本,以及一堆 car_net_*.txt 文件(如 car_net_141.txt、car_net_7.txt、car_net_5.txt、car_net_161.txt、car_net_40.txt、car_net_151.txt 等)。这些以 car_net 开头的 txt 文件,是已经处理好的数据集标签文件,每个文件名中的数字代表某一类车辆网络或某个数据分片编号。常见做法是,每个 txt 文件的每一行记录一个目标框信息,格式为类别、中心点 x、中心点 y、宽度 w、高度 h,或者按 YOLO 标签格式的 class x_center y_center width height 存储。

split_train_val.py 是数据集划分脚本,它把原始车辆图片和标签按比例拆分成训练集与验证集。通常这种脚本会读取标注文件,将图片路径列表随机打乱,然后按 8:2 或 9:1 的比例输出 train.txt 和 val.txt 两个清单文件。val.txt 已经在资源中直接提供,说明划分结果已经生成,你不需要重新执行划分就能上手训练或验证。

2.2 数据集与训练流程的关系

这个项目的设计思路是“开箱即用”:训练好的 YOLOv5 权重文件配合 DeepSORT 特征提取权重,加载后即可对视频帧做检测和跟踪。附带的 val.txt 和 car_net 系列标注文件,价值在于让你可以验证模型效果,或者用同一份数据继续微调。数据集的车辆类别可能覆盖轿车、卡车、公交车等常见车型,标签文件编号不同代表不同批次的数据分片,便于分批训练或增量学习。

使用这份数据时,建议把图片文件与标签文件放在同一个目录前缀下,YOLOv5 训练时会通过 txt 中的图片路径自动找到对应标注文件。假如你想重新划分数据集,只需修改 split_train_val.py 中的源图片目录和划分比例,然后执行 python split_train_val.py 即可生成新的 train.txt 和 val.txt。注意划分脚本输出的是图片路径清单,而不是移动真实图片文件,这样不会破坏原始数据目录结构。

3. 核心模块拆解:YOLOv5 检测与 DeepSORT 跟踪的完整链路

3.1 YOLOv5 检测端的输出处理

YOLOv5 检测端输出的原始结果是检测框坐标、置信度和类别 ID,但这些数据不能直接喂给 DeepSORT。在实际项目中,我一般会写一个转换层,把 YOLOv5 的 tensor 输出变成 DeepSORT 的 detections 输入格式,核心代码如下:

def yolo_to_deepsort_detections(yolo_output, conf_threshold=0.5): detections = [] for *xyxy, conf, cls in yolo_output: if conf < conf_threshold: continue x1, y1, x2, y2 = [int(v) for v in xyxy] bbox = [x1, y1, x2 - x1, y2 - y1] # 转为 x, y, w, h detections.append((bbox, float(conf), int(cls))) return detections

这段代码的作用是把 YOLOv5 输出的 xyxy 格式边界框转换成 DeepSORT 需要的 x, y, w, h 格式。置信度阈值 conf_threshold 控制检测框的筛选力度,设置过低会引入大量误检框,设置过高则可能漏掉远处的小目标车辆。实际调参时,建议先设为 0.5,再根据视频场景调整到 0.4 或 0.6 观察效果。

转换后的 detections 列表会传给 DeepSORT 的 update 方法,DeepSORT 内部用卡尔曼滤波器预测每个已跟踪目标在当前帧的位置,然后用匈牙利算法做检测框与预测框的匹配。这里有个容易踩坑的点:YOLOv5 在 GPU 上输出的检测结果如果直接转成 Python list 再传给 DeepSORT,会带来额外的数据拷贝开销。常见做法是保留 tensor 在 GPU 上做简单过滤,只在最后一步转格式,减少 CPU-GPU 间数据传输频率。

3.2 DeepSORT 跟踪器的参数配置

DeepSORT 跟踪器的初始化参数直接影响跟踪稳定性。下面是项目里常见的初始化写法及其含义:

from deep_sort import DeepSort deepsort = DeepSort( model_path='deep_sort_pytorch/configs/deep_sort.yaml', max_dist=0.2, # 特征距离阈值 min_confidence=0.3, # 最低检测置信度 nms_max_overlap=0.7, # 非极大抑制重叠阈值 max_iou_distance=0.7, # 级联匹配的 IoU 阈值 max_age=30, # 目标丢失后保留帧数 n_init=3, # 确认跟踪前最少匹配帧数 nn_budget=100, # 特征库最大容量 )

max_dist 是外观特征的马氏距离阈值,大于这个距离的检测框不会与轨迹关联,数值越小越严格,适合车辆外观差异明显的场景。max_age 表示目标丢失后最多保留多少帧再删除轨迹,设置过大会让已经离开画面的车辆 ID 残留很久,设置过小则会频繁丢失 ID。n_init 是轨迹确认参数,一个候选轨迹必须连续匹配 n_init 帧才会变成确认状态,否则不参与输出。

在车辆场景中,由于车辆外形相似度高,颜色接近的车辆容易被互相混淆。常见做法是把 max_dist 调低到 0.15 左右,同时增大 max_age 到 50,让轨迹在遮挡后能更快恢复。如果视频中车辆密度很高,可以适当增大 nms_max_overlap 到 0.8,避免相邻车辆的检测框被过度抑制。

3.3 检测与跟踪的串联执行流程

整个项目的核心执行逻辑是一个循环处理视频帧的流程:读取帧、YOLOv5 检测、格式转换、DeepSORT 更新、绘制结果、输出视频。关键代码如下:

cap = cv2.VideoCapture(video_path) while True: ret, frame = cap.read() if not ret: break results = yolo_model(frame) # YOLOv5 推理 yolo_dets = results.xyxy[0].cpu().numpy() detections = yolo_to_deepsort_detections(yolo_dets) outputs = deepsort.update(detections, frame) for x1, y1, x2, y2, track_id, cls in outputs: cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, f'ID:{track_id}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) out.write(frame)

这段代码里,deepsort.update 的第二个参数传入的是当前帧图像,用于提取外观特征。DeepSORT 内部会用一个小型 ReID 网络对每个检测框区域提取 512 维特征向量,并存入轨迹的特征库。当轨迹被遮挡时,匹配会优先使用运动特征,其次才用外观特征,这是 DeepSORT 相比 SORT 在遮挡场景下更鲁棒的关键原因。

需要注意的是,DeepSort 初始化时必须设置 model_path 指向 deep_sort.yaml 配置文件,其中包含了 ReID 网络的权重路径和特征维度。如果你的视频分辨率很高,处理速度会明显下降,常见做法是先对图像做等比缩放,检测完成后再把检测框坐标映射回原图,这样做可以显著提升 fps。

4. 数据划分与训练验证:split_train_val.py 的实际用法

4.1 数据划分脚本的工作方式

split_train_val.py 是项目里负责数据集划分的工具,它的核心逻辑是读取所有标注文件,生成图片路径列表并拆分。一个标准的划分脚本内部流程如下:

import os import random image_dir = 'datasets/images' label_dir = 'datasets/labels' train_ratio = 0.8 images = [f for f in os.listdir(image_dir) if f.endswith('.jpg')] random.shuffle(images) split_idx = int(len(images) * train_ratio) train_images = images[:split_idx] val_images = images[split_idx:] with open('train.txt', 'w') as f: for img in train_images: f.write(os.path.join(image_dir, img) + '\n') with open('val.txt', 'w') as f: for img in val_images: f.write(os.path.join(image_dir, img) + '\n')

这段代码中,train_ratio 控制训练集占比,0.8 意味着 80% 的图片用于训练,20% 用于验证。random.shuffle 保证了数据分布的随机性,避免同一时间段拍摄的车辆图片全部落在训练集或验证集,导致验证指标失真。生成的 train.txt 和 val.txt 每一行是图片的绝对路径或相对路径,YOLOv5 训练时通过这两个文件定位图片,然后根据图片文件名去对应目录下找同名 txt 标注文件。

4.2 使用预训练权重继续训练

拿到项目附带的数据集后,除了直接加载训练好的权重做推理,还可以继续微调。YOLOv5 的训练命令通常如下:

python train.py --data vehicle.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 50

vehicle.yaml 文件里需要配置 train.txt、val.txt 路径以及类别数量和类别名称。训练时 YOLOv5 会自动读取标注文件中的类别 ID,因此必须确保数据集中的类别编号与 yaml 文件中的 names 列表一一对应。如果类别顺序对不上,模型训练会直接错乱,这也是常见的数据集翻车点之一。

训练完成后会生成 runs/train/exp 目录,里面保存了 best.pt 和 last.pt 权重。推理时把 --weights 参数指向 best.pt 即可。微调时建议把学习率调低一个数量级(如 0.0001),冻结前几层卷积参数,只训练后面几层,这样可以避免在小数据集上过拟合,同时保留预训练模型对通用特征的提取能力。

4.3 验证集的作用与评估指标

val.txt 文件在项目中扮演验证集清单的角色,它的作用是评估模型在未见数据上的表现。YOLOv5 的 val.py 脚本会读取每张图片,运行检测,并使用 COCO 或自定义指标计算 mAP、precision、recall。运行验证命令:

python val.py --weights best.pt --data vehicle.yaml --img 640

验证结果的输出在 runs/val/exp 中,包含每种类别的精确率和召回率曲线、混淆矩阵和 mAP 值。如果发现某些车辆类别的 AP 值明显低于其他类别,通常原因是该类别的训练样本过少,或者数据集中的标注框存在误差。此时需要检查 car_net 系列标签文件中的对应类别数量,考虑补充数据或启用数据增强策略。

5. 常见问题与避坑指南:跑通这个项目需要注意的细节

5.1 检测框乱跳或 ID 频繁切换

现象:车辆在画面中行驶时,跟踪框能正确框住车辆,但 ID 数字频繁变化,同一辆车从画面左侧走到右侧已经换了三四个 ID,导致无法统计车辆数量。

原因:DeepSORT 的 max_dist 阈值设置过大,导致不同车辆的外观特征被判定为同一目标;或者 max_age 设置过小,车辆被短暂遮挡后轨迹就被删除,重新出现时匹配不上旧轨迹,只能分配新的 ID。

解决:先记录当前 max_dist 和 max_age 值,把 max_dist 从 0.2 降低到 0.1,观察 ID 切换是否减少;再把 max_age 从 30 提高到 50,给遮挡车辆保留更长的轨迹记忆。调整后重新运行程序,对比 ID 切换次数。

5.2 数据集标签文件读取报错

现象:训练时提示 “FileNotFoundError: No such file or directory”,并且指向 car_net_*.txt 或 val.txt 中的一个路径。

原因:split_train_val.py 生成的 txt 文件中记录的是绝对路径,而你把数据集拷贝到另一台机器后,路径前缀变了,原来记录的 /home/user/datasets/images/xxx.jpg 在当前机器上不存在。

解决:打开 train.txt 或 val.txt,检查路径前缀,用文本编辑器的全局替换功能把旧前缀改成新前缀。更规范的做法是修改 split_train_val.py 中的 image_dir 为相对路径,重新生成清单文件,这样迁移项目时不需要改路径。我一般还会在训练脚本开头加一段路径存在性检查逻辑,遍历 txt 中前 5 个路径,发现不存在就提前退出。

5.3 检测模型正常但跟踪框出现偏移

现象:YOLOv5 单独运行时检测框准确贴合车辆,但接入 DeepSORT 后跟踪框比车辆实际位置偏左或偏下半个车身。

原因:检测框坐标从 YOLOv5 的 tensor 转到 DeepSORT detections 时格式转换错误。YOLOv5 的 xyxy 输出是左上和右下坐标,而 DeepSORT 的 update 方法内部先做 x, y, w, h 转换时使用的是 x, y 作为左上角坐标,如果你传递的是中心点坐标,就会出现系统性偏移。

解决:检查 yolo_to_deepsort_detections 函数中的 bbox 构造,确认 x1, y1 是检测框左上角坐标,width 和 height 是差值。如果仍有偏移,在代码里临时输出检测框原始坐标和转换后坐标,逐帧对比方便定位问题。这类问题通常只出现在自己改过转换逻辑之后,使用官方提供的示例代码一般不会遇到。

5.4 视频处理速度过慢

现象:输入视频是 1080p 分辨率,但处理速度只有 3-5 fps,完全达不到实时要求。

原因:YOLOv5 模型选得太大(如 yolov5x),或者视频帧没有缩放直接送入检测器;另一方面,DeepSORT 的 ReID 特征提取也会消耗大量 GPU 资源,两个模型串行执行时单帧延迟累加。

解决:先换用 yolov5s 或 yolov5n 这种轻量级模型,检测速度会快很多;同时对视频帧做缩放处理,例如把长边缩放到 640 像素,检测完毕后再把坐标映射回原始分辨率。DeepSORT 的 nn_budget 可以适当降低,特征库过大时检索耗时会明显增加,设到 50 通常够用。

5.5 训练时显存不足

现象:使用 batch-size 16 训练时,程序报 CUDA out of memory,训练直接中断。

原因:训练图片分辨率是 640,batch-size 16 的组合在显存 8GB 的显卡上已经超过显存容量,尤其开启了 mosaic 增强后中间张量占用更大。

解决:把 batch-size 逐步调低到 8 或 4,同时把 --img 参数降到 416 或 320,显存占用会大幅下降。如果显存仍然不够,可以通过 --workers 降低数据加载线程数,减少 CPU 与 GPU 之间的数据传输压力。训练模型的精度损失可以通过增加训练轮数来弥补,常见做法是 batch-size 减半后把 epochs 加倍。

6. 二次开发思路:把这个车辆检测项目改造成车流统计系统

6.1 基于跟踪 ID 实现车流量统计

当你已经能稳定拿到每辆车的 track_id 后,下一步自然是把跟踪结果变成业务数据。最直接的应用是车流统计:在画面中画一条虚拟检测线,每当一个带 ID 的车辆跨过这条线,就记录一次计数。实现思路是维护一个已计数 ID 集合,车辆位置从线的一侧变化到另一侧时判断一次。核心逻辑如下:

passed_ids = set() line_y = 480 # 虚拟检测线位置 for x1, y1, x2, y2, track_id, cls in outputs: center_y = (y1 + y2) // 2 prev_y = track_history.get(track_id, center_y) if prev_y < line_y <= center_y or prev_y > line_y >= center_y: if track_id not in passed_ids: vehicle_count += 1 passed_ids.add(track_id) track_history[track_id] = center_y

这个逻辑里,track_history 保存每个 ID 上一次的中心 y 坐标。检测到中心点跨越 line_y 时,判断该 ID 是否已经计入;一个 ID 只计一次,避免同一辆车来回晃动时被重复计数。line_y 的取值要放在视频画面中车辆必经的位置,同时避开交叉路口内车辆乱序行驶的区域。

6.2 按类别统计不同车型的车流占比

DeepSORT 的 update 返回结果中包含了 detections 里的类别信息,因此你可以同时统计轿车、卡车、公交车的数量。在检测端的 yolo_to_deepsort_detections 中,类别 ID 被保留在每条 detection 的第三个元素中,跟踪器会将类别 ID 与 track_id 绑定,跨帧输出时类别保持一致。统计时只需在跨线判断中加入类别判断分支即可。

如果想统计道路上下游两个方向的车流,可以用两条虚拟线分别计数。反向判断用中心点 y 坐标的增减方向区分,从屏幕上方到下方记为下行,从下方到上方记为上行。这个方法适合在高速公路监控场景中做出入口车流量对比。

6.3 调试与验证的工程化习惯

改造完统计逻辑后,验证是最容易被忽略的环节。我第一次做这类功能时,把虚拟检测线画在窗口预览中,但在实际部署时不显示窗口,结果发现计数线位置和预期差了 50 像素,导致统计偏差很大。从那以后,我每次加可视化功能都先跑一遍带窗口的调试模式,确认检测线位置和车辆轨迹行为符合预期,再切换成无声版批量处理模式。建议在代码里加一个 show_video 开关参数,调试时置为 True,正式处理时置为 False,这样能避免反复修改代码。

另外,输出结果建议写成 CSV 或 JSON,包含每条记录的 track_id、时间戳、类别和越过检测线的方向。数据落盘后可以做后续的时段流量分析、拥堵指数计算等。希望这些改造思路能帮你把项目能力延伸到实际业务场景中,减少重复造轮子的成本。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 4:41:30

Flutter引导页实战:PageView+Indicator实现动态指示器与状态持久化

我曾经和朋友讨论过一个问题&#xff1a;在 Flutter 里实现一个 App 首次启动的引导页&#xff0c;到底是不是只用 PageView 就能搞定&#xff1f;答案当然是否定的。真正把一个引导页做得完整、顺滑、可维护&#xff0c;背后其实还牵扯到页码监听、指示器动画、按钮状态管理、…

作者头像 李华
网站建设 2026/10/18 4:38:58

Python代码执行过程全解析:从源码到字节码与虚拟机运行

平时写Python大家都有过这样的好奇&#xff1a;一个一个.py文件&#xff0c;双击或者敲一行python demo.py&#xff0c;屏幕上就出现了结果&#xff0c;看起来毫不费力。可你有没有停下来想过&#xff0c;它到底是怎么被“读懂”的&#xff1f;为什么代码里某个变量能记住上次的…

作者头像 李华
网站建设 2026/10/18 4:38:24

CSC联培推荐信写作规范:科研叙事、证据链与可验证性

简介&#xff1a;本资源是一份专为申请国家留学基金委&#xff08;CSC&#xff09;联合培养博士研究生项目的高校导师定制的推荐信模板&#xff0c;面向国内高校硕博导师、研究生院管理人员及拟申报CSC联培项目的博士生本人。模板严格对标CSC校内评审要求&#xff0c;完整覆盖被…

作者头像 李华
网站建设 2026/10/18 4:38:18

MATLAB实现可扩展二阶随机优化器:加速深度学习收敛

做深度学习训练调优的人&#xff0c;多少都会经历这样一个阶段&#xff1a;一开始用带动量的 SGD&#xff0c;收敛慢得让人怀疑人生&#xff1b;换成 Adam 之后&#xff0c;前期确实稳&#xff0c;可跑到后期就磨磨蹭蹭&#xff0c;loss 曲线像蜗牛爬坡。这时候你会想&#xff…

作者头像 李华
网站建设 2026/10/18 4:37:52

MySQL基础操作实战:从增删改查到索引慢查询优化

做后端开发这些年&#xff0c;MySQL几乎是我每天都要打交道的数据库。不管项目大小&#xff0c;业务代码里最频繁出现的还是那几条SQL&#xff1a;建表、插数据、查数据、更新、删除&#xff0c;也就是大家常说的“增删改查”。很多人觉得MySQL基础操作就是背几条命令&#xff…

作者头像 李华
网站建设 2026/10/18 4:37:03

DH2URDF:从DH参数表到URDF的自动转换与仿真验证

简介&#xff1a;DH2URDF 是一份面向机器人学与运动学建模学习者的 JavaScript 工具资源&#xff0c;用于将 Denavit-Hartenberg 参数表转换为统一机器人描述格式&#xff08;URDF&#xff09;&#xff0c;解决手工编写 URDF 繁琐、易错的问题。资源包共 9 个文件&#xff0c;以…

作者头像 李华