
简介这是一份面向YOLO系列算法学习者的车辆检测与计数目标检测数据集适用于yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流框架可直接用于模型训练与验证测试。数据集共1304张图像覆盖汽车、摩托车、公共汽车、卡车四类目标已完成训练集与验证集划分并附带data.yaml配置文件开箱即可投入实验。压缩包内共2000个文件包含911个txt格式的YOLO标注与1089个xml格式的VOC标注两种标签分别存放于独立文件夹便于按需选用YOLO标签采用归一化中心点与宽高比例符合标准训练输入要求。资源包整体约44.02MB体积轻量适合快速搭建车辆检测与计数实验环境。目前已有88人学习下载可作为课程设计、毕业设计或算法入门的实践素材帮助读者省去数据采集与标注环节将精力集中在模型调参与效果对比上。1. 1304 张图、双标签格式这份车辆检测数据集到底能不能直接开训如果你正在找一份能直接跑 YOLO 车辆检测的数据集大概率已经翻过不少仓库要么只有图片没标签要么标签格式对不上自己的训练脚本要么类别定义混乱光整理就要耗掉一整天。这份 1304 张图像的车辆检测与计数数据集核心价值就在于「开箱即训」——图片、YOLO 格式 txt 标签、VOC 格式 xml 标签、data.yaml 配置文件全部齐活类别覆盖汽车、摩托车、公共汽车、卡车四类道路常见目标。它适合三类人一是刚接触 yolo 系列算法、想拿一份干净数据跑通训练全流程的新手二是需要快速验证模型改动效果、不想在数据清洗上浪费时间的熟手三是做车辆计数、交通流量统计这类落地项目、需要一份结构规整的基线数据的开发者。数据集已经划分好训练集与验证集标签坐标采用归一化格式兼容 yolov5、yolov8、yolov9、yolov7、yolov10 以及 yolo11 等主流版本。下面我从目录结构、标签格式、训练配置到踩坑排查把这份资源拆开讲清楚。2. 目录结构与双标签格式先搞懂每份文件是干什么的2.1 拿到压缩包后先看什么解压之后你看到的不是一堆散图而是一套有组织的目录。常见做法是 images 文件夹放图像labels 文件夹放同名的 txt 标签另外单独有一个 xml 文件夹存 VOC 格式标注根目录下放 data.yaml。图像和标签必须同名只是扩展名不同——比如 img_050_518.jpg 对应 img_050_518.txt这是 YOLO 训练时能自动匹配的前提。项目正文里列出的 img_050_518.txt、img_050_715.txt 这些文件名就是标签文件的命名样例。命名规则本身不重要重要的是「图像名 标签名」这个约束。如果你后续自己增补图片务必保持这个对应关系否则训练时会出现「找到图片但找不到标签」的警告那些图会被直接跳过。data.yaml 是整个数据集的入口配置文件它告诉训练脚本三件事训练集和验证集的路径、类别数量、类别名称。这份数据集已经帮你写好了但路径部分通常需要根据你实际解压位置做一次修改。很多人第一次跑失败就是栽在这个路径上。2.2 YOLO 格式标签逐字段拆解YOLO 格式的 txt 标签每行代表一个目标框格式是class x_center y_center width height五个字段用空格分隔。class是类别索引从 0 开始。这份数据集四类目标的索引通常是0 对应汽车1 对应摩托车2 对应公共汽车3 对应卡车。具体顺序以 data.yaml 里的 names 列表为准不要凭记忆写。后面四个值是归一化坐标范围 0 到 1。x_center和y_center是框中心点相对于图像宽高的比例width和height是框宽高相对于图像宽高的比例。举个例子一张 640×480 的图某个框中心在像素 (320, 240)宽 128、高 96那么标签就是0 0.5 0.5 0.2 0.2这里 320/6400.5240/4800.5128/6400.296/4800.2。归一化的好处是图像缩放后标签不用改这也是 YOLO 系列一直用这种格式的原因。注意归一化坐标如果出现大于 1 或小于 0 的值说明标注越界了。训练前建议扫一遍越界框会导致损失计算异常。2.3 VOC 格式 xml 与 YOLO 格式的对应关系xml 文件夹里是 VOC 格式标注结构是标准的annotation根节点下面有filename、size宽高通道、以及若干object每个 object 里有name类别名和bndbox像素坐标xmin、ymin、xmax、ymax。两种格式的区别很直接VOC 用像素绝对坐标YOLO 用归一化中心点加宽高。如果你用的是 YOLOv5 及以上版本训练直接吃 txt如果你要用某些只认 VOC 的评估脚本或者想转 COCO 格式xml 就派上用场了。常见做法是保留两套训练用 txt做可视化核对或跨框架迁移时用 xml 反查。下面这段脚本可以把 VOC 的 xml 批量转成 YOLO 的 txt方便你核对两套标签是否一致import os import xml.etree.ElementTree as ET # 类别名到索引的映射必须和 data.yaml 里的 names 顺序一致 class_map {car: 0, motorcycle: 1, bus: 2, truck: 3} def voc_to_yolo(xml_path, out_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue cls_id class_map[name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 转成归一化的中心点加宽高 x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) # 批量处理 xml_dir xml out_dir labels_check os.makedirs(out_dir, exist_okTrue) for fn in os.listdir(xml_dir): if fn.endswith(.xml): voc_to_yolo(os.path.join(xml_dir, fn), os.path.join(out_dir, fn.replace(.xml, .txt)))逻辑说明先读 xml 里的图像宽高再把每个 object 的像素框转成归一化中心点加宽高。参数上class_map必须和 data.yaml 的 names 严格对应顺序错了类别就全乱。:.6f保留六位小数精度足够。跑完拿生成的 txt 和数据集自带的 txt 对比如果基本一致说明两套标签是同步的如果差异大就要查是哪套标注有问题。3. data.yaml 配置与训练启动从改路径到跑通第一个 epoch3.1 data.yaml 里每个字段怎么改data.yaml 是训练脚本读取数据集的唯一入口。典型内容长这样train: ../train/images val: ../valid/images nc: 4 names: [car, motorcycle, bus, truck]train和val是训练集、验证集图像目录的相对路径相对于 data.yaml 所在位置。如果你把数据集挪了地方这两行必须改否则脚本找不到图。nc是类别数这份数据集是 4。names是类别名列表顺序决定类别索引不能随意调换。常见做法是把 data.yaml 里的路径写成绝对路径省得相对路径算错。比如train: /home/user/dataset/train/images。虽然不够优雅但能避免一大类「路径找不到」的报错。提示改完 data.yaml 后先用几行 Python 验证路径是否存在比直接开训再报错省时间。3.2 用 YOLOv8 跑通训练的最小命令假设你已经装好 ultralytics 包训练命令就一行yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16参数逐个说data指向你的 yamlmodel用预训练的 yolov8n.pt小模型收敛快适合先验证数据没问题epochs100是训练轮数1304 张图这个量级100 轮通常够看趋势imgsz640是输入分辨率和大多数预训练权重匹配batch16看显存显存小就降到 8 或 4。如果你用的是 YOLOv5命令结构类似只是入口换成python train.py --data data.yaml --weights yolov5n.pt --epochs 100 --img 640 --batch 16。YOLOv9、v10、yolo11 的调用方式各有差异但 data.yaml 的格式是通用的这也是这份数据集兼容多版本的原因。训练启动后重点看第一轮输出里的几行train: Scanning...后面跟的图像数量和标签数量。如果标签数量明显少于图像数量说明有图没匹配到标签回去查命名。val: Scanning...同理。这两个数字对不上后面指标全是虚的。3.3 训练中该盯哪些指标跑起来之后终端会打印每个 epoch 的 box_loss、cls_loss、dfl_loss 和 mAP。box_loss 是框回归损失cls_loss 是分类损失这两个应该整体下降。mAP50 和 mAP50-95 是精度指标前者宽松后者严格正常情况随训练上升。1304 张图、四个类别如果标注质量过关mAP50 跑到 0.8 以上是合理预期。如果卡在 0.3 以下不动先别怀疑模型八成是标签或路径有问题。常见做法是拿训练完的模型在验证集上跑一次预测把预测框画出来和原图对比肉眼一看就知道是漏标还是错标。yolo detect predict modelruns/detect/train/weights/best.pt sourcevalid/images saveTrue这条命令会把验证集图像的预测结果存下来直接看可视化输出比盯数字直观得多。4. 避坑与排查五条血泪经验4.1 现象训练报「No labels found」原因图像目录和标签目录没对应上或者 data.yaml 里的路径指向了错误层级。YOLO 默认在 images 同级找 labels如果你的目录结构是train/images和train/labels它自己能推出来但如果标签放在别处就找不到。解决确认 images 和 labels 是同级目录且文件名一一对应。如果结构特殊在 data.yaml 里显式写清楚或者用脚本先做一次文件名匹配检查。4.2 现象类别全预测成同一类原因data.yaml 里 names 的顺序和标签里 class 索引的实际含义不一致。比如标签里 0 是 car但 names 第一个写成了 bus模型学出来的类别就整体错位。解决抽几个标签文件看 class 索引分布再对照 names 列表。必要时用脚本统计每个索引出现的次数确认四类都有样本且索引合理。4.3 现象mAP 一直很低loss 不降原因归一化坐标越界或者存在大量空标签文件。空标签意味着这张图没有目标但 YOLO 会把它当负样本少量可以大量会拖垮训练。解决扫一遍标签统计空文件数量和坐标越界数量。空文件过多就考虑剔除对应图像越界框要么修正要么删掉。4.4 现象显存爆了batch 调小还是报错原因imgsz 设太大或者用了大模型。1304 张图不算多但 640 以上分辨率配 yolov8l 这类大模型显存吃紧很正常。解决先把 imgsz 降到 416 或 320 跑通流程确认数据没问题后再往上调。模型先用 n 或 s 版本效果稳定了再换大的。4.5 现象验证集指标好实际预测一塌糊涂原因训练集和验证集划分不合理或者验证集图像和训练集高度相似导致指标虚高。解决检查划分是否随机。如果数据集本身场景单一考虑自己重新划分或者补充更多场景的图像。指标只是参考最终要看实际场景的预测效果。5. 进阶技巧用标签统计反查数据质量跑通训练只是第一步真正决定模型上限的是数据质量。我一般会在训练前做一次标签统计用几十行代码把每个类别的框数量、每张图的平均目标数、框的宽高分布都算出来。这一步能提前暴露很多问题某个类别样本极少、某些图目标密集到不合理、框的尺寸分布异常。import os from collections import Counter label_dir labels/train cls_counter Counter() box_per_img [] w_list, h_list [], [] for fn in os.listdir(label_dir): if not fn.endswith(.txt): continue with open(os.path.join(label_dir, fn)) as f: lines [l.strip() for l in f if l.strip()] box_per_img.append(len(lines)) for line in lines: parts line.split() cls_id int(parts[0]) w float(parts[3]) h float(parts[4]) cls_counter[cls_id] 1 w_list.append(w) h_list.append(h) print(类别分布:, dict(cls_counter)) print(平均每图目标数:, sum(box_per_img) / len(box_per_img)) print(最大单图目标数:, max(box_per_img)) print(框宽范围:, min(w_list), max(w_list)) print(框高范围:, min(h_list), max(h_list))这段脚本输出几个关键数字。类别分布能看出四类是否均衡如果某一类只有几十个框训练时这类基本学不好需要考虑补充数据或做类别加权。平均每图目标数反映场景密度车辆检测一般每图几个到十几个都正常如果平均几十个可能是标注过密或重复标注。框宽高范围能发现异常值正常归一化后应该在 0 到 1 之间出现接近 0 或超过 1 的就要查。我自己的习惯是每次拿到新数据集先跑一遍统计再抽十张图把标签画出来肉眼核对。画框用 OpenCV 几行就能搞定把归一化坐标还原成像素坐标在原图上画矩形。这一步花不了十分钟但能避免后面几小时的无用训练。从那以后我每次开训前都强制走一遍「统计加可视化」再也没出现过训到一半发现标签错位的情况。这份数据集的双格式标签和现成配置省掉了最枯燥的整理环节但数据质量最终还得自己把关。希望这份拆解能帮你少走几个弯路顺利把车辆检测模型跑起来。本文还有配套的精品资源点击获取