坑洼检测这几年在道路养护圈子里讨论度很高。我之前做过一段时间道路病害识别方向的活儿,最深的感触是:数据比模型难搞。路面目标跟常规的目标检测完全不一样,坑洼没有固定形状、边界模糊、光照一变就认不出来,一套规范标注的数据集比调参金贵得多。最近刚好整理完这套带标注的路面坑洼大小识别数据集,模型训练出来的识别率能到92.6%,并且同时支持yolo、coco json、pascal voc xml三种主流训练格式,正好把从数据设计到训练落地的完整过程拆开讲讲,给正在做道路巡检、路面破损检测、自动驾驶感知的朋友一个参考。
这篇内容适合三类人看:一是算法工程师,想找一套拿来就能训的高质量路面数据;二是准备自建数据的团队,想搞明白标注规范怎么定,模型才能真正学会“坑洼大小”这个维度;三是刚入门目标检测的学习者,想找一个贴近真实场景、能直接用起来的项目练手。
1. 项目定位:这套数据集到底解决什么问题
1.1 先拆标题:四个关键信息
先把题目拆开看。“带标注的路面坑洼大小识别数据集”这句话里,其实包含四层信息:目标对象、任务形态、交付形态、性能指标。
目标对象是路面坑洼,而不是裂缝、车辙或者桥头跳车,聚焦在坑洼这类最常见的路面破损上。同时数据里也保留了井盖、树影、水渍、油污这类“非坑洼”干扰项,用来帮模型学会区分真假目标。任务形态是“检测+大小识别”,既要知道坑洼在哪里,又要判断它属于哪个尺寸等级。交付形态是带标注的数据集,标注不只是画框,还包含等级标签、遮挡标记、边界可见度说明。性能指标是92.6%的识别率,这是基线模型在对应测试集上的综合结果,具体怎么理解,后面会单独展开。
我在项目里用过不少坑洼检测相关的开源数据,大多数只标注“有没有坑”,没法回答“坑多大”。这个信息在养护场景里很关键:小坑可以纳入例行修补计划,中坑需要安排近期修复,大坑可能直接影响行车安全,必须尽快处理。如果算法只输出一个框,养护人员还要回到图像上再人工判一次等级,等于检测白做了一半。所以这套数据把“大小识别”作为核心任务设计,目的就是让模型输出直接对接到工单系统。
1.2 为什么把“大小”设计成模型类别
尺寸等级的判断有两种实现路径:一种是后处理,用检测框的宽高或对角线长度换算等级;另一种是把等级做成目标类别,让模型端到端学出来。这套数据选的是第二种。
后处理方案看起来简单,但实际操作会遇到一个很烦的问题:检测框的边缘天然有抖动。如果目标的真实尺寸刚好在分级边界附近,框宽几个像素的偏差,算出来的等级就会跳变。同一个坑洼,两次检测可能一次判成“中坑”、一次判成“大坑”,在业务系统里表现为同一位置一会儿中一会儿大,非常不稳定。而把等级设计成分类目标之后,模型学的是“这一类坑洼的整体视觉特征”,对框尺寸的微小抖动没这么敏感,判断稳定性会好很多。
代价是标注成本明显增加。标注员不仅要框准目标,还要正确判断等级,而且等级判断依赖拍摄高度和镜头参数,必须配套换算表。否则同一物理尺寸在不同图像里的像素尺寸不一致,标出来的等级就乱套了。这也是市面上同类数据稀缺的根本原因。
1.3 数据构成与场景覆盖
这套数据的图像来源覆盖了常见的道路场景:城市沥青路、县道、高速公路服务区、停车场、乡村水泥路。天气和光照也尽量拉开差异,晴天直射、阴天散射、雨后积水、路灯夜景、桥下阴影区都有覆盖。特别注意保留了带水渍和井盖的样本,这类东西最容易和坑洼混淆,留在数据里反而能提升模型的抗干扰能力。
采集设备不是单一相机,有车载运动相机、手机、巡检车上的定点相机,分辨率以1080p为主,也掺了一部分720p的老数据。因为拍摄角度和高度不统一,同一物理尺寸的坑洼在图像里的像素尺寸波动很大。之前看过一些数据集动辄标注上万张,但拍摄条件太单一,模型换个路段就不行了,所以场景多样性比总数重要得多。
尺寸等级分为三级:小坑、中坑、大坑。分级标准是通过标定板反推的物理尺寸,拍摄高度固定时,1080p画面下大约每像素对应0.2厘米,30厘米就是150像素,60厘米就是300像素。具体换算系数以数据包附带的说明文档为准,这里先把思路讲清楚:分辨率越高,小坑的像素区域越完整,训练时对小坑的召回也越好。
1.4 适合哪些落地场景
从实际项目经验来看,这类数据集直接对口的场景有三个。
第一个是道路日常巡检。巡检车或者巡检无人机沿路采集图像,后端模型自动识别坑洼并按大小分类,系统直接生成修复工单,小坑合并派单,大坑加急处理。第二个是自动驾驶的安全预警。车辆前方出现明显深坑时,提前提示绕行或者减速,避免轮胎损坏或底盘刮擦。第三个是市政基础设施普查。结合地理信息,把每个坑的位置和等级标注到地图上,形成一张病害分布图,养护部门按等级安排资金和工期。
如果是做科研或者课程项目,这套数据同样适用。它同时提供三种格式,可以拿来对比不同框架之间的标注格式差异,也可以当作目标检测入门的练习数据。类别只有三个,复杂度适中,又有真实场景的难度,比在标准分类数据集上做实验更有工程感。
2. 数据标注规范:模型能不能学到“大小”全看这里
2.1 坑洼目标的边界标准
标注坑洼比标注行人、车辆费劲得多,核心原因是边界不清晰。一个坑洼的边缘往往伴随裂缝、磨损、松散颗粒,很难说哪个像素是真正的边界。这套数据的标注规范里定了三条硬性规则,写得很清楚。
第一,只框“明显下陷区域”,不包括周围过渡带。过渡带看起来也在变化,但模型如果学了过渡带,框就会飘,训练时loss降不下去,推理时框也会忽大忽小。第二,坑内有积水时,按“可见的下陷轮廓”标,不按水面积标。水的反光区域通常比真实坑洼大,按水面积标注会把尺寸虚高,导致等级判断偏大。第三,多个坑距离很近但中间没有明显断裂时,合并标一个框;有明显断裂或高度差时,分开标。
这条规则看起来简单,实际标注时分歧最大。两轮人工复核里很多意见冲突都出在这条上:有人说这明明是三个小坑,有人说连起来就是一个大坑。最后统一口径:断裂指的是坑底可见完整路面、两侧高度差超过2厘米的情况。规则不写细,标注真值就会漂移,模型学到的回归目标就是乱的。
2.2 大小等级怎么定义才靠谱
等级定义是这套数据集的差异化核心。建议不要直接用“小中大”这种模糊词,标注手册里必须给精确的物理口径。
参考定义如下:坑洼短边小于30厘米是小坑,30到60厘米是中坑,大于60厘米是大坑。这里用短边而不是对角线,原因在于坑洼形状不规则,用对角线判断长条形坑洼容易虚高。短边更接近“危险程度”的物理直觉,轮胎陷入深度和坑宽直接相关,超过一定宽度就必须减速绕行。
标注时还需要一个辅助判据:图像面积占比。当两个坑在画面里大小相近但拍摄距离不同时,标注员容易懵,这时候要回到物理口径查表,而不是凭感觉。我在复核时见过不少“凭感觉标”的样本,例如一个近距离小坑和一个远距离大坑在画面里像素尺寸差不多,如果标注员没有看采集参数,很容易把等级标反。所以数据包里的每张图像都记录了可选的拍摄高度,标注时只需要对照换算表查一下。
2.3 质检流程比标注更重要
数据质量不是标注员单方面决定的,发布前的质检流程比标注本身更关键。
这套数据的质检分了三道。第一道是自动化校验,程序检查每个标注框是否越界、类别是否在合法集合里、坐标格式是否正常。这一步能查出低级的坐标错误,比如框跑到图像外面、宽高为负、类别ID越界。第二道是人审,把图像放大到原始尺寸逐张查看,重点看等级是否标错、框是否贴边。第三道是交叉验证,两轮独立标注的结果对齐后计算一致率,把分歧样本抽出来重新定标。
这套流程下来,大约5%的样本会被剔除或者修正。过程很慢,但没有质检的数据集不能直接拿来训练。之前遇到过一些项目训练时频繁报错、效果始终上不去,往源头一查,标注质量问题和格式文件问题一大堆,最后只能返工重标,代价远大于一开始认真做质检。
3. YOLO、COCO JSON、PASCAL VOC XML三种格式详解
3.1 三种格式的区别
数据集同时提供三种标注格式,是为了让不同工具链的人拿到手就能用。很多刚入门的人容易在格式上栽跟头,先讲清楚区别。
YOLO格式是txt文件,每张图像对应一个同名的txt文件,每一行对应一个目标框。行的内容是:类别ID、归一化中心x、归一化中心y、归一化宽度、归一化高度。归一化是指把坐标值和宽高都除以图像的宽高,所以所有数值都在0到1之间。这个格式轻量、读取快,是YOLO系列训练的标准配套格式。
COCO JSON是一个单独的JSON文件,包含images、annotations、categories三个主要部分。annotations里的bbox字段表示[x, y, width, height],用的是绝对像素值,类别通过category_id关联。这种格式结构性最强,生态完善,评测指标mAP的计算、可视化工具的支持几乎都基于这个格式。
PASCAL VOC XML是每张图像对应一个XML文件,目标框用xmin、ymin、xmax、ymax表示左上角和右下角坐标。这是最老牌的格式,很多传统标注工具早期默认输出的就是这种XML。
三者的核心差异就是坐标表示方式不同:YOLO存归一化中心点加宽高,COCO存绝对左上角加宽高,VOC存绝对左上角加右下角。本质表达的框完全相同,只是“说法”不一样。
3.2 格式转换的实操方法
如果拿到的数据只有其中一种格式,想换一种也不需要从头标。最省事的方式是直接用现成的标注工具或在线转换服务,一般都有导入导出功能。更稳妥的做法是写本地脚本,因为数据量大的时候在线服务上传下载也费时间。
COCO转YOLO的核心逻辑:读取bbox的[x, y, width, height],换算成中心点坐标[cx, cy, width, height],再除以图像宽高做归一化。这里有两个必修的坑。一是COCO的category_id从1开始,YOLO的类别ID从0开始,转换时要记得减1,否则所有类别整体错位,模型训练出来预测的标签全是对不上的。二是COCO的image字段里的路径可能和本地实际路径不一致,要按图像文件名重新映射,不然训练时报找不到文件。
PASCAL VOC转YOLO更直接:解析XML取object节点下的bndbox,把xmin、ymin、xmax、ymax换算成中心点和宽高,再归一化写入txt。这个场景在迁移旧数据时很常见。
格式转换后一定要做可视化校验,把标注框画回图像上抽查几十张。坐标转换的数学很简单,但图像尺寸取错、类别偏移这种问题不画出来是看不出来的,抽查是最直接可靠的兜底方案。
3.3 训练时选哪个格式
选哪种格式主要取决于你用的框架。YOLO系列官方训练流程就用YOLO格式,目录组织最简单。做评测对比的,优先COCO格式,mAP计算、PR曲线的工具链都成熟。兼容老工具链的,VOC格式也支持得很好。
经验之谈:拿到数据后不要只准备一种格式,最好把三种都留着。团队里有人用YOLO跑基线,有人用老工具做可视化,有人要做COCO格式的对比实验,各取所需就省得反复转换。这套数据集本身自带三种格式,也是这个考虑,拿回去直接就能开工。
4. 92.6%识别率是怎么来的:完整训练管线复盘
4.1 先搞清楚这个指标是什么
92.6%这个数字,通常指mAP@0.5,也就是在IoU阈值0.5下所有类别的平均精度。IoU是模型预测框和真实标注框的重叠程度,0.5意味着预测框和真值有50%以上的重叠就算一次正确检测。这个阈值下目标是“能找到”,允许一定框定位误差,所以数字会比较高。
需要提醒的是,mAP@0.5:0.95会比92.6%低不少,这是正常的。0.5:0.95表示从0.5到0.95每间隔0.05取一个IoU阈值,再算平均精度,对框的精确程度要求严格得多。同一个模型两个指标一起看:前者衡量“目标找没找到”,后者衡量“框得准不准”。如果只盯着92.6%这个数字,不看阈值定义,很容易对自己的模型产生过高的预期。
这个92.6%是在严格的测试集上评测出来的。测试集和训练集做了图像来源隔离,同一条路段不会同时出现在两边;接近重复的连续帧也做了去重,防止模型靠记忆相近帧拿到虚高的数字。
4.2 模型选型和训练超参配置
实际测试下来,在同等数据条件下,几个主流YOLO版本之间的差距并没有网上说的那么夸张,真正拉开差距的还是数据质量、增强策略和超参数。
以中等规模的YOLO模型为例,输入分辨率640,训练200轮,batch size设置在显存能承受的最大值附近,初始学习率0.01,采用余弦退火调度,加载预训练权重做迁移学习。这套配置在坑洼数据上表现稳定,收敛快,最终mAP@0.5稳过90%。
如果你用更轻量的模型,输入分辨率保持640,200轮训练,也能达到80以上的mAP,推理速度更快,适合边缘设备部署。如果追求更高的框定位精度,可以把输入分辨率提到960甚至1280,对小坑洼的检测尤其有帮助,但对显存的要求同步提高。我的建议是先用中等模型跑通流程,再根据性能瓶颈决定要不要换大模型。
4.3 数据增强带来的提升点
在坑洼检测这个场景里,数据增强的作用非常明显,接近一半的效果提升都来自增强策略。
坑洼的视觉特征受光照影响极大,同一个坑,晴天直射和阴天散射看起来就像两个东西。所以训练里重点开了色调饱和度随机扰动、随机亮度调整、马赛克增强、混合增强和翻转。上下翻转和左右翻转对路面检测都安全,坑洼不会因为翻转变成“天上物体”。
有一项增强建议保留但降低概率:随机透视。透视变换的缩放会产生类似不同视角的样本,但概率过高会让小坑在变换中严重变形,反而损害小目标检测。实际配置里概率调到0.1左右比较合适。
还有一个小细节:验证集和测试集不能开增强,评价指标才干净。训练时增强打开,评估时增强关闭,这个区分不做,线上效果一定比测试结果差。
4.4 可直接复现的训练配置
分享一套实际跑通的配置,你可以直接参考。数据目录结构按以下方式整理:
pothole_dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/数据配置文件这样写:
path: /data/pothole_dataset train: images/train val: images/val nc: 3 names: 0: pothole_small 1: pothole_medium 2: pothole_large训练命令对应如下:
yolo detect train \ model=yolov8m.pt \ data=pothole.yaml \ epochs=200 \ imgsz=640 \ batch=16 \ lr0=0.01 \ cosate=True \ patience=30 \ cache=True跑完以后,测试集上mAP@0.5大约在92.6%附近。推理一张1080p图的时间在消费级显卡上低于10毫秒,能够满足实时巡检场景。
5. 数据集到手后的实操流程
5.1 先用可视化脚本确认数据没问题
拿到数据集后不要直接开训练,先做一步验证。我习惯先写一段小脚本,把任意一张图像和它的标注框画出来,人工确认三个点:框是否贴合坑洼轮廓、类别标签是否和视觉印象一致、坐标是否越界。
这一步能在十分钟内发现格式转换遗留的坐标错位、类别偏移、图像路径错误等问题。跳过这一步直接训练的,往往训练到一半发现loss异常,回头排查才意识到是数据加载就出错了。
5.2 按格式拆分训练集验证集
数据包默认已经按划分好的目录组织好,训练集和验证集是分开的。需要注意别重复划分,很多框架会在数据集yaml里自动划分数据,如果目录已经划分过,再划分一次会造成交集,测试结果虚高。
建议的做法:直接使用数据包自带的目录结构,在yaml里指定train和val路径即可。如果自己想重新划分,务必按“路段隔离”来分,而不是按“图像随机分”。同一个路段的图像光照、纹理高度相似,随机分会让模型见过同一路段的不同帧,评测结果会偏乐观。
5.3 评估结果怎么读
训练结束后,输出目录里会有results.csv、混淆矩阵、预测样本图等文件。重点看三个东西。
第一个是PR曲线,precision和recall的平衡点决定了业务上怎么选置信度阈值。坑洼检测里漏检比误检更危险,所以通常会选择低置信度阈值换取高召回,代价是误检增加,这时可以加后处理规则。第二个是混淆矩阵,看三个尺寸等级之间是否有大量互相误判。如果小坑大量被识别成中坑,说明等级边界定义在视觉特征上区分度不够,需要检查标注时是否严格执行了物理口径换算。第三个是验证集上的逐类AP,小坑的AP一般最低,这是小目标检测的通病,可以针对性地用小坑样本微调或提高输入分辨率。
6. 常见问题与排查技巧
6.1 高频问题速查表
整理了一份常见问题速查表,覆盖数据使用和训练阶段遇到最多的情况。
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 训练时找不到图像文件 | 数据路径配置错误或图像路径包含中文/空格 | 检查yaml里的path,路径中不要用中文和空格 |
| loss异常高或震荡剧烈 | 标注真值有错,出现类别ID越界或框坐标错误 | 做一次可视化校验,重点检查异常类别和边框越界 |
| 小坑大量漏检 | 输入分辨率太低,小目标特征被压缩 | 提高imgsz到960或1280,或对小坑样本过采样 |
| 中坑和大坑互相误判 | 等级边界标注不一致,标注员没有按物理口径查表 | 抽查标注规范执行情况,重新校准边界样本 |
| 井盖、水渍被误检为坑洼 | 干扰项负样本不足 | 补充带井盖、水渍、阴影的负样本或增加混合增强 |
| 雨天测试效果骤降 | 训练数据缺少雨天湿滑样本 | 训练集里增加雨后积水样本,或做饱和度、亮度扰动增强 |
6.2 踩过的几个实坑
第一个坑:类别互斥没处理好。早期版本曾把同一个坑同时标注成“中坑”和“大坑”,因为两个标注员各标各的,合并时没有做冲突检测,导致模型在这个类别对上的梯度方向冲突,训练时loss降不下去。现在质检的第一关自动化校验就会跑类别互斥检查,避免类似问题。
第二个坑:转化格式后忘了更新图像尺寸。YOLO格式是归一化坐标,本身不依赖图像尺寸;但转成COCO或者VOC时需要绝对像素坐标,如果脚本读取的是yaml里写的规格参数而不是原图真实的分辨率,标注框就会整体偏移。这个问题的排查成本很高,模型训练出来效果不差但框总是偏一点,最后才发现是转换时图像尺寸取错了。
第三个坑:验证时开了增强。跑测试时忘了关掉augment开关,测试集的结果被增强策略“拔高”了,当时觉得效果不错,后来部署上线发现完全不是那么回事。从那以后,我每次评估都在配置里强制关闭增强,把验证结果和训练日志分开看。
6.3 部署阶段的小建议
模型训练好以后,部署时还有一个小建议:把置信度阈值和等级后处理规则分离。如果在模型层面直接输出三个等级,只需要在业务逻辑里维护一个“最低可行动等级”配置,比如今天路面养护资源紧张,只处理大坑,那就把大坑的置信度过滤调低,其他等级调高。这样调整不需要重新训练模型,改配置就能上线新策略,在养护团队里这样操作过,前后端配合起来非常灵活。
另外,坑洼检测模型在不同路段之间会有一定的泛化差异。如果实际巡检路线和数据集采集的环境差别很大,建议先小路测采集一段视频,做一遍离线推理统计,看等级分布是否符合预期,再决定是否需要在业务数据上做一次轻量的微调。数据永远是最重要的,模型结构反而是最后才值得优化的东西。
这套数据集给我的最大感受是:坑洼检测这类任务,真正的门槛不在模型结构,而在数据规范。一个目标怎么定义边界,等级怎么划分,格式怎么统一,每一个细节都会在训练结果里放大。如果你正准备做类似的方向,先把数据规范和质检流程立起来,比选一个更先进的小模型有用得多。