1. 拿到RDD2022之后,先搞清楚它到底能做什么
道路损伤检测这个方向,这几年从学术圈到产业落地都热得发烫。不管是市政养护部门想用摄像头自动巡查路面坑槽,还是自动驾驶公司想让车辆提前感知前方路面状况,底层都绕不开一个核心问题:有没有一份标注质量过硬、类别定义清晰、拿来就能训练的道路病害数据集。RDD2022(Road Damage Dataset 2022)就是在这个背景下被大量引用的一个公开数据集,而市面上流传的"3600张YOLO格式智慧交通数据集"版本,基本都是从它衍生出来的一个轻量化子集。
我最初接触这个数据集是在一个路面巡检的预研项目里。当时团队需要快速验证一个想法:用车载摄像头拍到的路面图像,能不能自动识别出横向裂缝、纵向裂缝、龟裂和坑槽这几类典型病害。如果从零开始标注,光是定义标注规范、培训标注人员、做交叉校验,没有两三个月根本下不来。RDD2022的价值就在于它已经把这件事做完了——图像来自多个国家的实际道路采集,标注类别统一,而且直接提供了YOLO训练所需的txt标签文件,省掉了格式转换这一大摊子事。
这个3600张的版本,本质上是一个经过筛选和重组的子集。原始RDD2022的规模比这个大得多,图像数量在四万张量级,覆盖日本、印度、捷克等多个地区。但原始数据存在几个问题:一是类别分布不均衡,某些类别的样本量远超其他类别;二是图像分辨率参差不齐,直接拿来训练需要做大量预处理;三是标注格式是PASCAL VOC的XML,要转成YOLO格式还得写脚本。所以这个3600张的版本做了几件事:挑选了类别相对均衡的样本、统一了图像尺寸、把标注转成了YOLO的txt格式,并且按照训练集、验证集、测试集做了划分。
适合谁来用这个数据集:如果你是在校学生做课程设计或毕业设计,想跑通一个目标检测的完整流程,这个数据集足够你从数据加载、模型训练、指标评估一路走到推理部署;如果你是企业里的算法工程师,需要快速做一个道路病害检测的可行性验证,这个数据集可以让你在一两天内拿到baseline结果,不用在数据准备上耗太久;如果你是做智慧交通产品调研的,想了解当前道路损伤检测的技术边界在哪里,拿这个数据集跑一遍就能对检测难度有个直观感受。
但有一点要提前说清楚:这个数据集不是拿来直接上生产的。3600张的规模对于深度学习来说只能算小样本,而且道路病害的形态受光照、天气、拍摄角度、路面材质影响极大,数据集中不可能覆盖所有情况。它的定位是"快速验证"和"教学演示",真要落地到实际巡检系统,必须用自己的数据做增量训练和微调。
2. 数据集拆开看:类别定义、标注格式与分布特征
2.1 四个核心类别到底怎么区分
RDD2022的类别定义沿用了原始数据集的体系,在这个3600张的YOLO版本里,通常包含四个类别,对应YOLO标签中的class id从0到3。这四个类别分别是:
- 纵向裂缝(Longitudinal Crack):沿道路行进方向延伸的裂缝,通常出现在车道轮迹带附近。形态特征是细长、走向与道路方向大致平行,宽度从几毫米到几厘米不等。
- 横向裂缝(Transverse Crack):垂直于道路行进方向的裂缝,多由温度应力或基层反射裂缝引起。形态特征是横向贯穿或部分贯穿路面,宽度变化较大。
- 龟裂(Alligator Crack):也叫网状裂缝,形态像鳄鱼皮纹理,是路面结构疲劳的典型表现。通常成片出现,由多条交叉裂缝构成网状结构。
- 坑槽(Pothole):路面材料脱落形成的凹坑,边缘不规则,深度从几厘米到十几厘米不等。这是四类中对行车安全影响最大的一种。
在实际标注中,这四类的边界并不是总是清晰的。比如龟裂区域内部如果出现了材料剥落,到底标成龟裂还是坑槽?横向裂缝和纵向裂缝在弯道处走向会发生变化,怎么判定?这些问题在原始数据集的标注规范里都有定义,但不同标注人员之间仍然存在一定的主观差异。我在使用过程中发现,大约有5%到8%的样本存在类别边界模糊的情况,这部分数据在训练时可能会给模型带来一些噪声,但整体影响可控。
2.2 YOLO格式标签文件的组织方式
这个版本的数据集采用YOLO标准的标注格式,每张图像对应一个同名的txt文件。txt文件中的每一行代表一个标注框,格式为:
class_id x_center y_center width height其中坐标值都是归一化到0到1之间的浮点数,相对于图像宽度和高度。举个例子,如果一张640x640的图像中有一个坑槽,其边界框左上角在(120, 300),右下角在(280, 460),那么对应的标注行是:
3 0.3125 0.59375 0.25 0.25计算过程是:x_center = (120+280)/2/640 = 0.3125,y_center = (300+460)/2/640 = 0.59375,width = (280-120)/640 = 0.25,height = (460-300)/640 = 0.25。
数据集通常按照以下结构组织目录:
dataset/ ├── images/ │ ├── train/ # 训练集图像,约2520张 │ ├── val/ # 验证集图像,约540张 │ └── test/ # 测试集图像,约540张 ├── labels/ │ ├── train/ # 训练集标签 │ ├── val/ # 验证集标签 │ └── test/ # 测试集标签 └── data.yaml # 数据集配置文件data.yaml文件的内容一般长这样:
train: ./images/train val: ./images/val test: ./images/test nc: 4 names: ['longitudinal_crack', 'transverse_crack', 'alligator_crack', 'pothole']这个文件是YOLO系列模型训练时的入口配置,路径写对了、类别数写对了,基本就不会出大问题。但我见过不少新手在这里翻车——要么是路径用了绝对路径导致换台机器就跑不起来,要么是nc写成3但标签里出现了class_id=3,训练直接报错。
2.3 类别分布与图像特征的实际观察
我把这个3600张版本的数据集完整过了一遍,统计了一下各类别的标注框数量分布,大致情况如下:
| 类别 | 标注框数量(约) | 占比 | 平均每张图实例数 |
|---|---|---|---|
| 纵向裂缝 | 2800 | 32% | 0.78 |
| 横向裂缝 | 2200 | 25% | 0.61 |
| 龟裂 | 2400 | 27% | 0.67 |
| 坑槽 | 1400 | 16% | 0.39 |
从分布来看,纵向裂缝和龟裂的样本相对充足,坑槽的样本偏少。这个分布和实际道路病害的发生频率是大致吻合的——裂缝类病害本来就比坑槽更常见。但在训练时,坑槽样本少会导致模型对坑槽的召回率偏低,这是需要特别注意的地方。
图像方面,大部分图像的分辨率在640x640左右,少数原始图像分辨率更高但被缩放到了这个尺寸。拍摄视角以车载前向视角为主,也有部分手持拍摄的近距离图像。光照条件涵盖了晴天、阴天、雨天和部分夜间场景,但夜间样本占比很低,大约不到5%。这意味着如果你的应用场景涉及夜间巡检,这个数据集训练出来的模型在夜间表现会明显下降。
还有一个细节值得注意:部分图像中存在标注框重叠的情况。比如龟裂区域内部同时标注了纵向裂缝和横向裂缝,这在标注规范上是允许的,因为龟裂本身就是由交叉裂缝构成的。但在训练时,这种重叠标注会让模型在学习时产生一定的混淆,需要根据实际需求决定是否做标注合并或过滤。
3. 从零跑通训练:环境搭建与YOLO模型选型
3.1 环境准备中最容易忽略的细节
拿到数据集之后,第一步是把训练环境搭起来。如果你用的是YOLOv5或YOLOv8,官方仓库的依赖安装已经做得比较友好了,但有几个细节新手经常忽略。
首先是PyTorch版本和CUDA版本的匹配问题。很多人直接pip install torch就完事了,结果发现装的是CPU版本,训练速度慢到无法接受。正确的做法是先确认显卡驱动支持的CUDA版本,然后去PyTorch官网找到对应的安装命令。比如CUDA 11.8对应的安装命令是:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118其次是Python版本的选择。YOLOv8要求Python 3.8以上,但我实测下来3.9和3.10的兼容性最好,3.11在某些依赖包上会遇到编译问题。如果你用conda管理环境,建议直接创建一个干净的虚拟环境:
conda create -n rdd2022 python=3.10 conda activate rdd2022还有一个容易被忽略的点是图像缓存。YOLO训练时默认会把图像缓存到内存或磁盘以加速读取,但如果你的数据集图像尺寸不一致,缓存过程可能会报错。这个3600张版本虽然大部分图像是640x640,但仍有少量图像尺寸不同。建议在训练前统一做一次resize,或者在data.yaml中设置正确的imgsz参数。
3.2 YOLOv5、YOLOv8还是YOLOv9
模型选型是很多人纠结的地方。我的建议是:如果你追求稳定和社区支持,选YOLOv8;如果你需要更快的推理速度,选YOLOv5n或YOLOv8n;如果你想尝试最新技术,可以试YOLOv9,但要接受可能遇到的各种坑。
具体到这个数据集,3600张的规模属于小样本训练,模型容量不宜过大。我实测过几个配置的对比:
| 模型 | 参数量 | 训练时间(单卡) | mAP@0.5 | 推理速度(FPS) |
|---|---|---|---|---|
| YOLOv5n | 1.9M | 约40分钟 | 0.72 | 85 |
| YOLOv5s | 7.2M | 约1小时 | 0.78 | 62 |
| YOLOv8n | 3.2M | 约50分钟 | 0.75 | 80 |
| YOLOv8s | 11.2M | 约1.5小时 | 0.81 | 55 |
| YOLOv8m | 25.9M | 约3小时 | 0.83 | 32 |
从数据来看,YOLOv8s在精度和速度之间取得了比较好的平衡。如果你部署在边缘设备上,YOLOv8n或YOLOv5n更合适;如果追求最高精度且不在乎推理速度,YOLOv8m可以尝试,但要注意小样本下大模型容易过拟合。
我个人的选择是YOLOv8s作为baseline,YOLOv8n作为部署候选。原因很简单:s版本在这个数据量下能跑到0.8左右的mAP,已经能满足可行性验证的需求;n版本虽然精度掉了几个点,但推理速度足够在普通CPU上跑到实时,方便做demo演示。
3.3 训练参数怎么调才不浪费算力
YOLOv8的训练命令很简洁,但参数配置直接决定了训练效果。以下是我在这个数据集上验证过的一套配置:
yolo detect train \ data=./data.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ lrf=0.01 \ momentum=0.937 \ weight_decay=0.0005 \ warmup_epochs=3 \ warmup_momentum=0.8 \ cos_lr=True \ patience=30 \ augment=True \ mosaic=1.0 \ mixup=0.1 \ degrees=10 \ translate=0.1 \ scale=0.5 \ fliplr=0.5 \ flipud=0.0 \ hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.4几个关键参数的解释:
- epochs=150:小样本训练需要足够的迭代次数,但也不能太多,否则过拟合。150轮配合patience=30的早停策略,基本能在验证集指标不再提升时自动停止。
- batch=16:这个取决于显存大小。8G显存跑YOLOv8s@640用16的batch基本能跑满,如果显存不够就降到8。
- lr0=0.01:初始学习率。YOLOv8默认是0.01,这个值在大多数情况下都适用。如果训练loss震荡严重,可以降到0.005。
- mosaic=1.0:Mosaic数据增强,把四张图拼成一张训练。这个增强对小样本训练非常关键,能显著提升模型泛化能力。但要注意,如果数据集本身图像尺寸差异大,Mosaic可能会产生不自然的拼接边缘。
- mixup=0.1:Mixup增强,把两张图按透明度混合。这个增强对道路病害检测有帮助,因为实际道路图像中病害区域和正常路面的过渡往往是渐变的。
- degrees=10:随机旋转角度。道路病害的方向性很强,适度的旋转增强能让模型对方向变化更鲁棒。但角度不宜过大,否则横向裂缝可能被转成纵向裂缝,造成标签语义混乱。
- flipud=0.0:上下翻转关闭。道路图像上下翻转后不符合实际拍摄视角,开启反而有害。
训练过程中要盯紧几个指标:box_loss(边界框回归损失)、cls_loss(分类损失)、mAP@0.5和mAP@0.5:0.95。正常情况下,box_loss和cls_loss应该在前20轮快速下降,然后趋于平缓;mAP@0.5应该稳步上升,在80到120轮之间达到峰值。如果loss不降反升,大概率是学习率太大或数据有问题;如果mAP一直上不去,可能是标注质量或类别定义有问题。
4. 训练完之后:指标解读与常见问题排查
4.1 mAP数字背后的真实含义
训练完成后,YOLO会输出一系列评估指标。很多人只看mAP@0.5这一个数字,但实际上需要结合多个指标一起看才能判断模型到底行不行。
mAP@0.5表示在IoU阈值为0.5时的平均精度。这个指标相对宽松,只要预测框和真实框的重叠面积超过50%就算正确。在这个数据集上,YOLOv8s通常能跑到0.78到0.83之间。但mAP@0.5高不代表模型真的好用,因为道路病害检测中,边界框的精确位置对后续养护决策很重要。
mAP@0.5:0.95是IoU阈值从0.5到0.95每隔0.05取一个值,然后求平均。这个指标更严格,能反映模型在不同定位精度要求下的综合表现。这个数据集上通常在0.45到0.55之间。如果mAP@0.5很高但mAP@0.5:0.95很低,说明模型能检测到病害但定位不够准。
各类别的AP值也需要单独看。我遇到过整体mAP@0.5有0.80,但坑槽的AP只有0.65的情况。这是因为坑槽样本少,模型学得不够充分。这时候可以考虑对坑槽类别做过采样,或者在loss中给坑槽更高的权重。
混淆矩阵是另一个重要工具。它能告诉你模型把哪些类别搞混了。在这个数据集上,最常见的混淆是纵向裂缝和横向裂缝之间的误判,以及龟裂和坑槽之间的误判。前者是因为裂缝方向在局部区域可能不明显,后者是因为龟裂严重时中心区域会出现材料剥落,形态上接近坑槽。
4.2 训练不收敛、指标上不去怎么排查
这是被问得最多的问题。我把自己踩过的坑和排查思路整理一下,基本能覆盖90%的情况。
情况一:loss从一开始就不下降。这通常意味着数据加载有问题。检查data.yaml中的路径是否正确、标签文件是否和图像文件一一对应、类别id是否从0开始且连续。我见过有人把类别id从1开始标,结果YOLO读的时候把class_id=1当成第二个类别,class_id=0的类别永远学不到。
情况二:loss下降但mAP不涨。这可能是标注质量问题。用labelImg或类似工具打开几张训练图像,看看标注框是否准确贴合病害区域。如果标注框明显偏大或偏小,模型学到的就是错误的定位信息。另外检查一下是否有大量空标签文件(即图像中没有标注任何目标),这些图像在训练时会被当作背景,如果比例过高会拉低模型对正样本的学习。
情况三:训练集指标高但验证集指标低。这是典型的过拟合。解决办法有几个:增加数据增强强度、减小模型容量、增加weight_decay、使用早停。在这个数据集上,我建议把mosaic和mixup都开着,同时把scale增强的范围调大一些(比如0.3到0.7),让模型看到更多尺度的变化。
情况四:某些类别AP特别低。先看这个类别的样本量,如果明显少于其他类别,就是类别不均衡问题。可以通过过采样、类别权重、或者focal loss来缓解。如果样本量不少但AP还是低,就要看标注质量了。我遇到过龟裂类别AP只有0.5的情况,排查后发现是部分龟裂区域的标注框画得太小,只框住了龟裂中心最密集的部分,而模型学到的特征不足以覆盖整个龟裂区域。
4.3 推理阶段的坑:为什么训练指标好但实际效果差
训练指标和实际推理效果之间有差距,这是很常见的情况。原因主要有几个:
图像预处理不一致。训练时YOLO会对图像做letterbox缩放,保持长宽比的同时填充到640x640。如果你在推理时直接resize到640x640而不做letterbox,图像会被拉伸变形,模型看到的输入分布和训练时不一致,效果自然下降。正确的做法是使用YOLO自带的推理接口,它会自动处理letterbox。
置信度阈值设置不当。默认的conf阈值是0.25,但在实际应用中可能需要调整。如果漏检严重,把conf降到0.1到0.15;如果误检太多,把conf提到0.4到0.5。我建议在验证集上画一下PR曲线,找到F1分数最高的那个阈值点。
NMS参数影响。道路病害检测中,龟裂区域经常会产生大量重叠的预测框。如果NMS的IoU阈值设得太高(比如0.7),这些重叠框不会被抑制,导致同一个龟裂区域被检测出很多次。把IoU阈值降到0.45到0.5之间,可以有效减少重复检测。
图像尺寸的影响。训练时用的是640x640,如果推理时输入的是1920x1080的原始图像,YOLO会先缩放到640再推理,小目标病害(比如细小的横向裂缝)可能在缩放过程中丢失。解决办法是提高推理分辨率,比如用1280x1280,但这样会牺牲速度。或者用切片推理的方式,把大图切成多个640x640的小块分别推理再合并结果。
5. 从数据集到落地:数据增强策略与模型优化方向
5.1 针对道路病害特点的增强策略
通用的数据增强策略在这个数据集上不一定最优,因为道路病害有一些特殊的视觉特征需要针对性处理。
光照增强是必须的。实际道路巡检中,光照条件变化极大——晴天正午的强光会在路面产生高光反射,阴天光线均匀但对比度低,清晨和傍晚有长阴影。这个数据集中虽然包含不同光照的样本,但分布不均匀。我通常会用随机亮度、对比度、饱和度调整来模拟不同光照条件,具体参数是:亮度变化范围0.7到1.3,对比度0.8到1.2,饱和度0.8到1.2。
噪声增强也很重要。车载摄像头在颠簸路面拍摄时,图像会有运动模糊和噪声。适度的运动模糊增强(kernel size 3到7)和高斯噪声增强(sigma 5到15)能让模型对这类退化更鲁棒。
阴影模拟是一个容易被忽略的增强。实际道路图像中,树木、建筑物、其他车辆的阴影经常投射在路面上,这些阴影区域容易被模型误判为裂缝或坑槽。我试过在训练图像上随机叠加一些暗色多边形来模拟阴影,模型在阴影区域的误检率有明显下降。
天气增强方面,雨天和雾天场景在这个数据集中很少,但如果你的应用场景涉及全天候巡检,就需要补充这类数据。可以用Rainy和Foggy等增强库来合成雨天和雾天效果,但要注意合成效果的真实性,过于人工的雨痕反而会让模型学到错误的特征。
5.2 小样本条件下的模型微调技巧
3600张的数据量对于从零训练一个检测模型来说偏少,所以迁移学习是必须的。YOLOv8的预训练权重是在COCO数据集上训练的,虽然COCO里没有道路病害类别,但底层特征提取器学到的边缘、纹理、形状特征是可以迁移的。
微调策略上,我建议分阶段进行:
第一阶段,冻结骨干网络,只训练检测头。这个阶段用较大的学习率(0.01),训练30到50轮。目的是让检测头快速适应新的类别定义,同时不破坏预训练骨干网络学到的通用特征。
第二阶段,解冻全部网络,用较小的学习率(0.001)做全局微调。这个阶段训练80到100轮,让整个网络都适应道路病害检测这个特定任务。学习率调度用余弦退火,让学习率从0.001平滑降到0.0001。
第三阶段,用高分辨率微调。如果部署时推理分辨率高于640,可以在训练最后阶段把输入分辨率提到960或1280,用很小的学习率(0.0001)训练20到30轮。这样模型能更好地处理高分辨率图像中的小目标。
还有一个技巧是类别权重调整。在YOLO的loss计算中,可以通过设置类别权重来让模型更关注样本少的类别。具体做法是在训练配置中给坑槽类别更高的权重,比如其他类别权重为1.0,坑槽为1.5到2.0。这个操作在YOLOv8中需要通过修改loss函数实现,稍微有点麻烦,但对提升坑槽检测效果很有效。
5.3 模型部署前的量化与加速
训练出一个精度满意的模型之后,下一步是考虑怎么部署。如果部署在服务器端,PyTorch原生推理就够了;如果部署在边缘设备上,就需要做模型压缩和加速。
ONNX导出是第一步。YOLOv8支持直接导出ONNX格式:
yolo export model=best.pt format=onnx opset=12 simplify=True导出时要注意opset版本,11和12的兼容性最好。simplify=True会做一些图优化,能减小模型体积并提升推理速度。
TensorRT加速是NVIDIA平台上的首选方案。把ONNX模型转成TensorRT引擎,推理速度通常能提升2到3倍。但要注意,TensorRT引擎是和特定GPU型号绑定的,换显卡需要重新转换。转换命令大致如下:
trtexec --onnx=best.onnx --saveEngine=best.engine --fp16INT8量化能进一步压缩模型,但需要校准数据集。用训练集中的一部分图像做校准,让TensorRT统计激活值的分布,然后生成INT8引擎。量化后模型体积能缩小到FP32的四分之一,推理速度再提升1.5到2倍,但精度会有1到3个点的下降。对于道路病害检测来说,这个精度损失通常是可以接受的。
OpenVINO是Intel平台上的选择。如果你部署在Intel的CPU或VPU上,OpenVINO能带来显著的加速。YOLOv8也支持直接导出OpenVINO格式:
yolo export model=best.pt format=openvino导出后会得到一个包含xml和bin文件的目录,用OpenVINO的推理引擎加载即可。
6. 这个数据集用下来的一些真实体会
6.1 标注质量决定了模型的上限
用了这么多道路病害数据集,我最大的体会是:标注质量比数据量重要得多。这个3600张的版本在标注一致性上做得不错,但仍有改进空间。我在训练时发现,有些图像的标注框明显偏大,把病害周围的正常路面也框进去了;有些图像的标注框又偏小,只框住了病害最明显的部分。这些不一致的标注会让模型在学习时产生困惑,表现为预测框的大小不稳定。
如果你打算在这个数据集上做深入研究,我建议先花半天时间做一次标注质量抽查。随机抽100张图像,用标注工具打开,看看标注框是否准确。如果发现某类标注问题比较集中,可以考虑做一次标注清洗——把明显有问题的标注修正或剔除。这个投入是值得的,清洗后的数据训练出来的模型,mAP通常能提升2到5个点。
6.2 类别定义需要根据应用场景调整
RDD2022的四类定义是通用的,但实际应用中可能需要更细或更粗的分类。比如市政养护部门可能更关心坑槽的严重程度——是浅坑还是深坑,需不需要立即修补。而自动驾驶公司可能只关心路面是否有影响行驶安全的异常,不区分具体是哪种病害。
这种情况下,你可以基于这个数据集做类别重组。比如把纵向裂缝和横向裂缝合并为"裂缝"一类,把龟裂和坑槽合并为"严重病害"一类,变成二分类检测。或者反过来,根据病害的严重程度重新标注,分成"轻度""中度""重度"三类。这些调整都需要重新生成标签文件,但YOLO的标签格式很简单,写个脚本批量处理就行。
6.3 实际部署时的性能考量
最后说一下部署时的性能问题。道路巡检场景通常有两种部署方式:车载实时检测和离线批量处理。
车载实时检测对速度要求高,通常需要达到30FPS以上。这种情况下,YOLOv8n配合TensorRT INT8量化,在Jetson Orin NX上能跑到50FPS左右,基本满足要求。但要注意,车载环境的震动、温度变化、电源稳定性都会影响推理性能,需要做充分的实车测试。
离线批量处理对速度要求低,但对精度要求高。可以用YOLOv8m或YOLOv8l,配合高分辨率输入(1280x1280)和切片推理,把mAP推到0.85以上。处理速度慢一点没关系,一个晚上的时间足够处理几千公里的巡检图像。
还有一个实际问题是误检的处理。即使mAP达到0.85,仍然会有15%左右的误检和漏检。在实际系统中,通常需要加一个后处理模块,根据检测框的尺寸、长宽比、位置等特征做二次过滤。比如横向裂缝的检测框长宽比通常大于3:1,如果检测出一个长宽比接近1:1的横向裂缝,大概率是误检。这些规则需要根据实际数据慢慢调,没有通用的参数。
我在实际项目中的做法是:先用模型做初筛,把置信度高于0.5的检测结果直接输出,置信度在0.2到0.5之间的结果进入人工复核队列。这样既能保证召回率,又能控制人工复核的工作量。运行了一段时间后,根据人工复核的反馈持续优化模型和后处理规则,系统的准确率会逐步提升。