简介:这是一份面向目标检测学习与工程实践的YOLO系列车辆数据集,覆盖卡车、小型车、摩托车、公交车四类常见道路目标,适合正在做车辆检测项目、课程设计或算法验证的开发者与研究者使用。数据集已按训练与验证需求划分完毕,并附带data.yaml配置文件,可直接接入yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本开展训练与测试。压缩包共约2000个文件,整体62.4MB,其中1589个xml文件对应VOC格式标注,411个txt文件对应YOLO格式标注,两种标签分别存放,便于按框架灵活选用;YOLO标签采用类别索引与归一化中心点、宽高坐标,符合标准解析规范。目前已有111人学习下载。读者可借此省去数据采集与标注成本,快速搭建车辆检测基线,对比不同YOLO版本的训练效果,并借助现成标签完成模型评估与调参验证。
1. 从 2129 张带标签图像说起:这套车辆数据集到底能跑出什么
手头拿到一个叫yolo算法-车辆数据集-2129张图像带标签--卡车-小型车-摩托车-公交车.zip的压缩包,第一反应往往不是兴奋,而是犯嘀咕:2129 张够不够训一个能用的车辆检测模型?四类目标(卡车、小型车、摩托车、公交车)里,公交车和卡车在视觉上高度相似,会不会互相打架?标签到底是 YOLO 的 txt 格式还是 VOC 的 xml?这些问题不搞清楚,直接开训就是浪费显卡。
这篇笔记就围绕这个数据集展开,把「拿到一份中小规模车辆数据集之后,怎么从零跑通 YOLO 训练、怎么判断它值不值得投入、哪些参数必须调、哪些坑一定会踩」讲透。适合两类人:一类是刚接触 YOLO 目标检测、想找一个真实场景数据集练手的新手;另一类是做交通监控、卡口识别、自动驾驶感知预研,需要快速验证一个车辆检测 baseline 的工程师。2129 张不算大,但四类车辆的标注如果质量过关,足够训出一个 mAP50 在 0.85 以上的可用模型,前提是你别在数据格式和类别平衡上翻车。
2. 先搞清楚数据集结构:2129 张图像带标签到底长什么样
2.1 解压后先做三件事:目录清点、格式判定、类别统计
拿到压缩包别急着写训练脚本,先解压看结构。常见的车辆数据集有两种组织方式:一种是images/和labels/平行目录,对应 YOLO 格式;另一种是JPEGImages/+Annotations/+ImageSets/,对应 VOC 格式。判定方法很简单,看标签文件后缀——.txt是 YOLO,.xml是 VOC。
# 解压并查看顶层结构 unzip yolo算法-车辆数据集-2129张图像带标签--卡车-小型车-摩托车-公交车.zip -d vehicle_dataset cd vehicle_dataset find . -maxdepth 2 -type d | head -20 # 统计图像数量和标签数量 find . -name "*.jpg" -o -name "*.png" | wc -l find . -name "*.txt" | wc -l find . -name "*.xml" | wc -l这段命令的逻辑是:先解压到独立目录避免污染当前路径,然后用find逐层查看目录结构,最后分别统计图像、txt 标签、xml 标签的数量。参数说明:-maxdepth 2限制递归深度,避免在大数据集上输出爆炸;-o是 find 的或条件,注意-name "*.jpg" -o -name "*.png"要加括号才严谨,这里简化写法在多数 shell 下也能跑。如果 txt 数量和图像数量对不上,说明有图像漏标,这是第一个要记录的质量问题。
2.2 用脚本统计四类目标的分布,别让类别不平衡埋雷
卡车、小型车、摩托车、公交车这四类,在真实道路场景里的出现频率天然不均。小型车可能占 70%,公交车可能只占 5%。如果直接开训,模型会对小样本类别欠拟合。所以第二步必须做类别分布统计。
import os from collections import Counter # YOLO 格式:每行 class_id x_center y_center width height label_dir = "vehicle_dataset/labels" class_names = ["truck", "car", "motorcycle", "bus"] # 按 data.yaml 里的顺序 counter = Counter() for txt_file in os.listdir(label_dir): if not txt_file.endswith(".txt"): continue with open(os.path.join(label_dir, txt_file), "r") as f: for line in f: parts = line.strip().split() if len(parts) >= 5: counter[int(parts[0])] += 1 total = sum(counter.values()) for cid, name in enumerate(class_names): cnt = counter.get(cid, 0) print(f"{name}: {cnt} 个标注框, 占比 {cnt/total*100:.1f}%")逻辑说明:遍历 labels 目录下所有 txt,每行第一个字段是类别 id,累加计数。参数说明:class_names的顺序必须和训练时data.yaml里的names完全一致,否则统计结果会张冠李戴。跑完如果发现某一类占比低于 5%,就要考虑用数据增强(mosaic、mixup)或者类别权重来补偿。这一步不做,后面训练出来的模型在公交车上大概率是瞎的。
2.3 可视化抽查:随机抽 20 张图把框画出来
统计是数字,可视化才是真相。抽 20 张图把标注框画上去,重点看三件事:框有没有偏移、有没有漏标、公交车和卡车有没有标混。
import cv2 import random import os img_dir = "vehicle_dataset/images" label_dir = "vehicle_dataset/labels" class_names = ["truck", "car", "motorcycle", "bus"] colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0)] samples = random.sample(os.listdir(img_dir), 20) for img_name in samples: img = cv2.imread(os.path.join(img_dir, img_name)) h, w = img.shape[:2] txt_path = os.path.join(label_dir, img_name.rsplit(".",1)[0] + ".txt") if not os.path.exists(txt_path): print(f"漏标: {img_name}") continue with open(txt_path) as f: for line in f: cid, xc, yc, bw, bh = map(float, line.split()) x1 = int((xc - bw/2) * w); y1 = int((yc - bh/2) * h) x2 = int((xc + bw/2) * w); y2 = int((yc + bh/2) * h) cv2.rectangle(img, (x1,y1), (x2,y2), colors[int(cid)], 2) cv2.putText(img, class_names[int(cid)], (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[int(cid)], 2) cv2.imwrite(f"vis_{img_name}", img)逻辑说明:YOLO 格式的坐标是归一化的中心点加宽高,需要乘以图像宽高还原成像素坐标再画框。参数说明:colors按类别给不同颜色,方便肉眼区分;random.sample保证每次抽的图不一样。重点检查公交车和卡车——这两类在侧面视角下轮廓接近,如果标注员偷懒,很容易标错。发现超过 5% 的错标,建议先清洗再训,否则模型学到的就是错的。
3. 从零跑通 YOLO 训练:环境、配置、启动一条龙
3.1 环境搭建:CUDA、PyTorch、Ultralytics 的版本对齐
YOLO 训练翻车,一半以上是环境问题。常见做法是用 conda 建独立环境,先装 PyTorch 再装 ultralytics。版本对齐的原则是:PyTorch 的 CUDA 版本要和你显卡驱动支持的 CUDA 版本匹配,ultralytics 用 pip 装最新稳定版即可。
conda create -n yolo_vehicle python=3.10 -y conda activate yolo_vehicle # 根据你的 CUDA 版本选择,这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python # 验证 python -c "import torch; print(torch.cuda.is_available(), torch.__version__)"逻辑说明:先建环境隔离依赖,再装带 CUDA 支持的 PyTorch,最后装 ultralytics。参数说明:--index-url指定 PyTorch 官方 wheel 源,避免装到 CPU 版本;torch.cuda.is_available()返回 True 才算成功。如果返回 False,先查显卡驱动版本,再查 CUDA 版本是否匹配,别急着怀疑代码。
3.2 写 data.yaml:四个类别名和路径一个都不能错
YOLO 训练靠data.yaml找数据、认类别。这个文件写错,训练直接报错或者类别全乱。
# vehicle_data.yaml path: /absolute/path/to/vehicle_dataset train: images/train val: images/val test: images/test nc: 4 names: 0: truck 1: car 2: motorcycle 3: bus逻辑说明:path是数据集根目录,train/val/test是相对路径。参数说明:nc是类别数,必须和 names 长度一致;names 的顺序必须和标签里的 class_id 对应,顺序错了模型会把卡车认成公交车。如果数据集没有预先划分 train/val,需要自己按 8:1:1 切分,切分脚本要保证图像和标签同步移动。
3.3 启动训练:命令行参数怎么设才不浪费显卡
环境好了、yaml 写好了,就可以启动训练。以 YOLOv8 为例,一条命令搞定,但参数要按数据集规模调。
yolo detect train \ data=vehicle_data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs/vehicle \ name=exp1逻辑说明:model=yolov8s.pt表示用预训练权重做迁移学习,小数据集必须用预训练,否则收敛慢且效果差。参数说明:epochs=100对 2129 张图够用,配合patience=20早停防止过拟合;imgsz=640是标准输入尺寸,显存不够就降到 416;batch=16按显存调,8G 显存用 8 或 16;lr0=0.01是初始学习率,小数据集可以降到 0.005 更稳。启动后盯着 loss 曲线,如果 cls_loss 不降,多半是标签格式或类别名有问题。
3.4 训练过程监控:看什么指标、什么时候该停
训练不是启动了就完事,要盯几个关键指标。YOLO 会在 runs 目录下生成 results.csv 和可视化曲线。
| 指标 | 正常表现 | 异常信号 | 处理 |
|---|---|---|---|
| box_loss | 持续下降后趋稳 | 震荡不降 | 降学习率或查标签 |
| cls_loss | 持续下降 | 突然飙升 | 查类别是否标错 |
| mAP50 | 逐步上升 | 卡在低位 | 查数据量或增强 |
| mAP50-95 | 缓慢上升 | 远低于 mAP50 | 正常,定位精度难 |
逻辑说明:box_loss 管定位,cls_loss 管分类,mAP 是综合指标。参数说明:mAP50 是 IoU 阈值 0.5 下的平均精度,对车辆检测来说 0.85 以上算可用;mAP50-95 更严格,通常比 mAP50 低 0.1 到 0.2。如果训练到 50 轮 mAP50 还在 0.5 以下,别硬撑,停下来查数据。
4. 避坑指南:车辆数据集训练最容易翻车的五个地方
4.1 现象:公交车被识别成卡车,置信度还不低
原因:公交车和卡车在侧面视角下都是长条形,如果标注时边界框画得松,两类特征高度重叠。加上公交车样本少,模型倾向于把它归到样本多的卡车类。
解决:先统计两类样本量,如果公交车少于 200 个框,用 mosaic 增强时对公交车图像提高采样权重;或者在损失函数里给公交车类加 class_weight。更直接的办法是清洗标注,把公交车和卡车的边界框画紧,突出公交车的大面积车窗特征。
4.2 现象:训练 loss 正常下降,但验证集 mAP 一直上不去
原因:训练集和验证集分布不一致。常见于随机切分时,某些场景(比如夜间、雨天)的图全被分到训练集,验证集里没有。
解决:切分时按场景分层抽样,保证每个场景在 train/val 里都有。如果数据集本身场景单一,那就别指望验证集 mAP 能反映真实泛化能力,得另找外部测试集。
4.3 现象:训练到一半 CUDA out of memory
原因:batch 设太大,或者 imgsz 设太高。2129 张图用 yolov8s 在 8G 显存上,batch=16 + imgsz=640 是临界值。
解决:先把 batch 降到 8,如果还爆就降 imgsz 到 416。另一个隐藏原因是 dataloader 的 workers 设太多导致内存泄漏,把 workers 从 8 降到 4 试试。
4.4 现象:标签文件里有空行或坐标超出 0-1 范围
原因:标注工具导出时产生脏数据,或者人工修改时手误。
解决:训练前跑一个校验脚本,检查每行是否有 5 个字段、坐标是否在 0 到 1 之间、class_id 是否在 0 到 3 之间。发现异常行直接剔除或修正,别让脏数据进训练。
import os bad = [] for txt in os.listdir("vehicle_dataset/labels"): with open(os.path.join("vehicle_dataset/labels", txt)) as f: for i, line in enumerate(f): parts = line.strip().split() if len(parts) != 5: bad.append((txt, i, "字段数不对")); continue cid = int(parts[0]) coords = list(map(float, parts[1:])) if cid not in range(4) or any(c < 0 or c > 1 for c in coords): bad.append((txt, i, "类别或坐标越界")) print(f"发现 {len(bad)} 处异常") for b in bad[:10]: print(b)逻辑说明:逐行校验字段数、类别 id、坐标范围。参数说明:range(4)对应四类,坐标必须在 0 到 1 之间。这个脚本跑一遍,能拦掉大部分低级错误。
4.5 现象:推理时小目标摩托车漏检严重
原因:摩托车在图像里占像素少,YOLO 下采样后特征丢失。2129 张图里如果摩托车样本本身少,问题更突出。
解决:训练时开启close_mosaic=10,让最后 10 轮关闭 mosaic 增强,专注小目标;或者把 imgsz 提到 800 再训一轮。推理时把 conf 阈值从 0.25 降到 0.15,能召回更多摩托车,但误检会增加,需要权衡。
5. 进阶技巧:用这套数据集把模型推到可用线以上
5.1 迁移学习 + 冻结训练:小数据集的正确打开方式
2129 张图不算多,从头训必然过拟合。正确做法是分两阶段:先冻结 backbone 训 head,再解冻全量微调。
# 第一阶段:冻结 backbone,只训检测头 yolo detect train data=vehicle_data.yaml model=yolov8s.pt epochs=30 freeze=10 lr0=0.01 # 第二阶段:解冻全量微调,降低学习率 yolo detect train data=vehicle_data.yaml model=runs/vehicle/exp1/weights/best.pt epochs=70 lr0=0.001逻辑说明:freeze=10冻结前 10 层(backbone 主体),只更新检测头,让模型先适应车辆数据的类别分布。参数说明:第一阶段学习率可以高一点,第二阶段必须降,否则会破坏已学到的特征。两阶段加起来 100 轮,比一次性训 100 轮效果更稳。
5.2 用混淆矩阵定位类别混淆,针对性补数据
训练完看混淆矩阵,能直接看出哪两类在互相误判。如果公交车和卡车混淆严重,就针对性地补这两类的难例样本。
from ultralytics import YOLO model = YOLO("runs/vehicle/exp2/weights/best.pt") metrics = model.val(data="vehicle_data.yaml") print(metrics.confusion_matrix)逻辑说明:model.val会在验证集上跑一遍,输出混淆矩阵。参数说明:矩阵对角线是正确分类,非对角线是误判。重点看公交车行和卡车列的交叉值,如果数值大,说明这两类需要更多区分性样本。
5.3 导出 ONNX 做部署前的最后验证
训练完的 pt 模型要部署,通常先导出 ONNX。导出后必须做一次推理对齐,确认精度没掉。
yolo export model=runs/vehicle/exp2/weights/best.pt format=onnx imgsz=640逻辑说明:导出 ONNX 后,用 onnxruntime 跑一张测试图,和 pt 模型的输出对比。参数说明:imgsz=640必须和训练时一致,否则输入尺寸不匹配会导致精度下降。如果 ONNX 推理结果和 pt 差异超过 1%,检查是否有算子不支持或动态轴设置问题。
这套流程走下来,2129 张图的车辆数据集能训出一个在四类目标上 mAP50 达到 0.85 以上的模型,公交车和卡车的混淆能压到可接受范围。我自己踩过的最大坑是没做类别统计就开训,结果公交车几乎全漏,回头补数据浪费了两天。所以拿到数据集先统计、再可视化、最后才训练,这个顺序别省。希望帮到你。
本文还有配套的精品资源,点击获取