自动驾驶道路异常检测数据集:六类目标与YOLO11训练实战

📅 发布时间:2026/10/6 6:55:51
自动驾驶道路异常检测数据集:六类目标与YOLO11训练实战
简介面向自动驾驶场景道路异常检测的数据集配套说明文档以单个PDF文件形式提供大小5.08MB。文档完整介绍了包含8000张真实道路高质量图片的数据集情况图片来自丰富场景标注类别涵盖轻型机动车汽车、摩托车、小型卡车等、重型机动车公交车、卡车、拖拉机等、道路损坏坑洼、裂缝、井盖等、未铺面道路、行人以及减速带六大类并采用LabelImg工具进行精细标注。数据提供VOC、COCO、YOLO三种常见目标检测格式标签可直接衔接YOLO系列等算法训练流程同时附赠YOLO11一键训练脚本和博主训练日志帮助用户快速复现训练并评估效果。文档内还说明了百度网盘的数据获取方式适合自动驾驶研究者、算法工程师及目标检测初学者作为数据集补充和迭代参考。目前已有203人浏览学习。1. 自动驾驶道路异常检测8000张图、六类目标、三种格式能做什么自动驾驶场景下的目标检测大多数人首先想到的是车辆、行人、红绿灯这类常规目标。真正进入道路实测才会发现坑洼、裂缝、减速带这些不速之客才是让感知模型翻车的高危因素。这套数据集把方向切在“道路异常”这个分支上8000张真实道路图片覆盖轻型机动车、重型机动车、道路损坏、未铺装道路、行人、减速带六个类别每张图都提供VOC/COCO/YOLO三种格式的标注文件还附了一个YOLO11一键训练脚本和博主自己的训练日志。对正在做自动驾驶道路异常检测项目的工程师它解决的是“怎么在路面上提前发现异常结构”的问题对刚接触YOLO的开发者它又是一套可以直接跑通的完整训练闭环。资源本体是一份PDF说明文档文档内写明数据集全貌与百度网盘链接提取码6666先看目录再决定下载不会白跑一趟。下面把类别语义、标签格式、训练配置和实战踩坑逐项拆开。2. 六类目标的语义边界训练前先把类别定义和分布吃透2.1 车辆分组逻辑LMVs与HMVs为什么不能合并数据集把车辆拆成LMVs和HMVs两组是特意做的。LMVs轻型机动车包括汽车、摩托车、小型卡车、小型货车体积小、纵向速度变化快、变道动作频繁决策模块对这类目标通常采用较短的安全距离和更灵活的轨迹预测。HMVs重型机动车则包括公交车、卡车、拖拉机、JCB挖掘机和厢式货车质量大、加速慢、制动距离长、侧向盲区明显跟车时机和制动策略都要更保守。两类合并成一个类别模型学出来的是平均特征无法为决策系统提供差异化的车辆类型信息。从标注一致性角度看合并也会引入噪声。小型卡车和小型货车的边界本身模糊街上的皮卡到底算小型卡车还是小型货车标注员缺少统一尺度时会产生大量主观偏移。LMVs/HMVs这种命名在自动驾驶行业里对应“轻型机动车/重型机动车”的标准分组后续对接V2X或车队管理平台时类别定义可以直接对上不用二次映射。我在第一次拿到数据时会单独把这两类的xml抽查20个确认边界框没有把小货车和面包车混进同一类再去定训练计划。训练配比上有个值得注意的点重型车图片大概率集中在多车道主路轻型车更常出现在城市支路和交叉口。如果部署场景以高速为主验证集里重型车占比至少要达到40%否则整体mAP再高部署后也会在重车密集路段出现明显漏检。这种配比调整不需要改标注只要在划分train/val时按场景目录分层抽样就行。2.2 道路损坏是“结构性目标”坑洼、裂缝、凸起与井盖的共性Road Damages这一大类底下包含坑洼、裂缝、凸起、井盖四种路面异常。它们的共同点是紧贴地面、颜色与沥青接近、尺寸偏小恰好是目标检测模型最不擅长的一组。常规车辆行人数据集里目标有明显的轮廓和占据面积坑洼和裂缝往往只有十几个像素宽经过YOLO骨干网络多次下采样之后小目标的特征在深层图上可能只剩一两个点。井盖是城市道路里特别有代表性的子类。它形态规则、反光明显但容易被路面的修补痕迹带偏。标注时如果只框圆形外边界模型会默认学习“井盖外沿”这个视觉概念训练图里混入被污渍覆盖的井盖后模型就会把圆形污渍或路标边缘误识别成井盖。标注边界框应该框住井盖金属结构的可见外沿而不是把周边柏油补丁包进去。坑洼和凸起是一对互补异常坑洼是负向凹陷靠阴影纹理识别凸起是正向隆起靠轮廓光影变化识别。模型要同时学会这两类特征样本量几乎是对称的。增量训练时优先补车头视角的近景路面损坏图因为透视形变会让近处纹理充满整个画面边界稳定性远高于远景训练出来的框更干净。2.3 未铺装道路与减速带常规数据集里最稀缺的两个类别未铺装道路这个类别在开源目标检测数据集中非常少见。语义分割通常把可行驶区域当作整体处理不会细分铺装与未铺装。但自动驾驶测试车进入乡村、矿区、施工路段时未铺装砂石路是典型未知场景。把它单独作为检测目标模型输出的就不只是“前方有物体”而是“当前路面条件异常”决策系统可以降速并切换底盘模式。未铺装道路没有清晰边界标注策略是框住整段可见路面的消失区域。这个框在特征层面代表“纹理从平滑沥青过渡到松散颗粒”的转折点所以如果把框只圈住局部小坑模型会觉得整条砂石路只是背景噪声训练效果直接打折。这里要接受一个事实框的边界必然比车辆行人框粗糙但类别维度是清晰的对规划决策已经够用。减速带与减速坎合并进Speed Bumps类别也是合理的归并。常规拱形橡胶减速带是连续凸起钢制减速坎是分段结构外形差异明显。归成一个类强制的学习方向是“前方存在强制减速障碍”的功能语义而不是某一个固定外观遇到非标准减速装置、比如工地铁板临时减速带时泛化表现会更好。2.4 行人与遮挡目标先做一次样本分布扫描再训练行人类别覆盖路边行人、过马路行人两种典型位置。与主流行人检测数据集相比这里的行人图往往不在画面中心而是位于边缘、被车辆遮挡或部分被护栏遮住的中小目标。自动驾驶决策最关心行人是否进入本车轨迹所以边缘位置和遮挡条件下的行人在测试时权重应该更高。训练时如果把行人和车辆放在相同损失权重里模型大概率会牺牲行人精度去保车辆类别。建议第一次训练先跑整体再单独拆出Pedestrians类别看mAP不要被整体数字掩盖。部署后如果出现某段连续图片里行人极小的情况指标掉得非常明显这在小目标检测任务里很常见。开工前我会写几行脚本扫一遍类别分布确认类别不均衡程度再决定是否调权重from collections import Counter label_dir labels/train class_counter Counter() for txt_name in os.listdir(label_dir): with open(os.path.join(label_dir, txt_name), r) as f: for line in f: cls_id int(line.strip().split()[0]) class_counter[cls_id] 1 print(类别ID分布:, dict(class_counter))这段代码的功能是把yolo格式txt里每行第一列的类别id统计成直方图。如果某个类别数量比最大类别低一个量级后面训练就要针对它做复制增强或类别加权。另外要说明白本数据集提供的是二维检测框不是三维目标检测那种带朝向角的立方体标注如果项目需要距离估算要在检测后单独接测距模块这个前提得在方案设计阶段就确定。类别子目标尺寸特征主要难点LMVs汽车、摩托车、小型卡车、小型货车中小目标摩托车易漏检HMVs公交车、卡车、拖拉机、JCB挖掘机、厢式货车大目标遮挡区域特征分割Road Damages坑洼、裂缝、凸起、井盖小目标与地面纹理混淆Unsurfaced Roads未铺装路面大目标边界不清晰Pedestrians路边行人、过马路行人中小目标遮挡与画面边缘Speed Bumps减速带、减速坎小目标形态跨度大3. VOC/COCO/YOLO三格式标签结构差异、读取代码与互转要点3.1 VOC的XML最直白却最啰嗦的存储方式用labelimg标注最先拿到的原始产物大概率是VOC的XML。每个图像对应一个xml文件记录filename、size和object列表object里有name、bndboxxmin、ymin、xmax、ymax有时带difficult、truncated等附加字段。解析XML不用什么技巧但要注意这里坐标是绝对像素值而YOLO训练统一要求归一化浮点数这个转换无论如何都绕不过去。一个典型的VOC xml文件长这样annotation folderJPEGImages/folder filenameframe_00123.jpg/filename size width1920/width height1080/height depth3/depth /size object nameLMVs/name difficult0/difficult bndbox xmin204/xmin ymin412/ymin xmax619/xmax ymax778/ymax /bndbox /object /annotation读取时我常用的解析函数如下import xml.etree.ElementTree as ET def parse_voc(xml_path): tree ET.parse(xml_path) root tree.getroot() filename root.findtext(filename) size root.find(size) img_w int(size.findtext(width)) img_h int(size.findtext(height)) objects [] for obj in root.findall(object): name obj.findtext(name).strip() if obj.findtext(difficult) 1: continue # 难例可跳过或单独处理 box obj.find(bndbox) xmin float(box.findtext(xmin)) ymin float(box.findtext(ymin)) xmax float(box.findtext(xmax)) ymax float(box.findtext(ymax)) objects.append({name: name, bbox: [xmin, ymin, xmax, ymax]}) return filename, img_w, img_h, objects这里有几个注意点图片resize之后xml里的坐标仍然基于原图尺寸转换时必须以原始width和height做分母difficult字段为1的难例如果直接丢进训练会干扰loss最好先统计数量再决定是否保留name的大小写必须与类别清单完全一致统一用strip再比对。解析结果先画到图上人工抽查比直接送入训练省力得多。3.2 COCO的JSON三层结构与image_id索引COCO格式不是一图一文件而是一个annotations.json把所有图片和标注串起来内部按images、annotations、categories三个数组组织。annotations里每条引用一个image_idbbox记录为x、y、width、heightcategory_id来自categories数组的id。这套结构向下兼容评估工具链像pycocotools的评测接口可以直接无缝使用。用Python读取时逻辑很直接import json def load_coco_annotations(json_path): with open(json_path, r, encodingutf-8) as f: coco json.load(f) categories {c[id]: c[name] for c in coco[categories]} image_index {img[id]: img for img in coco[images]} result [] for ann in coco[annotations]: img image_index[ann[image_id]] x, y, w, h ann[bbox] label categories[ann[category_id]] result.append({ file_name: img[file_name], label: label, bbox: [x, y, x w, y h] }) return result这段代码把COCO的x,y,w,h还原成左上右下两个点方便直接用OpenCV画框。关键要记住COCO的bbox是“左上角xy宽高”不是两个对角点。从VOC导出COCO时换算很简单wxmax-xminhymax-ymin但很多人转的时候把y和x的位置写反导致训练框整体偏移。转换后抽几类目标做可视化比反复看代码快得多。3.3 YOLO的TXT归一化坐标与class_id的顺序约定YOLO格式在数据集里是每张jpg对应一个同名txt每行五个数字类别id、中心点x、中心点y、宽w、高h全部归一化到0-1。优点是训练代码拿起txt就能拼batch不用额外做关联解析代价是归一化截断会引入坐标误差如果只保留五到六位小数1920x1080的图上单个框会偏移1到2像素对Road Damages这种小目标已经是实质性偏差。读取YOLO txt并还原成像素坐标的代码def read_yolo_txt(txt_path, img_w, img_h): boxes [] with open(txt_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, xc, yc, w, h map(float, parts) x1 (xc - w / 2) * img_w y1 (yc - h / 2) * img_h x2 (xc w / 2) * img_w y2 (yc h / 2) * img_h boxes.append((int(cls_id), x1, y1, x2, y2)) return boxes这段代码的关键点是归一化坐标乘分母。分母必须是原图的宽高不能是resize后的宽高如果图集里混有不同分辨率宽和高要分别取对应图片的原始值。类别id的映射顺序必须和训练yaml里的names完全一致比如yaml里names[0]是LMVstxt里第一列写0才会被正确解读。这种错位很隐蔽loss照降、mAP曲线照走只是推理结果全对不上。所以每次拿到新数据集我第一步都是把txt坐标还原画框人工抽查50张再进训练。3.4 三格式互转的最小实现从VOC到YOLO的完整脚本数据集本身三份标注齐全多数场景直接用就行。但真实项目里经常只拿到一种格式所以转换脚本还是要会写。下面这个最小实现把xml解析、归一化、写入txt一次做完import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, txt_path, class_list): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.findtext(width)) img_h int(size.findtext(height)) lines [] for obj in root.findall(object): name obj.findtext(name).strip() if name not in class_list: continue cls_id class_list.index(name) bndbox obj.find(bndbox) xmin float(bndbox.findtext(xmin)) ymin float(bndbox.findtext(ymin)) xmax float(bndbox.findtext(xmax)) ymax float(bndbox.findtext(ymax)) xmin max(0.0, min(xmin, img_w)) ymin max(0.0, min(ymin, img_h)) xmax max(0.0, min(xmax, img_w)) ymax max(0.0, min(ymax, img_h)) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) return len(lines)脚本里两个细节最值钱越界clip真实标注偶尔出现xmax超过图宽、ymax为负的情况不处理训练时会产生NaN loss归一化保留六位小数涉及中心点换算时误差能控制在1像素以内。class_list的顺序必须和训练yaml的names一致这是我会在换数据集时强制检查的第一项比任何参数调优都重要。4. YOLO11一键训练从环境准备到训练日志解读4.1 环境确认yolov11(ultralytics) 版本配套与依赖坑这套资源附带的YOLO11一键训练脚本基于ultralytics包内部模型名是yolo11n、yolo11s、yolo11m这一组。环境配置最常遇到的问题是torch版本不匹配ultralytics新版代码在torch 2.0下运行顺畅但torch 1.x下会缺少某些算子出现导入直接报错的情况。我一般固定建一个conda环境python 3.10、torch 2.0以上、ultralytics最新发布版避免被版本碎片时间干扰。还有一个藏在设备层面的坑Windows下数据路径带空格会导入失败中文目录名虽然能跑但偶尔触发编码报错。所有代码和数据集目录建议全部用英文命名路径里不要有空格和特殊符号。确认环境是否就绪最快的办法是跑一句yolo任务检查加v版本能正常输出版本号再进入下一步。4.2 数据集YAML路径、names与类别编号的对应关系YOLO训练第一步是写好数据yaml格式如下path: /home/user/road_abnormal_dataset train: images/train val: images/val nc: 6 names: 0: LMVs 1: HMVs 2: Road Damages 3: Unsurfaced Roads 4: Pedestrians 5: Speed Bumps这里最关键的是names顺序和YOLO格式txt里每行第一列的id一一对应。如果提供的训练脚本重新定义了类别顺序要在跑脚本前确认yaml里的names和标签id完全一致。train和val路径在yaml中是相对path字段的把yaml放到其他目录而数据集在另一个盘符时相对路径会失效改成绝对路径是最稳的。批量修改路径可以用一个很短的sed/shell命令sed -i s|path: .*|path: /data/road_abnormal|g road_abnormal.yaml这行命令把yaml里path替换成实际存放目录sed的原地修改比手工编辑快也不容易漏掉同一字段的多个出现位置。改完后用yolo data check或直接打开yaml确认解析正常再开始训练。4.3 训练命令与关键参数batch、imgsz、patience怎么定数据yaml就绪后训练命令本身很简短yolo detect train \ dataroad_abnormal.yaml \ modelyolo11n.pt \ epochs100 \ batch16 \ imgsz640 \ patience20 \ device0常用参数的选择逻辑如下表参数本次推荐值说明modelyolo11n.pt预训练权重起步可以用n精度最低但最快epochs100后续可加到150观察过拟合点batch168G显存降到824G上升到32imgsz640显存允许时试1280对小目标有明显收益patience20控制在15-30过小会提前截断掉点workers4Windows下不宜超过8device0单卡直接指定0这个数据集的特殊性在于Road Damages和Speed Bumps都是小目标。640的imgsz能提供可接受的基线有条件上1280的话小目标特征更完整但显存占用约翻三倍8G显存下batch只能降到4。我通常先跑640到一半把训练好的权重拿出来在1280的验证集上看一次再决定是否值得加一轮高分辨率训练。训练中断不想从头再来时用resumeTrue从最近一次checkpoint续跑。4.4 训练日志怎么读从loss曲线到类别mAP的判断顺序ultralytics训练日志里每轮输出epoch、训练各类loss、验证各类loss、precision、recall、mAP50和mAP50-95。读日志的判断顺序有三个先看val/mAP50是否单调上升此时震荡说明学习率可能过大再看train/box_loss与val/box_loss的差值如果训练损失继续降但验证损失不降就开始过拟合了最后拆出来单独看类别mAP因为整体mAP容易被大样本类别拉高。博主提供的训练结果日志是一个参考基线说明这个配置组合能正常收敛。实际跑的时候数据集随机划分导致的波动通常在2到3个mAP点以内不要拿日志里的具体数值当作自己的承诺指标。训练结束后别急着关终端ultralytics会把best.pt和last.pt存到runs/detect/train目录best.pt是验证集上表现最好的权重后续推理和部署都用它。保存训练日志的习惯我坚持了一年多每次换数据集都回头翻旧日志对照排查新配置的改动是否真正有效。5. 避坑指南道路异常检测训练里五个高频翻车点5.1 类别不均衡Speed Bumps的mAP只有其他类别一半现象训练日志里整体mAP50到0.85拆开看Speed Bumps类别mAP只有0.4甚至更低。整体指标好看单一类别一塌糊涂这种问题最坑人因为它不会在训练过程中产生任何警报。原因样本数量大小不均。车辆、行人这类目标在路面上频繁出现减速带和井盖的天然出现率低很多模型在多数batch里根本看不到足够多的减速带学习到的特征自然稀疏。解决先在训练前用统计脚本把每个类别的框数扫出来低于最大类别30%的需要处理。可以用复制粘贴增强把减速带目标随机贴到多张不含减速带的图上也可以单独提高该类别在损失函数里的权重。最直接的做法是调整train/val划分多分一些包含减速带的图到训练集验证集保持真实分布这样既不缺样本评估依然算数。5.2 VOC转YOLO后推理框整体偏移现象用自写脚本把VOC的xml转成YOLO格式txt训练完推理画框发现框整体向左上或右下偏移目标中心对不上框中心。原因转换脚本里的归一化分母用错了尺寸。常见错误是把图片resize后的宽高当成分母或者一组训练图有不同分辨率代码写死成单一尺寸。解决训练前先跑一遍可视化回放。写个小脚本把txt转回像素坐标用OpenCV画框抽查20张原图看框是否贴合目标。如果发现只有部分图偏几乎可以断定是分辨率混用导致。还有一个次要因素整数除法。坐标做除法时注意类型xmin等字段在XML里是整数直接除整型宽高在高版本Python里已经是浮点但中途混用int除法会出现精度丢失。从那以后我每次做格式转换都强制加一步可视化校验不再依赖代码自检。5.3 晴天训练的模型一到阴雨逆光就漏检现象模型在晴天的验证集上mAP达标拿到阴雨或逆光场景推理坑洼、裂缝的漏检率骤增轻型车也偶尔跟丢。原因数据集的整体光照分布偏向晴朗白天模型在训练时被大量高照度图片偏置了权重对暗部区域的特征响应不够。雨天积水反光会改变路面纹理坑洼和裂缝的颜色对比大幅衰减。解决靠数据增强补足。ultralytics的hsv_h、hsv_s、hsv_v参数可以控制色调饱和度亮度扰动适当提高hsv_v的范围值模拟不同曝光另外Mosaic和MixUp能组合出更多光照过渡的样本。如果项目允许最有效的数据是补一批真实阴雨图做微调20到50张就足以拉起模型对该场景的敏感度。部署侧也可以在预处理里做一次gamma校正实测对逆光图有稳定提升。5.4 训练到80轮后val指标掉头train_loss还在降现象train_loss一路向下val mAP跑到80轮前后开始回落学习曲线出现典型的“缝外翻”式分离也就是过拟合。原因8000张图相对于中小模型的容量并不算多小目标类别多模型容易先记住训练集的具体纹理而不是通用特征。训练轮次过长也会让数据增强的随机性失效。解决把patience参数从默认值调小到20左右训练在val不再提升时提前停止避免后段纯过拟合模型换成更小的yolo11n而不是yolo11x参数量小一些约束正则效果。另外可以冻结骨干层只训练检测头收敛速度快且对数据量要求低。跑过一个对照同样配置下冻结前三层骨干的版本比全量微调掉点少约1.5个mAP点。5.5 路面裂缝反复误检成Road Damages现象推理视频里沥青路面的正常裂缝被框成Road Damages而真正的危险宽度裂缝却漏掉。误检率一上去决策模块就不敢信任这个输出。原因裂缝与沥青纹理在局部特征上高度相似数据集标注里裂缝框的边界标准如果各标注员不一致正样本信号就会互相打架。模型学出来的边界既不拒绝纹理也抓不住明显的宽裂缝。解决第一步统一标注规则框住裂缝的可见破损范围不框整块路面。第二步给训练集加入明显的负样本也就是正常无病害路面的图不标任何框让模型知道“光滑路面不是目标”。第三步把推理时的conf阈值从0.25提到0.4误报量会明显下降但要注意同时观察漏检率。这种误检问题不完全靠模型参数解决标注口径的收敛反而贡献更大。6. 把权重落到部署环ONNX导出、边界测试与固定动作训练日志里mAP达标只算完成一半。我会把best.pt导出成ONNX先在推理框架上验证一次再拿边界场景图集做人工统计。导出命令是yolo export modelbest.pt formatonnx opset12 imgsz640导出后用ONNX Runtime加载和PyTorch端输入同一张图对比输出张量。两端的输出数值允许有微小浮点误差但框坐标不应该有超过1到2像素的结构性差异。如果差异过大先查导入时是否做了相同的图像预处理归一化参数和letterbox尺寸只要差一点结果就差很多。验证环节我自留了二十张“不友好”图夜晚路口的坑洼、雨后反光的减速带、雪天被覆盖后只剩轮廓的井盖、刚铺砂石路的明暗分界。每次训练完拿这套图跑一遍推理记录漏检和误检数量设定能接受的误报上限。整体mAP只是整体倾向边界case的表现不体现在数字里只能靠人工看。跑完这三个动作我才会把模型交到部署工程师手上。这段经验来自一次教训一套模型在验证集上mAP快到0.9交付后逻辑视频里连续误报井盖调查两天发现是训练集里井盖标注把一整块柏油补丁框进去了。从那以后我每次训练完都强制走三遍流程——第一看类别mAP而不是整体第二导出ONNX做一次推演对比第三拿极端光照图做人工统计。这三个固定动作做完模型在真路上的表现才有基本保障。希望帮到你。本文还有配套的精品资源点击获取