资讯动态

YOLOV5路面缺陷检测数据集:4类别目录格式与标注实践全解析

发布时间:2026/10/18 7:25:40 来源:尧图企业网站定制
简介一套面向路面缺陷检测的YOLOV5标准目录格式目标检测数据集适合目标检测初学者或道路养护场景快速训练与验证。数据均为600×600的RGB图片标注4类常见路面缺陷纵向裂纹、横向裂纹、坑洞、不规则裂缝并预先划分为训练集841张与验证集231张每个图片均配有对应的txt标注文件可直接送入YOLOV5工程使用。压缩包内共2000个文件主要包括1073个txt标签文件、926张jpg图像和1个Python可视化脚本脚本无需修改即可运行随机传入一张图片即可绘制边界框方便快速检查标注质量。资源整体约74.55MB目录结构按训练集与验证集分开组织便于数据管理与迭代。目前已有770人浏览学习是一份轻量、清晰且可直接落地的目标检测数据集。1. 路面缺陷检测为什么绕不开 YOLOV5 目录格式一个 4 类别数据集能解决什么路面缺陷检测这几年从纯人工巡检转向「相机采集 模型识别」卡住落地的往往不是算法而是数据。标题里的「目标检测数据集(YOLOV5目录格式)路面缺陷检测数据4类别」指的是一份已按 YOLOv5 官方目录排好的数据images 放原图labels 放同名 txt 标注4 个类别通常对应裂缝、坑槽、龟裂与修补。对做道路巡检、市政养护、无人机公路检测的团队它省掉了从零整理数据的时间拿到手就能进训练流程对刚入门目标检测的开发者这也是把 YOLOv5 全流程走通的标准练习集。但目录排好不等于能训好标签边界、类别均衡、增强参数都会左右最终 mAP。后面按「格式 → 标签 → 划分 → 踩坑 → 验证」的顺序拆开讲。2. YOLOV5 目录格式拆解从图片目录到 data.yaml 的完整落地拿到一份路面缺陷数据第一件事不是急着训练而是确认目录结构是不是 YOLOv5 认得的那一套。YOLOv5 对数据组织的约定很死板图片和标签分属两个目录同名文件一一对应标签必须是 YOLO 格式的 txt。很多数据源初期可能是 VOC 的 xml 或 COCO 的 json转成 YOLO 之前先把目录本身立起来后面每一步才走得稳。2.1 标准目录结构images 与 labels 的同名对应关系我一般会先按这个结构落盘road_defect/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── rd_00001.jpg │ │ └── rd_00002.jpg │ ├── val/ │ │ └── ... │ └── test/ │ └── ... └── labels/ ├── train/ │ ├── rd_00001.txt │ └── ... ├── val/ └── test/这里有三条硬约定。第一条图片和标签只靠「同名不同后缀」关联rd_00001.jpg 对应 rd_00001.txt后缀不一致或文件名带空格、中文都会造成图片被静默跳过。第二条train/val/test 在 images 与 labels 两侧必须同名同数量划分在目录层面完成data.yaml 里只需写 train 和 val 的路径。第三条图片统一转成 jpg 再入库YOLOv5 读图走 cv2png 带透明通道时容易读出异常通道数路面图片量大时 jpg 也能省不少磁盘和加载时间。另外 labels 目录里只能放 txt混入 json 或 xml 会在训练时被遍历到并报格式错误。注意先运行一个比对脚本确认每一张训练图片都有同名 txt且 txt 非空。空标签文件在 YOLOv5 里会被当成背景图处理训练时不报错但 val 效果会神鬼莫测。2.2 data.yaml 写法与路径基准path、nc、names 一个都不能少目录就位后在数据集根目录放一个 data.yaml# road_defect/data.yaml path: /data/road_defect # 数据集根目录建议写绝对路径 train: images/train val: images/val nc: 4 names: 0: crack 1: pothole 2: alligator_crack 3: patch这里最容易翻车的是路径基准。YOLOv5 解析 data.yaml 时如果写了 pathtrain 和 val 就是相对于 path 的路径如果不写 path相对路径会以启动训练时的当前工作目录为基准换个目录跑同样的命令数据就找不到了。所以只要数据集和脚本不在同一个固定目录我建议一律写 path 绝对路径。第二个坑是 names 的索引必须从 0 开始且连续标签文件中所有类别 ID 都得落在 0nc-1 之间出现类别 4 而 nc 只写了 4会直接触发索引越界。第三个坑是类别名用英文小写单词别用中文或带空格的名字后续部署转 ONNX、做结果过滤时中文名处理起来非常麻烦。提示标题只说明是 4 类别具体是哪四类要以 labels 里的类别 ID 分布和提供方的类别说明为准。如果 txt 里只出现 0、1、2没有 3先核对是不是某一类样本缺失或名字映射没对齐再决定 names 怎么写。2.3 用脚本生成目录并自动划分把原始图片拆成 train/val/test即使数据集出厂就是 YOLOV5 目录我也建议拿到手后用脚本重新划分一遍确保 val/test 的独立性可控。常见做法是先按固定比例随机打乱划分import random import shutil from pathlib import Path random.seed(42) SRC Path(./raw_images) # 原始图片统一放这里 DST_IMG Path(./images) DST_LBL Path(./labels) RATIOS (0.7, 0.2, 0.1) # train / val / test imgs list(SRC.glob(*.jpg)) list(SRC.glob(*.png)) valid [p for p in imgs if (SRC / f{p.stem}.txt).exists()] print(f有效图片 {len(valid)} / 总图片 {len(imgs)}) random.shuffle(valid) n_train int(len(valid) * RATIOS[0]) n_val int(len(valid) * RATIOS[1]) for i, img in enumerate(valid): part train if i n_train else val if i n_train n_val else test (DST_IMG / part).mkdir(parentsTrue, exist_okTrue) (DST_LBL / part).mkdir(parentsTrue, exist_okTrue) shutil.copy2(img, DST_IMG / part / img.name) shutil.copy2(SRC / f{img.stem}.txt, DST_LBL / part / f{img.stem}.txt)脚本做了两件关键事一是只保留有对应 txt 的图片把「图片有、标签没有」的脏样本挡在训练外二是用固定随机种子保证每次划分结果可复现。RATIOS 里的 0.7/0.2/0.1 是路面场景比较稳的默认值数据量在几千张时够用只有几百张的小数据我建议改成 0.8/0.2 不留 test把留白全部给验证集避免测试集太小导致评估波动。划分脚本在 4.1 节还会补一段按类别分层的版本数据类别不均衡时那一版更可靠。3. 四类别标注边界与 YOLO 标签格式裂缝、坑槽、龟裂、修补的框该怎么画数据本身是「有标注的」但不代表标注没有歧义。我拿到带标注的路面数据后会先抽 50 张图把框画出来看一遍重点看类别边界是否统一。四类缺陷从形态上比较好分但真实路面场景里阴影、油渍、施工痕迹都会让标注者犹豫这一章把判定规则和标签格式一次说清楚。3.1 四类缺陷的判定边界容易混淆的对象与标注优先级先给一张我在整理路面数据时常用的判定表类别推荐名称典型形态容易混淆的对象判定优先级crack裂缝线状、细长、单条或几条交错龟裂的局部、伸缩缝只有线状纹理时归 crackpothole坑槽块状凹陷、边缘粗糙、颜色深阴影、油渍、修补脱落有明确凹陷和破损优先 potholealligator_crack龟裂网状、多边块状交织多条裂缝交叉、重载车辙呈网络状成片出现时归 alligator_crackpatch修补规则或不规则补丁颜色与周边不同新铺沥青颜色差、树影人工修补痕迹明显归 patch实际标注中优先级「坑槽 龟裂 裂缝」能解决大多数重叠争议一个区域里既有网状裂缝又有脱落坑洞时按坑槽标没有坑洞的网状纹理按龟裂标已经是修补区域的不再单独标里面的裂缝和龟裂。这套规则看起来简单却是后面类别 AP 能不能稳住的根基标注混乱的数据集喂给再好的模型也是事倍功半。3.2 YOLO 标签格式与坐标换算归一化框的每个字段YOLOv5 的标签是一行一个目标的纯文本格式固定为 class x_center y_center width height全部是相对图片宽高的归一化值0 0.4731 0.5124 0.0832 0.0419 2 0.6123 0.4803 0.1604 0.1145第一行表示一条裂缝类别 0位于图片中心 (0.4731, 0.5124)宽高占全图的 8.3% 和 4.2%。如果数据是从 VOC 格式转来的换算逻辑是W, H img.shape[1], img.shape[0] # 原图宽高不是 resize 后的 xc (xmin xmax) / 2 / W yc (ymin ymax) / 2 / H bw (xmax - xmin) / W bh (ymax - ymin) / H # 拼接结果写一行class_id xc yc bw bh保留 6 位小数这个环节有三个细节决定成败。第一分母必须是原图的宽高如果图片在标注平台里被显示成缩略图换算出来就是错框第二x_center 是框中心的归一化坐标不是左上角第三小数位保留 6 位就够更长的小数不会提升精度反而让文件体积无谓变大。转完后我会用第 5 章里的检查脚本跑一遍坐标范围任何负坐标和大于 1 的值都意味着标注或转换出了问题。3.3 细长裂缝与重叠目标的标注策略拆几段、合一个框裂缝是四类里标注分歧最大的目标。一条贯穿整张图的路面裂缝常见做法是沿着延伸方向拆成 24 段分段标注每段的框尽量贴合裂缝本体避免一个横跨全图的超长框把大量背景包进来。拆得太多也不行一段裂缝被拆成十几个小框后每个框都只有几十个像素模型很难学到连续性特征AP 反而下降。我的经验是单段长度控制在图片短边的三分之一以内比较稳。细长框的宽高比经常超过 10:1而 YOLOv5 默认锚框比例多在 0.33 之间超长框匹配不到合适锚框最直接的后果是这一类训练慢、AP 低。另一个常见分歧点在龟裂区域一个成片的龟裂区只用一个框包住整体框内细碎的裂缝不再单列否则一张图上十几个互相覆盖的框会让正样本的定义变得模糊。4. 数据划分与增强参数让路面缺陷模型在小数据量下不翻车路面缺陷数据的常见瓶颈是量不大视频抽帧容易真正有效标注可能只有一两千张。这个量级下划分方式和增强参数比网络结构更影响结果。这一章给出两个能直接抄的配置。4.1 按类别分层的划分先看分布再切 train/val/test随机划分在类别不均衡时会把稀有类全部分到 train造成 val 里某类样本为零评估结果完全失真。我拿到数据的第一件事是统计类别分布from collections import Counter from pathlib import Path counter Counter() empty [] for txt in sorted(Path(./labels/train).glob(*.txt)): lines txt.read_text().strip().splitlines() if not lines: empty.append(txt.name) continue for line in lines: counter[int(line.split()[0])] 1 print(类别分布:, dict(counter)) print(空标签文件:, empty)统计完先看两个数每个类别的目标总量和空标签文件的数量。如果某个类别样本量只有其他类的十分之一比如修补类普遍少就要在划分时做分层处理把所有图片按「是否包含稀有类」分成两组每组内部再按比例抽 train/val/test保证两个集合里稀有类都存在。最简单实现是把 2.3 节脚本里的 random.shuffle(valid) 换成对两个分组分别 shuffle 后再合并。4.2 增强参数怎么调马赛克、明度扰动与翻转的取舍YOLOv5 默认的增强配置在路面场景下多数可以直接用但有几个参数值得单独调。默认 hyp 里的 HSV 扰动大约是色相 0.015、饱和度 0.7、明度 0.4对路面这种光照变化剧烈的场景明度扰动建议再放宽一点坑槽在逆光下常常就是一团深色训练集里明度多样性不够验证时就漏检。翻转向量方面车辆前视采集的路面图建议只开 fliplr左右翻转不开 flipud因为上下翻转后的路面语义不合理如果是无人机俯拍两个方向翻转都没问题。参数默认参考值路面场景建议理由hsv_h0.0150.010.015色调扰动物理意义弱保持默认hsv_s0.70.70.9增强日晒/背阴路面差异hsv_v0.40.50.6逆光阴影多明度多样性要够fliplr0.50.5道路左右对称可放心开flipud00前视图像不开mosaic1.01.0小数据保持小目标多mosaic 提供上下文马赛克增强在小数据集上基本是必开的它能在一张图里拼出 4 张图的场景等于送了几倍内存和样本多样性只有当数据量超过一万张时我才会考虑降到 0.5 以下因为那时代价主要是训练时间。这里要提醒一句增强参数不是越多越好路面缺陷里裂缝是强纹理目标过度模糊、过度旋转反而让它和树影、油渍更难区分所有改动都以 val 集表现为准一次只改一个参数。4.3 最小训练命令与首轮验证先跑通再谈优化划分和增强都定下来后用一个最小命令先跑通全流程python train.py \ --data /data/road_defect/data.yaml \ --weights yolov5s.pt \ --imgsz 640 \ --batch-size 16 \ --epochs 50 \ --device 0--imgsz 640 是路面目标常用的默认值裂缝和坑槽都不算超小目标640 足够--batch-size 按显存来16G 显存跑 yolov5s 一般是 16 到 32--weights yolov5s.pt 表示从官方预训练权重开始路面图片和通用场景差异大但底层特征仍然有用收敛速度明显快于从零训练。首轮 50 个 epoch 够判断数据是否正常训练时盯两个东西loss 是否前 10 个 epoch 内明显下降val 集的 mAP0.5 是否在稳步爬升。如果 loss 下降很快、mAP 原地不动甚至往下掉多半不是参数问题而是标签质量问题直接跳到第 5 章排查。5. 路面缺陷数据集使用中的 5 个常见坑与排查清单这一章全是我在路面数据上反复踩过的坑按现象、原因、解决的顺序写照着排查比瞎调参有用得多。5.1 图片与标签对不齐训练集悄悄变小val 精度虚高**现象**训练日志里每个 epoch 处理的图片数明显少于预期的图片数或者验证精度高得异常但现场实测漏检一堆。**原因**文件名存在尾缀不一致比如图片是 rd_1.jpg 而标签的 stem 对不上还有部分是标签文件为空被 YOLOv5 当成背景图跳过等于训练样本直接缩水。val 精度虚高通常是因为 val 和 train 里混入了同一来源的连续帧内容高度相似。**解决**先把 4.1 节的统计脚本跑一遍确认空标签再用代码比对 images 与 labels 两个目录的 stem 集合是否完全一致。val 独立性的问题没有自动化捷径只能靠划分脚本检查文件在集合层面不相交采集时也别把连续视频帧同时塞进两个集合。5.2 坐标越界和零尺寸框loss 突跳甚至 NaN 的前兆**现象**训练日志频繁出现 out of bounds 警告或者某个 epoch loss 突然翻倍再往后直接 NaN。**原因**转标注格式时分母用错或者标注工具导出时框被裁剪到图片外得到 xmax 大于图片宽度、宽高为 0 的坏框。YOLOv5 对越界框只打警告不做剔除坏框多了训练就崩。**解决**写一个轻量检查脚本逐行解析 txt过滤 w 或 h 小于等于 0、坐标小于 0 或大于 1 的记录把文件名列出来回炉重标。这个检查应该放进每次取数后的固定流程因为标注工具版本升级往往就会批量产出这类脏数据。5.3 类别不均衡龟裂和修补的 AP 塌方**现象**训练完看逐类 AP裂缝和坑槽 0.7 以上龟裂或修补只有 0.10.2总 mAP 看着还行但那一类场景完全不能用。**原因**数据原本就少随机划分又让 val 里的稀有类只有几张同时模型把稀有类学成了背景或错分成邻近类。**解决**先按 4.1 分层划分保证 val 里有稀有类样本再对稀有类图片做「裁剪级复制」把一张 1280 的图裁成两张 640 的图既增加样本量又没改变标注坐标。复制整图会引入和 val 的潜在重复裁剪复制风险小得多我一般用这种办法把稀有类补到其他类样本量的三分之一以上。5.4 光照与阴影逆光、桥下阴影导致的漏检与误检**现象**白天顺光图效果很好一到逆光、桥下阴影或树影路段坑槽大量漏检阴影边缘被误检成裂缝。**原因**训练集里这些困难场景占比太低模型学到的正样本亮度分布太单一HSV 增强里的明度扰动默认幅度又不足以覆盖这种差异。**解决**把困难场景图片优先扩充进训练集这是最直接的办法同时把 hsv_v 提到 0.50.6让模型见过更多亮度形态。如果困难样本实在凑不齐对训练图做一次自适应直方图均衡的副本再入库也能让亮度分布更平缓但注意副本不要进 val。5.5 类别边界混淆同一个缺陷在不同图上被标成两个类**现象**训练 loss 一直降不下来val 的 mAP 在 0.30.5 之间波动人工抽检发现同一形态的网状破损一张图标成龟裂另一张图标成裂缝。**原因**标注规范里没有优先级规则多人标注时各自按直觉判断类别边界在数据层面就是模糊的。模型被迫学出「两个类没区别」自然收敛不了。**解决**按 3.1 节的优先级表重跑一遍争议样本批量筛选的办法是找出同时包含裂缝类和龟裂类的图片人工复核这两类是否真的同时存在。类别定义写清楚后把修正后的标签重新入库再训练这属于没有后悔药的环节越早定义越省事。6. 训练前先做可视化核验一张图看穿标签问题再用逐类 AP 收尾我的习惯是任何数据集进门先做一遍画框核验再谈训练。画框的脚本很简单import cv2 from pathlib import Path NAMES {0: crack, 1: pothole, 2: alligator_crack, 3: patch} COLORS {0: (0, 0, 255), 1: (0, 255, 255), 2: (255, 0, 255), 3: (0, 255, 0)} Path(./check).mkdir(exist_okTrue) for txt_file in sorted(Path(./labels/train).glob(*.txt))[:30]: img cv2.imread(str(Path(./images/train) / f{txt_file.stem}.jpg)) for line in txt_file.read_text().strip().splitlines(): cid, cx, cy, w, h map(float, line.split()) x1 int((cx - w / 2) * img.shape[1]) y1 int((cy - h / 2) * img.shape[0]) x2 int((cx w / 2) * img.shape[1]) y2 int((cy h / 2) * img.shape[0]) cv2.rectangle(img, (x1, y1), (x2, y2), COLORS[int(cid)], 2) cv2.putText(img, NAMES[int(cid)], (x1, max(0, y1 - 6)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, COLORS[int(cid)], 1) cv2.imwrite(f./check/{txt_file.stem}_check.jpg, img)画完重点看三件事框有没有贴住缺陷本体、细长裂缝有没有被拆得支离破碎、龟裂区是不是被重叠框盖满。这些问题在 txt 里根本看不出来画出来一眼就懂比任何自动检查脚本都直观。划分阶段还要确认 train 与 val 的文件名没有交集防止连续帧泄漏。训练结束后用逐类 AP 收尾YOLOv5 验证完会在终端打印每个类别的 P、R、mAP50 表也可以单独跑一次 val.py --verbose 重新核验。某个类别 AP 明显低于其他类回到 5.3 补样本、5.5 查边界别急着调网络结构。这个「先画框、再看逐类 AP」的习惯我保持了很久血泪经验是只盯总 mAP 最容易自我欺骗——某一类塌方会被其他三类的大数字盖住。数据集质量这件事自动化工具只能查格式查不了语义人的眼睛仍然是最后一道防线。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑