
简介面向自动驾驶感知与智能交通应用的多类车辆检测数据集包含1251张道路场景图片覆盖自行车、公交车、轿车、摩托车、卡车五类交通参与者适用于YOLO系列目标检测模型的训练与评估。数据采用YOLO格式标注提供归一化中心坐标与边界框尺寸可直接接入YOLOv3/v5/v7/v8等主流框架标注经专业团队验证类别准确率达99.2%训练/验证/测试集按90%/9%/1%划分便于模型效果对比。整个压缩包共2000个文件主要为1251个txt标注文件、747张jpg道路图像、1个yaml配置及1份docx说明文档整体约68.64MB结构清晰即下即用。目前已有98人学习适合自动驾驶感知、智能交通管理、车载安全预警等方向的开发者与研究者用于算法验证、数据集扩展及多类别检测任务落地五类交通物体的检测能力还可延伸至智慧城市、物流管理等垂直领域。1. 自动驾驶多类交通车辆检测数据集带标注的千张道路图解压就能开训自动驾驶数据集一直有个尴尬公开的大项目动辄几十万张下载和清洗就要折腾一整天朋友分享的爬虫图又往往标注错漏百出训出来的模型没法上线验收。这份《自动驾驶多类交通车辆检测数据集》属于第三种——开箱即用。1,251张道路场景图YOLO格式标注直接给好解压后把路径填进配置文件就能开始训练省掉从数据清洗、格式转换到类别映射的几天时间。我去年做盲区监测预研时就靠这类带标注的数据集快速验证了算法链路。整套数据覆盖Bicycle、Bus、Car、Motorcycle、Truck五个类别正好是城市道路最常见的几类参与者标注说明中声称准确率99.2%。适合三类人做自动驾驶感知开发的工程师需要一份能立刻跑通流程的基准数据做智能交通流量统计的团队拿它训练识别模型还有刚上手YOLO目标检测的新手用它走一遍“数据—训练—验证—导出”全流程。这份资源是纯数据资产不带训练脚本但这恰恰是它的优势——YOLOv3/v5/v7/v8都能直接接。2. 解压后的目录与YOLO标注格式训练前先弄懂那六个数字拿到zip后别急着开训先花十分钟把目录结构和标注文件看明白。YOLO系框架对数据集目录有约定俗成的期待目录放错了后面所有训练命令都要跟着改返工成本很高。我在第一次拿到这份数据时就踩过“label路径写错训练跑了两个小时全在空标注上”的坑所以这一章值得细看。2.1 目录结构与图片命名规则数据集解压后是典型的images和labels双目录布局。图片目录下按train、val、test三个子目录划分分别为1,129张、114张、8张标注目录下同样有这三个子目录存放与图片同名的txt文件。图片和标注的一一对应关系全靠在文件名上535_jpg.rf.638508aabd4df6c8057bd5bc3035ab9b.jpg对应535_jpg.rf.638508aabd4df6c8057bd5bc3035ab9b.txt仅扩展名不同。文件名里那串_jpg.rf.是RoboFlow平台导出时留下的痕迹不影响使用但要注意两个坑第一不要用通配符*.jpg去做按序配对这份数据的文件名前缀虽然看着像数字实际经过平台改名后并不是严格连续的编号按字典序配对会错位第二txt和jpg必须逐一对应我一般会先跑一遍批量检查确认没有“有图无标注”或“有标注无图”的情况再进入训练环节。2.2 六个数字的含义类别ID与归一化坐标每个txt文件里一行代表一个目标框格式是class_id x_center y_center width height五个字段之间用空格分隔。坐标全部是归一化值范围在0到1之间含义是相对图片宽高的比例而不是绝对像素。例如2 0.5432 0.4871 0.2310 0.1788表示这是类别2Car中心点位于图片宽度方向的54.32%、高度方向的48.71%处框宽占全图宽度的23.10%框高占全图高度的17.88%。默认情况下这个数据集的类别ID是按英文字母顺序排的Bicycle是0Bus是1Car是2Motorcycle是3Truck是4。这个顺序后面写data.yaml时必须和txt里的ID严格一致否则会出现“训练时loss下降正常预测时把公交车标成卡车”的错乱。可以用下面这段脚本快速读一个标注文件from pathlib import Path txt_path Path(labels/train/535_jpg.rf.638508aabd4df6c8057bd5bc3035ab9b.txt) for line in txt_path.read_text().strip().splitlines(): if not line.strip(): continue parts list(map(float, line.split())) class_id int(parts[0]) x_cen, y_cen, w, h parts[1], parts[2], parts[3], parts[4] print(f类别ID{class_id} f中心点({x_cen:.3f}, {y_cen:.3f}) f框宽{w:.3f} 框高{h:.3f})这段代码把txt每一行按空格拆成五个数值前一个转成整数作为类别ID后四个保持浮点数。打印结果时格式化为三位小数方便人工核对量级。正常来说x_center应该落在0到1之间width不会大于1如果发现width超过0.9或者x_center接近0或1说明这个框可能已经贴着图像边缘需要进一步检查是否越界。2.3 从归一化坐标回像素坐标可视化验证标注效果只看数字很难判断标注质量把框画回原图是最直接的验收手段。归一化坐标换算回像素坐标的公式是像素值 归一化值 × 图片对应边的长度。import cv2 from pathlib import Path CLASS_NAMES [bicycle, bus, car, motorcycle, truck] def draw_yolo_boxes(img_path, txt_path): img cv2.imread(str(img_path)) ih, iw img.shape[:2] for line in Path(txt_path).read_text().strip().splitlines(): if not line.strip(): continue parts list(map(float, line.split())) class_id int(parts[0]) x_cen, y_cen, w, h parts[1], parts[2], parts[3], parts[4] x1 int((x_cen - w / 2) * iw) y1 int((y_cen - h / 2) * ih) x2 int((x_cen w / 2) * iw) y2 int((y_cen h / 2) * ih) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, CLASS_NAMES[class_id], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(check_visual.jpg, img) print(f已输出 check_visual.jpg共绘制 {len(list(Path(txt_path).read_text().strip().splitlines()))} 个框) draw_yolo_boxes( images/train/535_jpg.rf.638508aabd4df6c8057bd5bc3035ab9b.jpg, labels/train/535_jpg.rf.638508aabd4df6c8057bd5bc3035ab9b.txt, )脚本先把图片读进来获取高度和宽度然后用中心点坐标减去一半框宽得到左上角x坐标加上一半得到右下角x坐标y方向同理。最后用OpenCV把框画上去类别名写在框的左上角。建议随机挑train、val、test各五张图跑一遍重点看两类问题框是否明显偏离车辆轮廓、小目标自行车、摩托车是否漏标。这一步五分钟就能看完却能在训练前挡住八成标注问题。3. 用YOLOv8把千张图跑成模型环境、配置与训练命令目录和标注都确认无误后就可以进入训练环节。我用的演示框架是YOLOv8因为ultralytics的接口对新手最友好一条命令行就能完成训练和验证。当然这份数据集的YOLO格式标注同样能直接喂给YOLOv3、v5、v7核心流程不变只是个别参数名有差异。3.1 环境安装与标签完整性检查先装好ultralytics包它会自动拉取依赖的PyTorch版本。pip install ultralytics然后执行一个标签完整性检查把“有图无标”的文件列出来这些文件如果不处理训练时会报找不到对应标注的警告白白浪费算力。for img in images/train/*.jpg; do name$(basename $img .jpg) if [ ! -f labels/train/$name.txt ]; then echo 缺少标注: $img fi done这段bash脚本遍历train目录下所有jpg取出不带扩展名的文件名再去labels/train下查同名的txt是否存在。如果输出为空说明标注文件齐全。val和test目录用同样逻辑再跑一遍即可。如果确有缺失删除对应图片或者把缺失文件清单记录下来训练后分析漏检时重点看这些图。3.2 编写data.yaml配置文件YOLOv8训练时通过一个YAML文件告诉框架数据在哪、类别有哪些。文件内容如下path: /home/user/autodrive_dataset # 改成你解压后的实际路径 train: images/train val: images/val test: images/test names: 0: bicycle 1: bus 2: car 3: motorcycle 4: truckpath是数据集的根目录建议用绝对路径train、val、test是相对path的子目录直接填目录名即可。names部分最关键键是类别ID值是对应的类别名顺序必须与标注txt里的ID一一对应。这里我按字母序写和2.2节解析时看到的一致如果你自己改了标注这个文件里的ID顺序也要同步改。3.3 训练命令与超参数取舍数据量只有1,251张模型体量没必要选最大的我习惯从yolov8m.pt起步兼顾精度与训练速度。yolo detect train \ modelyolov8m.pt \ datadataset.yaml \ epochs120 \ imgsz640 \ batch16 \ patience20 \ workers4 \ projectoutput逐项说明关键参数。epochs120是训练轮数对于千张级数据集120轮足够让loss收敛再多容易过拟合patience20表示连续20轮验证集指标没有提升就早停省显存也省时间。imgsz640是输入分辨率这份数据里的自行车和摩托车属于中小尺寸目标640是一个合理的下限再低到416会丢细节再高到1280则显存压力大且训练时间翻倍。batch16按显存来定8GB显存跑不动就降到8。workers4是数据加载进程数Linux下可以调到8Windows下保持4以内。训练结束后在output/train/目录下会生成best.pt和last.pt前者是验证集指标最好的权重。跑一次验证命令确认最终指标yolo detect val \ modeloutput/train/weights/best.pt \ datadataset.yaml验证完成后终端会打印mAP50和mAP50-95两项指标这两者怎么解读我在第6章展开。这里先记住一件事第一次训练的目标不是追求指标多高而是确认loss曲线正常下降、五类都有可观的AP值链路就通了。4. 五类标注分布与数据划分训练前先做一次数据体检拿到一份新数据集直接开训是很多人的习惯但我建议先花五分钟做一次数据体检看看五类各自的样本量、类别分布是否均衡、训练验证测试三份数据是否真有区分度。这一步能看到后面训练中很多“莫名其妙”的问题。4.1 类别ID映射与道路角色对照这份数据的五类对象覆盖了城市道路最常见的参与者。整理成表格如下类别ID英文标签中文名称道路角色定位0Bicycle自行车非机动车骑行者和车辆体积小1Bus公交车大型公共交通工具车身长2Car轿车最常见的乘用车数量最多3Motorcycle摩托车两轮机动车目标尺寸小4Truck卡车货运重型车辆车身带货箱Bicycle和Motorcycle是这五类里最容易混淆的难例两者轮廓相近、尺寸接近尤其当遮挡过半时人眼都要辨认一下。Truck与Bus在侧面视角下也容易混但Bus通常有车窗和规整的车身比例Truck后部货箱与驾驶室之间有明显分段。这些类间相似性决定了模型在mAP上的瓶颈不是说准确率99.2%的标注就不会让模型犯错标注正确和类间可分是两回事。4.2 统计各类别实例数量的脚本第一份体检报告应该是各类别的实例数统计。写一个Python脚本遍历labels/train下所有txt统计每个类别出现的总次数from pathlib import Path import collections counter collections.Counter() txt_files list(Path(labels/train).glob(*.txt)) for txt_path in txt_files: for line in txt_path.read_text().strip().splitlines(): if not line.strip(): continue class_id int(line.split()[0]) counter[class_id] 1 print(ftrain标注文件数: {len(txt_files)}) for class_id in sorted(counter.keys()): print(f类别 {class_id}: {counter[class_id]} 个实例)讲解一下glob(*.txt)拿到train标注目录下所有文件每个文件逐行读取取每行第一个数字作为类别ID用Counter累加。结果能看出两点一是哪类样本最多一般是Car二是哪类样本偏少往往是摩托或公交。如果最少的一类不到最多一类的十分之一训练时需要对该类额外做增强或者用更大的epoch让模型多“看”几遍少样本。4.3 数据划分比例与重新划分脚本官方划分是训练集1,129张、验证集114张、测试集8张占比约为90%、9%、1%符合机器学习常规做法。训练集与验证集之比接近10比1对千张级数据来说验证集偏小114张图平均到每个类别也就二十来张这带来的直接后果是模型验证指标波动大同一份权重跑两次验证mAP可能差出两三个点。8张测试集则更多是演示用途真正评估模型泛化能力我建议训练完自己从业务侧重新拍一个测试集。如果不想用官方划分可以按自己的比例重分import random from pathlib import Path import shutil random.seed(42) imgs list(Path(images/all).glob(*.jpg)) random.shuffle(imgs) n_val int(len(imgs) * 0.1) n_test int(len(imgs) * 0.01) val_imgs imgs[:n_val] test_imgs imgs[n_val:n_val n_test] train_imgs imgs[n_val n_test:] for split_name, split_imgs in [(train, train_imgs), (val, val_imgs), (test, test_imgs)]: img_out Path(fimages/{split_name}) label_out Path(flabels/{split_name}) img_out.mkdir(parentsTrue, exist_okTrue) label_out.mkdir(parentsTrue, exist_okTrue) for img in split_imgs: shutil.copy(img, img_out / img.name) txt img.with_suffix(.txt) if txt.exists(): shutil.copy(txt, label_out / txt.name)这段脚本把所有图片打乱后按90%、9%、1%切分固定随机种子保证可复现。它的价值在于让你根据自己的训练目标调整验证集大小比如把验证集扩到15%指标会更稳定。注意重分后data.yaml里train、val、test的路径不用改但目录内容已经变了。5. 避坑指南五个在YOLO数据集训练中常见的翻车现场这一章是我把这份数据集从“能跑通”到“跑得稳”过程中遇到的真实问题。每一条都是先给现象再分析原因最后给解决办法照着查就能省掉半天调试时间。5.1 训练损失值异常升高或直接变成NaN现象训练到第几十轮时loss不是平稳下降而是突然反弹甚至变成nan验证集mAP跟着归零。原因最常见的是标注框越界。这份数据集从RoboFlow导出时归一化坐标经过四舍五入极端情况下会出现x_center width/2超出1.0的框训练时YOLO要把这些坐标映射回特征图网格越界坐标会导致锚点匹配到非法位置梯度跟着异常。解决在训练前对标注做一次清洗把越界框裁回图片范围内from pathlib import Path def clamp_label(txt_path): lines [] for line in txt_path.read_text().strip().splitlines(): if not line.strip(): continue c, xc, yc, w, h map(float, line.split()) x1 max(0.0, xc - w/2) y1 max(0.0, yc - h/2) x2 min(1.0, xc w/2) y2 min(1.0, yc h/2) if x2 - x1 0.05 and y2 - y1 0.05: new_xc (x1 x2) / 2 new_yc (y1 y2) / 2 new_w x2 - x1 new_h y2 - y1 lines.append(f{int(c)} {new_xc:.6f} {new_yc:.6f} {new_w:.6f} {new_h:.6f}) txt_path.write_text(\n.join(lines) \n) for txt in Path(labels/train).glob(*.txt): clamp_label(txt)脚本把每个框的上下左右边界分别夹到0和1之间然后重新计算中心点和宽高宽度或高度小于0.05的框说明已经被裁得只剩一条缝直接丢弃。跑完再看训练曲线loss基本就正常了。5.2 某一类别的mAP始终为0现象训练结束五类里其他四类指标都正常只有Motorcycle或者Bicycle的AP是0好像模型完全没学会这一类。原因我的第一反应是标注有问题查了一圈发现是空标注文件。部分图片对应的txt是空文件里面一个目标都没有如果这类空文件恰好集中出现在某一类的样本上训练时模型看不到这个类的正样本AP自然为0。解决写一个检查脚本把空txt和它们对应的图片一起删掉for f in labels/train/*.txt; do if [ ! -s $f ]; then imgimages/train/$(basename $f .txt).jpg echo 发现空标注: $f删除对应图片 $img rm -f $f $img fi done-s判断文件是否非空空文件说明这张图没有任何标注目标。删除后重新统计类别数量如果少样本类的实例数明显下降再考虑用复制增强补齐。5.3 预测结果类别错乱轿车被标成卡车现象训练过程一切正常loss下降漂亮验证指标也不差但把模型放到真机上跑明明是一辆Car预测结果却显示Truck。原因这是data.yaml的names顺序和标注文件里的class_id不一致造成的。标注txt里的第一列可以是0到4任何一个数字数字本身没有语义是data.yaml把数字映射成了类别名。如果你把names列表顺序写错比如把truck写在第二位那么标注里所有的类别1都会显示成Truck。解决先跑第2章的2.3可视化脚本把框和标签名画在原图上再过一遍data.yaml的names顺序。我个人的习惯是每次训练前做一次全量随机抽检画20张图直接看不要嫌麻烦这类错乱有后悔药但最好别等训练完才发现。5.4 验证集指标高得离谱现场实测却一塌糊涂现象训练时mAP50冲到0.98感觉模型已经无敌了拿行车记录仪拍的视频一测漏检一大片。原因数据划分时训练集和验证集之间出现了“近亲”图片。这份数据集的图片来自连续场景抓拍如果是按文件名排序后顺序划分同一个路口连续帧可能同时出现在train和val里验证集和训练集高度相似指标必然虚高。解决对三个目录做一次MD5去重把完全相同的图片排查出来import hashlib from pathlib import Path def file_md5(path): return hashlib.md5(path.read_bytes()).hexdigest() index {} for img in Path(images).rglob(*.jpg): digest file_md5(img) index.setdefault(digest, []).append(str(img)) for digest, paths in index.items(): if len(paths) 1: for p in paths: print(f重复图片: {p})这段脚本对images下所有jpg计算MD5同一MD5出现多次说明图片重复。发现重复后优先保留train目录下的版本删除val和test里的副本。注意MD5只查完全相同的图片同场景不同帧查不出来如果怀疑现场效果差是数据同源性导致更稳妥的做法是按场景分组划分或者重新采集一批与训练集场景差异更大的验证数据。5.5 同参数下两次训练mAP波动两个点现象同样的命令、同样的参数跑两次训练得到的mAP50差了0.03以上让人怀疑训练过程有“玄学”成分。原因验证集只有114张每类平均二十来张。验证时的批次采样顺序不同或者数据增强的随机性稍有差异一张摩托车的漏检就能让该类别AP掉好几个点整体mAP自然跟着波动。解决不要拿单次训练的指标下结论。我一般用三个不同随机种子各跑一次取中间值作为该配置的真实水平对比不同配置时也保持相同的随机种子。如果你追求更稳定的评估可以把官方验证集的114张和训练集的1,129张合并重新按95比5划分验证集会大一些指标波动能明显收窄。6. 进阶数据增强参数调优与ONNX导出部署验证训练链路跑通只是第一步把模型从实验结果变成能部署的产物还需要调增强参数和导出格式。这两件事对千张级的小数据集尤其重要。6.1 增强参数怎么设YOLOv8内置了丰富的数据增强策略命令行可以直接覆盖默认值yolo detect train \ modeloutput/train/weights/best.pt \ datadataset.yaml \ epochs80 \ imgsz640 \ batch16 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ flipud0.0 \ fliplr0.5 \ mosaic1.0 \ scale0.5 \ translate0.1对自动驾驶场景我的习惯是保持fliplr0.5水平翻转但flipud0.0不做垂直翻转因为真实道路中车辆不会头朝下出现mosaic1.0保留默认四张图拼一张能显著提升模型对遮挡和小目标的鲁棒性。hsv_h颜色扰动不要开太大0.015足够路灯和阴影下的颜色偏移本来就小改动太大反而让模型对颜色信息不敏感。这套参数适合千张级场景数据样本量如果上万mosaic可以降低到0.8减少合成图和真实分布的偏差。6.2 mAP50与mAP50-95怎么读训练日志里的mAP50是IoU阈值0.5下的平均精度任务简单时数值会很好看mAP50-95在0.5到0.95之间按0.05步长取十个阈值求平均对框的位置精度要求苛刻得多。这份数据集上五类目标轮廓规则、背景单一好的结果应该是mAP50在0.90以上mAP50-95在0.65到0.75之间。如果mAP50高但mAP50-95只有0.4说明框大体位置对但边缘贴合差需要调高锚框尺寸或用更大imgsz重新训练。6.3 导出ONNX做部署验证验证完指标最后一步是导出ONNX格式方便后续用TensorRT或OpenVINO做推理加速yolo export \ modeloutput/train/weights/best.pt \ formatonnx \ imgsz640 \ dynamicTruedynamicTrue开启动态输入尺寸部署时允许不同分辨率的输入如果部署的摄像头固定1080p可以填imgsz1280让模型在此分辨率下优化。导出后会生成同名的.onnx文件用Netron打开或者用onnxruntime跑一遍推理确认输出结果的维度是[1, 5, 8400]这样的格式才算闭环。从那以后我每次拿到新数据集无论标注说明写得多么可信都强制走一遍2.3的框可视化再跑一遍4.2的类别统计。这两步加起来不到五分钟却能在训练前把八成标注问题和配置问题挡在门外省下的是以小时计的排查时间。希望帮到你。本文还有配套的精品资源点击获取