ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

墙面缺陷检测数据集5737张YOLO+VOC格式实战:训练、转换与避坑指南

墙面缺陷检测数据集5737张YOLO+VOC格式实战:训练、转换与避坑指南 简介本资源为墙面缺陷检测数据集面向从事建筑结构健康监测、计算机视觉目标检测的开发者与研究人员可用于训练YOLO系列或VOC格式的目标检测模型解决墙面病害自动识别与分类问题。压缩包共含2000个文件以1999个xml标注文件和1个说明txt为主整体约143.08MB图片、xml与txt分别存放于JPEGImages、Annotations、labels三个文件夹方便直接接入主流检测框架。数据集共5737张清晰图片已做约60%增强标注7类墙面缺陷外露钢筋、分层、裂缝、剥落、脱落、锈迹与潮湿总框数达15733个其中裂缝4513框、外露钢筋3673框、锈迹2550框类别分布较均衡。目前已有668人学习下载适合需要快速构建墙面缺陷检测基线、验证模型泛化能力或进行数据增强策略对比的读者参考使用。1. 墙面缺陷检测数据集5737 张已增强样本到底能解决什么问题拿到「数据集墙面缺陷检测数据集yolovoc格式5737张已增强.zip」这个标题第一反应不该是「有多少张」而是「这批数据能不能直接喂进训练脚本、训完能不能在真实墙面上跑出可用结果」。墙面缺陷检测属于工业质检里最典型的细长目标场景裂缝、空鼓、渗水、剥落、霉斑这几类缺陷在图像里往往只占几十个像素宽背景却是大面积纹理重复的涂料或瓷砖。5737 张已经做过增强的样本意味着你省掉了最耗时的采集和第一轮增广但也意味着你必须先搞清楚增强方式是否匹配你的检测目标——随机旋转对裂缝是增益对渗水区域可能是噪声。这个数据集同时提供 YOLO 和 VOC 两种标注格式本质上是把「训练」和「验证/迁移」两条路都铺好了。YOLO 格式适合直接进 ultralytics 系训练管线VOC 的 XML 适合做格式转换验证、跨框架迁移或者拿去做传统机器视觉方案比如 Halcon 那套 blob 分析的对照实验。适合谁用做建筑外墙巡检、隧道衬砌检测、室内墙面验收的算法工程师以及想找一个真实工业缺陷场景练手 YOLO 全流程的人。不适合谁想直接拿来做通用目标检测 benchmark 的因为墙面缺陷的类间差异和类内差异都跟 COCO 那套完全不是一回事。2. 先看清数据5737 张增强样本的目录结构与标注分布2.1 解压后应该先跑的三条统计命令不要急着写训练脚本。先把压缩包解开用三条命令把数据摸清楚文件数量、图像尺寸分布、标注框尺寸分布。这三项直接决定你后面 anchor 怎么设、输入分辨率怎么选、增强还要不要补。# 统计图像数量与格式分布 find ./dataset -type f \( -name *.jpg -o -name *.png -o -name *.jpeg \) | wc -l find ./dataset -type f -name *.jpg | wc -l find ./dataset -type f -name *.png | wc -l # 统计标注文件数量确认图像与标注是否一一对应 find ./dataset -type f -name *.txt | wc -l find ./dataset -type f -name *.xml | wc -l # 查看目录层级确认 images/labels 是否分离 tree -L 3 ./dataset逻辑说明第一条命令确认实际图像总数是否接近 5737增强后的数据集经常出现图像和标注数量对不上的情况尤其是做过 mosaic 或 copy-paste 增强的。第二条确认 YOLO 的 txt 和 VOC 的 xml 是否同时存在如果只有一种说明压缩包内可能只保留了一套。第三条看目录结构YOLO 训练要求 images 和 labels 目录平行且文件名一一对应VOC 则通常把 xml 和 jpg 放在同一级。参数说明-type f限定文件避免把目录算进去\( ... \)是 find 的多条件分组少了转义会报错。如果你的环境没有 tree用find ./dataset -maxdepth 3 -type d代替。2.2 用 Python 脚本统计标注框尺寸判断增强是否合理增强过的数据集最怕一件事随机裁剪把缺陷裁没了或者随机缩放把细裂缝缩成了几个像素。下面这段脚本统计每个标注框的宽高分布输出最小、最大和中位数。import os import glob import numpy as np # 修改为你的 labels 目录 label_dir ./dataset/labels/train widths, heights [], [] for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue # YOLO 格式: class x_center y_center width height (归一化) w, h float(parts[3]), float(parts[4]) widths.append(w) heights.append(h) widths np.array(widths) heights np.array(heights) print(f标注框总数: {len(widths)}) print(f宽度 min/median/max: {widths.min():.4f} / {np.median(widths):.4f} / {widths.max():.4f}) print(f高度 min/median/max: {heights.min():.4f} / {np.median(heights):.4f} / {heights.max():.4f}) print(f宽高比中位数: {np.median(widths / (heights 1e-6)):.2f})逻辑说明YOLO 格式的宽高是归一化值乘以图像边长才是像素尺寸。如果中位宽度低于 0.02即 640 输入下约 13 像素说明这批数据里细长缺陷占比很高训练时输入分辨率不能低于 640否则下采样到 P3 特征图后目标就消失了。宽高比中位数如果远大于 1 或远小于 1说明缺陷有明确的方向性anchor 或损失函数里的 aspect ratio 权重需要相应调整。参数说明len(parts) ! 5用来跳过空行或格式异常行1e-6防止除零。如果你的数据集类别数不是从 0 开始连续编号还需要额外统计 class id 分布确认没有越界类别。2.3 增强方式反推哪些增强对墙面缺陷是增益哪些是噪声已增强的数据集不会告诉你它用了哪些增强。但你可以通过观察图像对来反推如果同一处墙面出现多张视角、亮度、尺度不同的图大概率做了随机旋转、亮度抖动、缩放裁剪。对墙面缺陷来说水平翻转通常是安全的垂直翻转要谨慎——裂缝的走向有物理意义上下翻转后可能变成现实中不存在的形态。随机旋转 90 度对空鼓和剥落是增益对细长裂缝可能引入不自然的断裂。我的习惯是拿到增强数据集后先按 8:2 切训练验证用原始未增强的图做一次验证集再用增强图做一次对比 mAP 差异。如果增强集 mAP 反而低说明增强方式引入了分布偏移需要手动筛掉一部分。3. YOLO 格式训练从 data.yaml 到第一次收敛的完整命令3.1 目录重组与 data.yaml 的正确写法YOLO 训练对目录结构有硬性要求images 和 labels 必须平行且文件名除扩展名外完全一致。很多压缩包解压后是JPEGImages和Annotations这种 VOC 风格需要先转换。# 假设解压后是 VOC 风格先重组为 YOLO 风格 mkdir -p yolo_dataset/images/train yolo_dataset/images/val mkdir -p yolo_dataset/labels/train yolo_dataset/labels/val # 将 jpg 复制到 imagesxml 转换后的 txt 放到 labels # 这里假设你已经有了转换脚本输出到 labels 目录 cp ./dataset/JPEGImages/*.jpg yolo_dataset/images/train/data.yaml 的写法直接决定类别映射是否正确# data.yaml path: ./yolo_dataset train: images/train val: images/val nc: 4 names: 0: crack 1: spalling 2: seepage 3: mildew逻辑说明path是数据集根目录train和val是相对路径。nc必须等于 names 的长度且 names 的索引必须和标注文件里的 class id 一致。墙面缺陷数据集常见的类别是裂缝、剥落、渗水、霉斑如果你的标注里还有空鼓或泛碱需要相应增加 nc 并调整 names。参数说明如果验证集和训练集在同一目录下用不同 txt 文件划分val可以写成images/val或直接指向一个 txt 列表文件。不要用绝对路径换机器后容易翻车。3.2 训练命令与关键超参imgsz、batch、lr0 怎么定yolo detect train \ data./data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ device0 \ project./runs/wall_defect \ nameexp01逻辑说明imgsz640是墙面缺陷的底线如果 2.2 节统计出中位宽度低于 0.02建议提到 960 或 1280。batch16是 8G 显存下的保守值显存够可以翻倍。lr00.01是 SGD 的常规起点如果用 AdamW 要降到 0.001。patience30表示 30 轮无提升就早停墙面缺陷数据量不大容易过拟合早停能省时间。参数说明lrf是最终学习率因子lr0 * lrf是末端学习率。device0指定第一块 GPUCPU 训练把 device 设为 cpu。project和name决定权重保存路径建议按实验编号管理不然跑多了找不到哪个是哪个。3.3 训练日志怎么看loss 曲线与 mAP 的对应关系训练开始后重点盯三个指标box_loss、cls_loss、mAP50。box_loss 下降但 mAP 不涨通常是标注框质量问题cls_loss 震荡可能是类别不平衡或学习率过大。墙面缺陷里裂缝样本往往远多于霉斑如果 cls_loss 一直下不去需要在 data.yaml 里加类别权重或者对少样本类做过采样。验证集 mAP50 在 0.5 以上算可用0.7 以上算不错。但墙面缺陷检测的验收标准不是 mAP而是漏检率。裂缝漏一条可能意味着整面墙要返工所以 recall 比 precision 更重要。训练时可以把conf阈值调低到 0.15 看 recall 上限再根据实际业务定阈值。4. VOC 格式的用法转换、校验与跨框架迁移4.1 VOC 转 YOLO 的脚本与四个边界坑虽然数据集同时提供两种格式但实际训练时往往需要从 VOC 转 YOLO或者反过来验证标注一致性。下面这个转换脚本处理了四个常见边界图像尺寸不一致、标注框越界、类别名映射缺失、空标注文件。import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射必须与 data.yaml 一致 class_map {crack: 0, spalling: 1, seepage: 2, mildew: 3} def voc_to_yolo(xml_path, img_path, out_path): tree ET.parse(xml_path) root tree.getroot() # 从图像实际尺寸读取不信任 xml 里的 size with Image.open(img_path) as im: iw, ih im.size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in class_map: continue # 坑1: 类别名不在映射表里跳过而不是报错 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 坑2: 标注框越界裁剪到图像范围内 xmin, xmax max(0, xmin), min(iw, xmax) ymin, ymax max(0, ymin), min(ih, ymax) if xmax xmin or ymax ymin: continue # 坑3: 裁剪后无效框丢弃 xc (xmin xmax) / 2 / iw yc (ymin ymax) / 2 / ih w (xmax - xmin) / iw h (ymax - ymin) / ih lines.append(f{class_map[name]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) # 坑4: 空标注文件也要写否则 YOLO 会当成背景图 with open(out_path, w) as f: f.write(\n.join(lines))逻辑说明坑1 是类别名拼写不一致比如 xml 里写 Crack 而映射表是 crack直接跳过会导致该图变成负样本。坑2 是标注框超出图像边界增强时旋转或裁剪容易产生这种框。坑3 是越界裁剪后宽高为负必须丢弃。坑4 是空标注文件YOLO 训练时如果 labels 目录下没有对应 txt会报错或当成背景显式写空文件更安全。参数说明class_map必须和 data.yaml 的 names 完全对应顺序也要一致。:.6f保留六位小数YOLO 官方推荐精度。4.2 用 VOC 标注做交叉验证确认增强没有破坏标注VOC 的 XML 保留了原始图像尺寸和标注框的绝对坐标适合用来校验增强后的 YOLO 标注是否偏移。做法很简单随机抽 50 张图把 YOLO 的归一化框还原成像素框和 XML 里的框对比 IoU。如果 IoU 低于 0.95说明增强过程中标注没有同步变换这批数据需要重新处理。def yolo_to_pixel(xc, yc, w, h, iw, ih): xmin (xc - w / 2) * iw ymin (yc - h / 2) * ih xmax (xc w / 2) * iw ymax (yc h / 2) * ih return xmin, ymin, xmax, ymax def iou(box1, box2): x1 max(box1[0], box2[0]) y1 max(box1[1], box2[1]) x2 min(box1[2], box2[2]) y2 min(box1[3], box2[3]) inter max(0, x2 - x1) * max(0, y2 - y1) area1 (box1[2] - box1[0]) * (box1[3] - box1[1]) area2 (box2[2] - box2[0]) * (box2[3] - box2[1]) return inter / (area1 area2 - inter 1e-6)逻辑说明这段代码只做校验不参与训练。如果发现某张图的 IoU 异常低先检查这张图是否被旋转过——旋转后 XML 的轴对齐框和 YOLO 的轴对齐框本来就不一致这种情况需要看增强时是否同步旋转了标注。如果没有同步这批增强图只能用于分类任务不能用于检测。参数说明1e-6防止除零。IoU 阈值 0.95 是经验值低于这个值就值得人工抽查。4.3 迁移到其他框架VOC 作为中间格式的注意事项如果你要把这批数据迁移到 MMDetection、Detectron2 或 PaddleDetectionVOC 是比 YOLO 更通用的中间格式。但要注意两点一是 VOC 的类别名是字符串迁移到 COCO 风格时需要建立 id 映射二是 VOC 的difficult字段在 YOLO 里没有对应如果原数据集标了 difficult转换时会丢失需要手动决定是否保留这些样本。5. 避坑与排查墙面缺陷检测训练中最容易翻车的五件事5.1 现象训练 loss 正常下降但验证集 mAP 始终为 0原因最常见的是 data.yaml 里的val路径写错YOLO 找不到验证集或者验证集 labels 目录为空。其次是类别 id 越界标注文件里的 class id 大于等于 ncYOLO 会静默跳过这些框。解决先跑yolo detect val data./data.yaml model./runs/exp01/weights/best.pt看输出里val的图片数量是否为 0。如果是 0检查路径如果不是 0 但 mAP 为 0用 2.2 节的脚本统计 class id 分布确认没有越界。5.2 现象模型在验证集上表现很好但实际墙面图片漏检严重原因增强数据集里的图像和真实巡检图像存在域偏移。增强可能引入了不自然的纹理或亮度模型学到了增强伪影而不是缺陷特征。另外验证集如果也是从增强集里切的等于在测同分布数据指标虚高。解决留出一批完全未增强的原始图做测试集不要参与训练。如果原始图 mAP 比增强验证集低 20 个点以上说明增强方式有问题需要减少几何增强的强度或者用原始图做微调。5.3 现象细长裂缝被检测成多个短框或者框明显偏移原因YOLO 的 anchor 或损失函数对细长目标不友好。默认 anchor 是基于 COCO 聚类的墙面裂缝的宽高比可能达到 1:20 甚至更极端默认 anchor 覆盖不到。解决用 2.2 节的统计结果重新聚类 anchor或者改用 anchor-free 的模型如 YOLOv8 本身是 anchor-free但损失函数里的 aspect ratio 权重仍可调。另一个办法是提高输入分辨率让细裂缝在特征图上占更多像素。5.4 现象训练到一半 loss 突然变成 NaN原因学习率过大或者某张图的标注框宽高为 0。增强过程中随机裁剪可能产生宽高为 0 的框YOLO 计算 loss 时除零导致 NaN。解决在数据加载前加一道过滤丢弃宽或高小于 1 像素的框。学习率从 0.01 降到 0.001 再试。如果用了混合精度训练NaN 概率会更高可以关掉 AMP 或加梯度裁剪。5.5 现象同一张图在不同训练轮次里检测结果跳变很大原因增强的随机性过大或者 batch size 太小导致 BatchNorm 统计量不稳定。墙面缺陷数据量不大如果 batch 只有 4 或 8BN 层的均值方差波动会很明显。解决增大 batch size或者改用 GroupNorm。如果显存不够用梯度累积模拟大 batch。另外检查增强里的随机旋转角度范围超过 ±30 度对裂缝检测通常弊大于利。6. 把 5737 张用到极致小样本类过采样与推理端阈值调优数据集里裂缝样本往往占大头霉斑、渗水这类少样本类容易被模型忽略。我的习惯是在训练前先统计每个类的实例数对少于总实例数 10% 的类做过采样。具体做法不是简单复制图像而是用WeightedRandomSampler给少样本图更高的采样权重。from torch.utils.data import WeightedRandomSampler import numpy as np # 假设 class_counts 是每个类的实例数 class_counts np.array([3200, 800, 400, 200]) class_weights 1.0 / class_counts class_weights class_weights / class_weights.sum() # 每张图的权重 它包含的类的权重之和 # 这里用简化逻辑按图的主类分配权重 image_weights [] for label_path in label_files: with open(label_path) as f: classes [int(line.split()[0]) for line in f if line.strip()] if not classes: image_weights.append(0.0) continue w sum(class_weights[c] for c in classes) image_weights.append(w) sampler WeightedRandomSampler(image_weights, num_sampleslen(image_weights), replacementTrue)逻辑说明class_weights与实例数成反比少样本类权重高。image_weights把一张图里所有类的权重加起来包含多个少样本类的图会被更频繁采样。replacementTrue允许重复采样。这个 sampler 直接传给 DataLoader 的sampler参数即可。参数说明num_samples通常设为数据集大小设太大会导致过拟合。如果某些图权重为 0空标注采样时会被跳过这是期望行为。推理端阈值调优是另一个容易被忽略的点。训练时的 mAP 是在默认 conf 阈值下算的但实际部署时漏检代价远高于误检。我的做法是在验证集上画 P-R 曲线找到 recall 达到 0.95 时的 conf 阈值通常比默认的 0.25 低不少。墙面缺陷检测里conf 设 0.1 到 0.15 往往能多召回 10% 到 15% 的缺陷代价是误检增加但误检可以靠后处理规则过滤——比如要求检测框面积大于某个阈值或者连续多帧出现才报警。最后说一个我踩过的坑不要用增强后的验证集去调阈值。增强图的分布和真实巡检图不一样调出来的阈值在真实场景里会偏。一定要留一批原始图做阈值标定哪怕只有 100 张。这个习惯帮我省过好几次返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表