简介:针对道路坑洞检测场景的YOLO系列目标检测数据集,共1990张带标签图像,面向计算机视觉开发者、智能交通与道路养护领域研究者,可直接用于模型训练与验证。压缩包内包含2000个文件,其中txt标签580个、xml标签1420个,分别对应YOLO格式与VOC格式,并附带data.yaml配置文件及划分好的训练集、验证集,适配yolov5、yolov8、yolov7、yolov10、yolo11等主流框架,免去自行标注和格式转换的繁琐步骤。资源包大小166.52MB,结构清晰,标签与图像按对应关系组织,便于批量读取与调试。目前已有148人学习下载。对于缺少坑洞样本的算法落地项目,这份数据能显著降低数据采集与标注成本,帮助快速验证模型性能,推动道路巡检自动化。
1. 从一张 1990 张的坑洼图像集说起
路面坑洞检测是道路养护里最典型的小目标、高变体视觉任务。坑洼没有固定轮廓,光线、水渍、裂缝遮挡都让边界变得模糊,而巡检车和手持设备拍到的画面又常常伴随运动模糊和曝光不均。一个只带 1990 张图像和标签的压缩包,听起来规模不大,但用在 YOLO 系列模型上,恰好处于“从零训练不现实、直接微调又偏小”的中间地带。搞懂这个数据集的结构、标签格式和训练策略,比再攒三万张图更实际。
这套东西能解决什么?一是让 YOLOv5/v8 快速在道路场景上收敛出可用的检测器,二是给“小数据 + 强增强 + 预训练微调”这条管线一个完整的落地样板。适合谁?做智慧养护、巡检算法验证的工程师,以及刚把 YOLO 跑通、需要真实数据来调参的入门者。下面直接按“数据解剖 → 训练前处理 → 参数与排错 → 部署验证”的顺序拆开讲。
2. 解压后先别急着训练:搞清数据集目录和标签的真实格式
解压 ZIP 后第一件事不是打开图片看坑洼长什么样,而是用tree或find命令把整个目录结构打出来。很多道路检测数据集的压缩包会把图片和标注分两个文件夹存放,但 YOLO 训练器默认要求图片和同名 txt 标签放在同一个目录镜像下。如果你不先确认这一点,后面写data.yaml时路径全是错的。
2.1 用一条命令快速摸清压缩包的真实结构
unzip 道路坑洞检测数据集-1990张图像带标签-坑洼.zip -d pothole_data cd pothole_data find . -maxdepth 3 -type f | sed 's#[^/]*$##' | sort | uniq -c这段命令把压缩包解压到pothole_data,然后按目录层级统计文件数。sed部分只保留路径前缀,uniq -c就能看出哪一层放的是图片、哪一层放的是标签。常见布局有两种:images/与labels/平级,或者所有文件混在一起。如果是后者,你需要先做一次拆分,否则 YOLO 的train.txt和val.txt会把 txt 标注也当成图片路径。
2.2 标签内容决定了你要不要写转换脚本
打开任意一个标注文件,用cat或者head看一眼内容。YOLO 格式的标签每一行是“class x_center y_center width height”,数值已归一化到 0~1。如果看到的是多边形坐标、或者像 KITTI 那样的“类别 截断 遮挡 角度 bbox 尺寸”格式,就必须先做格式转换。
head -3 labels/000001.txt # 输出示例: # 0 0.5234 0.6211 0.1832 0.2417这里0代表类别索引,后面四个数分别是 bbox 中心 x、中心 y、宽、高。如果只有一类坑洼,类别索引就是 0。如果数据集把坑洼、裂缝、修补块都标了,就要看类别名映射文件。我一般会把classes.txt或obj.names打开和标签索引对一遍,防止出现“索引 1 在训练集表示裂缝、在验证集却表示坑洼”的错位。
2.3 图片分辨率和标注质量的快速体检
1990 张图看着不多,但分辨率差异可能很大。无人机拍的俯视图和行车记录仪拍的近景图,目标尺度完全不同。写个小脚本统计一下宽高分布:
python3 - <<'EOF' import os from PIL import Image imgs = os.listdir('images') ws, hs = [], [] for f in imgs[:200]: w, h = Image.open(os.path.join('images', f)).size ws.append(w); hs.append(h) print("avg:", sum(ws)//len(ws), sum(hs)//len(hs)) print("min:", min(ws), min(hs), "max:", max(ws), max(hs)) EOF这一步能直接决定训练时要不要开rect模式,以及锚框初始化需不需要重算。分辨率差异大的数据集,如果强行imgsz=640拉平,小目标的细节会丢得很厉害。
3. 训练前必须做的三步:数据集重组织、YOLO 配置和增强策略
数据本身没问题不等于能直接开训。YOLO 的训练器对数据集路径结构有固定预期,你在 Kaggle 或 Gitee 上拿到的压缩包往往不满足这个预期,重组织就是第一个绕不开的步骤。
3.1 把图片和标签改成 YOLO 标准布局
常见做法是在项目根目录下重新建一套文件夹结构:
mkdir -p pothole_yolo/images/{train,val} mkdir -p pothole_yolo/labels/{train,val} cp pothole_data/images/*.jpg pothole_yolo/images/train/ cp pothole_data/labels/*.txt pothole_yolo/labels/train/ # 按 9:1 或 8:2 分出验证集 python3 - <<'EOF' import random, os, shutil files = os.listdir('pothole_yolo/images/train') random.seed(42) random.shuffle(files) val = files[:int(len(files)*0.2)] for f in val: shutil.move(f'pothole_yolo/images/train/{f}', f'pothole_yolo/images/val/{f}') shutil.move(f'pothole_yolo/labels/train/{f[:-4]}.txt', f'pothole_yolo/labels/val/{f[:-4]}.txt') EOF注意验证集划分必须图片和标签同步移动,否则训练时Dataset会报“label 缺失”或“image 缺失”。如果原始标签文件和图片不是同名,这份代码会漏掉,建议先用diff检查两边文件名集合是否一致。
3.2 data.yaml 里最容易写错的三个字段
path: pothole_yolo train: images/train val: images/val nc: 1 names: ['pothole']第一处path要填相对于你执行训练命令位置的路径,不是绝对路径。第二处nc必须和标签里出现的最大索引 + 1 相等,如果标签里出现过索引 5,nc至少是 6,写 1 会在 loss 计算时直接崩掉。第三处是names列表的长度要和nc一致,名字本身随便起,但顺序必须和标签索引对应。
3.3 增强参数:小数据集的命脉
1990 张图上直接训 YOLOv8,不增强的话大概率过拟合。合理配置增强参数是这步的核心:
| 参数 | 推荐值 | 说明 |
|---|---|---|
hsv_h | 0.015 | 色调偏移不宜大,道路颜色变化有限 |
hsv_s | 0.5 | 饱和度增强可以缓解阴天和强光差异 |
fliplr | 0.5 | 水平翻转对坑洼有效,但不能开flipud |
mosaic | 1.0 | 默认开启,但小数据集建议降到 0.8 |
mixup | 0.2 | 对坑洼这种纹理型目标效果不稳定,谨慎开启 |
degrees | 5 | 巡检车拍摄有轻微旋转,5 度就够 |
注意翻转策略:坑洼在路面上的位置没有方向性,水平翻转安全;垂直翻转会让“天空”出现在路面区域,破坏场景语义,训出来的模型在真实道路上会误检路牌。
4. 用 YOLOv8 跑通训练:命令、损失曲线判读和三个高频报错
这个数据集叫“yolo 算法道路坑洞检测”,说明就是为 YOLO 系列准备的,用 YOLOv8 实测最稳。yolo命令行工具已经足够完成从训练到导出的全部流程,不需要写额外的 Python 脚本。
4.1 最小训练命令和显存预算
yolo train data=pothole.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 patience=10 project=runs/pothole name=exp1model=yolov8s.pt是关键的迁移学习设定,它会自动下载 COCO 预训练权重。batch=16在 640 分辨率下约需 12 GB 显存,如果你只有 8 GB 卡,改成batch=8或imgsz=512。patience=10是早停轮数,数据集小的时候 loss 容易震荡,早停阈值可以放宽到 15。
训练启动后注意看首屏输出的类别数和标签数。YOLO 会在数据集扫描阶段就计算每个类别的实例数量,如果发现某个类别只有几十个标注框,后续 mAP 大概率被这个类拉低。这时可以考虑把该类别从训练中剔除,或者用复制粘贴增强去补。
4.2 训练中怎么判断模型有没有在学
别只看box_loss绝对值,要看下降趋势。正常情况是前 20 轮 loss 快速下降,然后进入平台期。如果box_loss在 50 轮后反复波动不下降,说明学习率偏高,需要调低lr0到 0.001 或改用cos_lr=True做余弦退火。
另一个可靠信号是验证集上的mAP50和mAP50-95的差值。坑洼检测场景里,mAP50达到 0.7 以上但mAP50-95只有 0.3 多,说明框的大致位置对了但 IoU 精度不够,问题出在回归分支,可以增大iou阈值或检查标注框边缘是否贴得过紧。
4.3 三个实际训练中最常见的报错
第一个是AssertionError: train: Label class 1 missing from training。这个报错说明标签里有的类别没有出现在训练集划分中,而验证集里有。解决方法是把类别少的样本用脚本抽出来,人为分配到训练集,或者在data.yaml里缩减类别数。
第二个是CUDA out of memory。除了调小batch,更推荐开启fraction=0.7让 PyTorch 只使用 70% 显存,避免和数据加载器的缓存冲突。
第三个是No labels found in image folder。这往往是标签文件扩展名不是.txt,或者标签和图片文件名有隐藏空格。用ls -la看看文件列表,再用file命令确认标注文件的真实格式。
5. 训练完别急着部署:用混淆矩阵和剪枝手段榨干小数据集的剩余价值
1990 张图训出来的模型,直接上生产环境大概率会在陌生路面上翻车。最后一章不聊理论,聊点实际能落地的增强手段。
5.1 用混淆矩阵找系统性误检
训练结束后,yolo val会生成confusion_matrix.png。重点看“background”那一列。如果很多检测框落在背景类上,说明模型把路面裂缝、积水阴影当成了坑洼。这时候不是加数据,而是检查标注框是不是把裂缝也框进去了。道路场景里坑洼和裂缝常伴生,标注员的画框习惯会直接影响模型的决策边界。
5.2 用剪枝把模型压到能上嵌入式设备
yolov8s的参数量大约 11M,跑在 Jetson 或 RK3588 上还算宽裕,但如果要部署到更低功耗的设备,可以用torch.prune做通道剪枝:
import torch from ultralytics import YOLO model = YOLO("runs/pothole/exp1/weights/best.pt") for module in model.model.modules(): if hasattr(module, "conv") and hasattr(module.conv, "weight"): torch.prune.ln_structured(module.conv, name="weight", amount=0.2, dim=0) torch.save(model.ckpt, "pothole_pruned.pt")剪枝后必须重新训练几个 epoch,否则精度会掉到不可接受。
5.3 把模型导出为 ONNX 并检查推理输出
最后一步是导出验证,目的是确认整个链路从训练的模型格式到实际部署格式之间没有信息丢失:
yolo export model=runs/pothole/exp1/weights/best.pt format=onnx opset=12 half=True导出成功后,用onnxruntime或onnx2trt推理一张验证集图片,检查输出的坐标是否落在合理范围内。如果输出的置信度普遍低于 0.1,大概率是half=True在导出时精度损失过大,改成half=False重试。这一步做完,这套数据集才算真正从 zip 变成了可用的道路巡检检测能力。
本文还有配套的精品资源,点击获取