ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

路面缺陷检测数据集拆解:YOLOV5目录格式与训练避坑指南

路面缺陷检测数据集拆解:YOLOV5目录格式与训练避坑指南 简介面向使用YOLOV5框架进行路面缺陷识别的研究者与开发者这是一份包含纵向裂纹、横向裂纹、坑洞、不规则裂缝四个常见道路破损类别的目标检测数据集。数据按YOLOV5标准目录保存为训练集与验证集训练集841张图片及对应标签txt文件验证集231张图片及对应标签txt文件图像统一为600×600的RGB格式标注信息完整可直接投入模型训练。资源共2000个文件由1073个txt标签、926张jpg图片和1个py可视化脚本组成附带类别说明txt脚本随机传入一张图片即可自动绘制边界框并保存结果便于快速核对标注质量。整体压缩包约74.55MB目前已有769人学习下载。对刚入门目标检测的学习者来说这套开箱即用、目录结构清晰的数据集既免去繁琐的格式转换流程也能为道路养护、自动驾驶等场景中的缺陷检测技术验证提供可靠的数据基础。1. 路面缺陷检测数据集YOLOV5目录格式的4类别数据下完就能开训做目标检测的人最怕的不是模型调参而是数据集到手先要擦屁股格式不对、坐标没归一化、训练验证混在一个文件夹里。这份路面缺陷检测数据集我拆完之后第一感觉是——这活儿终于有人干完了。74MB、600×600 RGB图、4个类别纵向裂纹、横向裂纹、坑洞、不规则裂缝数据已经按YOLOV5的标准目录铺好训练集841张、验证集231张连画框可视化的py文件都附带了下载解压就能直接开训不需要再写格式转换代码。这数据适合两类人。新手可以拿它完整走一遍YOLOV5从配置、训练到验证的流程不用在数据格式上翻车已经在做道路检测的熟手可以拿它当baseline数据验证自己的网络结构、数据增强思路或者anchor设置。图像是路面缺陷的典型切片细长裂纹居多这个形状特点本身就是训练时容易踩坑的地方。接下来我只讲拆包后最值得关心的东西目录怎么组织的、标签怎么写的、训练前哪些坑会让你白等一晚上。2. 目录结构拆解images/labels 配对关系与类别先验2.1 目录布局与YOLOV5的组织惯例解压后主目录里是 datasets 下分 images 和 labels各自带 train 和 val 两个子目录。训练集 images/train 里 841 张jpglabels/train 里 841 个txt验证集同理 231 对。先用 tree 命令过一遍结构tree -L 3 datasets/ # 期望输出 # datasets/ # ├── images/ # │ ├── train/ # 841 张 .jpg # │ └── val/ # 231 张 .jpg # ├── labels/ # │ ├── train/ # 841 个 .txt # │ └── val/ # 231 个 .txt # └── classes.txt # 4 行类别名一行一个图片和标签文件一一配对配对靠主文件名硬关联Czech_002951.jpg 必然有一个 Czech_002951.txt主文件名完全一致只是一个在 images 一个在 labels。这是YOLOV5约定俗成的关联方式——它不读任何标注索引文件只认文件名前缀。所以拿到手第一件事就是确认每一对都存在缺一个都不行。YOLOV5 对数据目录要求很宽松它只看 data.yaml 里 path、train、val 三个字段train/val 指向图片目录标签目录它会自动把路径里的 images 替换成 labels。这就是为什么目录一定要按 images/labels 的结构放不要自己造一个 mixed 目录把图和txt混在一起否则训练时会报找不到标签文件。2.2 四类缺陷定义与数据分布classes.txt 里的四个类别要在训练前确认顺序因为标签txt里第一列的整数就对应这个顺序。常见排法如下class_id类别目标形态0纵向裂纹细长条沿行车方向拉长1横向裂纹细长条垂直行车方向2坑洞近圆形或多边形块状3不规则裂缝网状、分叉无固定长宽比训练验证按 841:231 划分接近 4:1。每个txt里有多少行就代表这张图有几个目标框另外需要注意同一类里不同框的尺寸差异很大——坑洞往往是几十像素的块裂纹却可能贯穿整张 600×600 的图这种尺度剧烈变化在没有多尺度训练时挺考验模型。先统计每类目标的框数和平均宽高我一般用十几行的脚本跑一遍心里先有数import os import numpy as np labels_dir datasets/labels/train cls_count {0:0, 1:0, 2:0, 3:0} widths, heights [], [] for f in os.listdir(labels_dir): if not f.endswith(.txt): continue with open(os.path.join(labels_dir, f), encodingutf-8) as fh: for line in fh: parts line.strip().split() if len(parts) 5: continue # 空行或缺字段直接跳过 c int(parts[0]) w float(parts[3]) # 归一化宽 h float(parts[4]) # 归一化高 if c in cls_count: cls_count[c] 1 widths.append(w) heights.append(h) print(类别分布:, cls_count) print(平均归一化宽:, np.mean(widths), 高:, np.mean(heights))这个脚本只依赖 os 和 numpy不需要额外装库把训练标签过一遍。它统计了两件事各类别样本数是否均衡、框的平均尺寸落在哪个量级。如果发现某类框数特别少比如坑洞只有几十个那就提前知道这类AP大概率偏低应该在训练后单独看这个类别的验证指标而不是只盯着整体mAP。2.3 配对完整性与重复文件校验目录树看着没问题不代表标签真的对得上。常见坑是标注按新类别重新导出过一次只覆盖了部分文件结果一部分txt是旧格式。我没耐心逐张比对直接按主文件名写校验循环cd datasets/ for f in images/train/*.jpg; do b$(basename $f .jpg) test -f labels/train/$b.txt || echo 缺失标签: $b done同样逻辑把 train 换成 val 再跑一遍。输出为空说明配对完整。这个脚本要塞进其他shell里也容易改把路径换掉就行。跑完我还习惯统计 jpg 和 txt 里是否有重复主文件名凡是出现重复的YOLOV5 加载时只会保留最后一张多余的图等于白放还占着磁盘空间。3. 标签格式与可视化从归一化坐标到边界框绘制3.1 YOLO标签txt的一行是什么YOLOV5 的标签文件不是xml也不是json就是一行5个数的纯文本每行代表一个目标框2 0.487500 0.512500 0.095000 0.260000 0 0.650000 0.380000 0.120000 0.045000第一列是类别id从0开始对应 classes.txt 里的行号后面四列分别是归一化中心点x、中心点y、框宽、框高。所谓归一化是原始像素坐标除以图像的宽和高得到0到1之间的数。为什么要归一化因为YOLOV5内部会把所有输入图缩放到训练尺寸默认640×640如果标签是绝对像素一缩放就全失效归一化坐标跟分辨率解耦换训练尺寸不用改标签。换算关系是x_center (x_left x_right) / 2 / image_widthwidth (x_right - x_left) / image_widthy方向同理。原始标注如果是左上角加宽高的格式比如VOC的xml转YOLO格式就按这个公式做除法。遇到宽度或高度算出来为0或者大于1的情况说明原标注有问题得回到源图查。3.2 项目自带可视化脚本的解读这份资源附带的py文件作用是传到一张图片就绘制边界框并保存无需改脚本直接运行。我自己重写了一个等价版本方便讲逻辑内容一样只是CLASSES要按你实际的 classes.txt 顺序去改import cv2 import os import random IMG_DIR datasets/images/train LABEL_DIR datasets/labels/train OUT_DIR vis_out CLASSES [vertical_crack, transverse_crack, pothole, irregular_crack] # 按classes.txt顺序改 os.makedirs(OUT_DIR, exist_okTrue) imgs [f for f in os.listdir(IMG_DIR) if f.endswith(.jpg)] pick random.choice(imgs) # 随机抽一张图 img cv2.imread(os.path.join(IMG_DIR, pick)) h, w img.shape[:2] label_path os.path.join(LABEL_DIR, pick.replace(.jpg, .txt)) with open(label_path, encodingutf-8) as fh: lines fh.read().strip().splitlines() colors [(0, 0, 255), (0, 255, 0), (255, 0, 0), (0, 255, 255)] for line in lines: parts line.split() cid int(parts[0]) xc, yc, bw, bh map(float, parts[1:]) # 归一化坐标换算回像素画框必须乘回去 x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[cid], 2) cv2.putText(img, CLASSES[cid], (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[cid], 2) cv2.imwrite(os.path.join(OUT_DIR, pick), img) print(saved:, os.path.join(OUT_DIR, pick))逻辑拆开看先用 random.choice 从训练集随机选一张jpg然后用同名txt找到标签读txt每一行把归一化坐标乘回图像宽高算出左上角和右下角像素坐标再画矩形。putText 顺手把类别名画上去方便人眼确认框对不对。要改的地方主要有三个CLASSES 列表必须和 classes.txt 一致否则图上类别名显示错乱LABEL_DIR 换验证集就改成 val颜色列表只有4组多类别场景要扩展成循环取色。图像宽高不要写死用 img.shape 现取换数据集也能跑。3.3 批量质量检查越界框、空标签、类别越界单张可视化只能发现偶发问题要检查整个数据集健康度还得批量统计。我每次拿到带框数据都会跑一个严格模式脚本把三类致命问题一次性扫出来坐标越界归一化值小于0或大于1、标签类别id超过类别总数、txt里出现空文件或一行少于5个字段import os BAD_FILES [] for split in [train, val]: label_dir fdatasets/labels/{split} for f in os.listdir(label_dir): if not f.endswith(.txt): continue path os.path.join(label_dir, f) lines open(path, encodingutf-8).read().strip().splitlines() if not lines or len(lines) 0: BAD_FILES.append(f{split}/{f} 空标签) continue for i, line in enumerate(lines): parts line.split() if len(parts) ! 5: BAD_FILES.append(f{split}/{f} 第{i1}行字段数不对) continue cid int(parts[0]) if cid 0 or cid 4: BAD_FILES.append(f{split}/{f} 类别id越界: {cid}) for v in parts[1:]: val float(v) if val 0 or val 1: BAD_FILES.append(f{split}/{f} 坐标越界: {v}) print(问题文件数量:, len(BAD_FILES)) for item in BAD_FILES[:50]: print(item)这个脚本跑完如果零输出基本可以认定标签在语法层面是干净的。但要注意它只检查格式和取值范围不检查语义——比如框偏了半个目标脚本看不出来那种错误只能靠可视化抽查。我一般对每个类别单独抽5张看一眼再开始训练这步省不得等训完再发现标签错位返工成本高得多。4. 训练前的避坑清单五个常见错误的排查记录4.1 现象训练刚启动就提示 no labels found 或 Found no valid images训练日志里刷出WARNING: No labels found in ...或者加载数据时直接报Found no valid images多数情况不是数据集坏了是 data.yaml 路径写错。我 ls 目录看文件都在但YOLOV5就是加载不到。原因data.yaml 里 train/val 是绝对路径或相对路径算错了按路径去 images 目录找不到图标签自然无从加载。解决打开 data.yaml把 path 写成数据集所在目录train 和 val 写成相对 path 的子目录例如 path: /root/datasetstrain: images/trainval: images/val。改完再跑一次日志里会打印实际载入的图片数841/231 对得上就说明路径生效。4.2 现象可视化画框位置错乱或框特别小有人用OpenCV画框画出来的边界框全挤在图左上角。原因是拿txt里的归一化坐标直接当成像素坐标传给 cv2.rectangle画出来的全是在几百像素见方的小框。解决画框前必须乘回原图尺寸也就是代码里x1 int((xc - bw/2) * w)这一步。如果显示出来的框扁得离谱还要检查是不是用了 resize 后的图来显示原始比例的标签。这个坑在自写可视化脚本时几乎人人都会踩一次。4.3 现象mAP0.5 始终为 0 或 loss 收敛但验证集 AP 极低这个现象比较诡异训练 loss 一直掉但每个类别的 AP 都是0。排查下来最常见的原因是 data.yaml 里 names 顺序和 classes.txt 顺序对不上。比如标签里第0类是纵向裂纹names 里第0位却写的坑洞模型学的和评估的错位AP 自然归零。解决把 data.yaml 的 names 和 classes.txt 逐行对齐顺手确认 nc 字段等于4。这两个点固化了正常跑50个epoch就能看到AP曲线起来。另一个可能性是初始anchor不适配下一节单独说。4.4 现象细长裂纹和小坑洞漏检严重路面缺陷里细长裂纹最难搞归一化后宽可能只有0.01长却有0.8这种极端长宽比在默认anchor集合里没有对应物。常见现象是横向裂纹AP能到0.8纵向裂纹只有0.3。原因YOLOV5默认anchor偏向通用目标的方形框。解决训练命令里不要关掉anchor自动调整YOLOV5每轮会在训练前几十个batch自动重聚类anchor如果用了--noautoanchor就得手工把anchor改小。我一般先用默认autoanchor跑一版再看runs/train/exp里的anchor分布图确实不匹配就手工填一组小anchor配合 hsv 增强和 mosaic对裂纹这类小目标有明显帮助。4.5 现象验证集 mAP 不错但实际摄像头测试一塌糊涂这算是最容易误判的坑。数据上训出mAP0.5有0.6以上部署到实地却漏检。原因往往是训练图和实测图光照、纹理差异太大而841张训练图覆盖的场景太窄。解决不要只在val上看指标把训练集外的真实路面图哪怕手机拍的放一批进val目录做外场验证数据增强里的亮度、对比度、模糊度也可以拉大一点。这份数据74MB不算大迁移到实际场景之前最好补充一批自己场景的图后面我会讲怎么低成本扩展。5. 进阶先跑30个epoch验收数据集再把标签平滑迁移到YOLOV85.1 10分钟内确认数据集是否能正常训练正式跑长训练之前先压到30个epoch用yolov5s小模型、小batch快速过一遍python train.py --data data.yaml --weights yolov5s.pt --epochs 30 --batch-size 16 --imgsz 640看三条曲线loss下降是否平滑验证集mAP是否在10个epoch后开始抬头precision/recall有没有剧烈抖动。如果训练启动报错大概率是路径或格式问题回到第4章逐条排查。这个30epoch的小跑还有一个额外作用它会生成 runs/train/exp 里的结果图和混淆矩阵后续分析都用它当素材。5.2 标签迁移到YOLOV8完全复用同一份txtYOLOV8对数据集格式的约定和YOLOV5基本一致imageslabels、归一化txt差别只在data.yaml写法。新建一个 yolo8_data.yamlpath: /root/datasets train: images/train val: images/val nc: 4 names: [vertical_crack, transverse_crack, pothole, irregular_crack]然后一行命令开训yolo detect train datayolo8_data.yaml modelyolov8s.pt epochs100 imgsz640。这里有个小提醒YOLOV8里配置文件对 names 的缩进敏感多行 names 必须逐个换行列写成一行数组会报 schema 校验错误。格式不对时错误信息会带行号对着改就行。同一份标签txt两边通用这是当初选YOLOV5目录格式最大的好处。5.3 数据扩展的便宜做法图像切片加自动标注初筛只有841张训练图花式增强很快到天花板。我的习惯是把原始拍摄的大图切成600×600滑动窗口切成几十张小图后先甩进刚训好的模型预测一遍把置信度大于0.4的框自动转成标签人工删掉明显错的再合并回数据集重训。这一步的产出是这份数据给我最大的心得路面缺陷场景预标记再删错比从头画框省至少一半时间代价是系统性的误判会成为新噪声所以每批自动标签都保留置信度字段方便后续回溯。从那以后我每次拿到新数据集都强制先走一遍可视化脚本加配对校验再决定要不要碰训练。数据集的坑从来不是模型报错那种显性错误更多是标签错位这类隐形问题白等一个晚上才发现成本太高。这篇拆包笔记如果能让你的第一次训练少踩几个坑希望帮到你。本文还有配套的精品资源点击获取
返回列表