ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

墙面缺陷检测数据集:5737张VOC与YOLO双格式实战指南

2026/9/23 17:34:25 拓冰建站 浏览量
墙面缺陷检测数据集:5737张VOC与YOLO双格式实战指南 简介本资源为墙面缺陷检测数据集面向从事建筑外墙病害识别、结构健康监测及计算机视觉目标检测的开发者与研究人员可用于训练YOLO系列或VOC格式的目标检测模型解决墙面裂缝、剥落、锈迹等病害自动定位问题。压缩包共2000个文件以1999个xml标注文件和1个说明txt为主另含对应jpg图片与YOLO格式txt标签整体约143.08MB目录分为图片、xml、txt三类便于直接接入主流检测框架。数据集共5737张清晰图片已做约60%增强标注7类缺陷外露钢筋、分层、裂缝、剥落、脱落、锈迹、潮湿总框数达15733个其中裂缝4513框、外露钢筋3673框、锈迹2550框类别分布较均衡。目前已有665人学习下载适合需要真实墙面病害样本、快速构建检测基线或扩充训练集的中高级视觉开发者参考使用。1. 墙面缺陷检测数据集5737 张已增强样本VOC 与 YOLO 双格式怎么落地拿到一份标注好的墙面缺陷数据集最怕的不是数据量不够而是格式对不上、标签名看不懂、增强之后分布偏了。这份资源给的是 5737 张 jpg 图片配套 5737 个 xml 和 5737 个 txtVOC 与 YOLO 两套标注一一对应标签分 7 类总框数 15733。标签名是意大利语像 Fessura裂缝、Spalling剥落、Umidita潮湿这些做建筑外立面巡检、老旧小区改造评估、桥梁隧道表面病害识别的团队会直接用到。它适合两类人一类是想快速跑通 YOLO 训练流程、不想从零打标的工程师另一类是手里有检测模型、需要一批带增强的墙面病害数据做迁移学习或消融实验的研究者。下面按「数据长什么样 → 怎么转怎么训 → 坑在哪 → 怎么验证」的顺序拆开讲。2. 数据解剖7 类标签的分布、增强痕迹与格式对应关系2.1 标签体系与框数分布先把 7 个类别的框数摆出来因为这直接决定训练时要不要做类别平衡。原始统计如下标签名含义意译框数Fessura裂缝4513Armatura in vista钢筋外露3673Tracce di ruggine锈迹2550Spalling剥落2004Umidita潮湿1748Delaminazione分层/起皮1005Scaling鳞片状剥落240Fessura 和 Armatura in vista 占了总框数的一半以上Scaling 只有 240 个框差了将近 19 倍。这种长尾分布如果直接丢给 YOLOv8 默认配置小类召回率会很难看。常见做法是在 data.yaml 里给 Scaling 和 Delaminazione 加权或者用 copy-paste 增强补样本。注意这份数据已经做过约 60% 的增强增强手段大概率是翻转、旋转、亮度调整这类几何与光度变换所以不要再无脑叠加同类增强否则小类过拟合会更严重。2.2 VOC 与 YOLO 的字段映射VOC 的 xml 里每个目标是一个object包含name和bndbox的 xmin/ymin/xmax/ymax坐标是绝对像素值。YOLO 的 txt 每行是class_id cx cy w h全部归一化到 0~1。两者数量都是 5737说明是一一对应的没有漏标。验证对应关系可以用下面这段脚本跑一遍就能确认图片、xml、txt 三者文件名是否对齐import os img_dir JPEGImages xml_dir Annotations txt_dir labels imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(.jpg)} xmls {os.path.splitext(f)[0] for f in os.listdir(xml_dir) if f.endswith(.xml)} txts {os.path.splitext(f)[0] for f in os.listdir(txt_dir) if f.endswith(.txt)} print(图片数:, len(imgs), xml数:, len(xmls), txt数:, len(txts)) print(图片有但xml缺:, imgs - xmls) print(xml有但txt缺:, xmls - txts)这段代码只做集合差集不依赖任何第三方库。如果输出三个集合都为空说明命名规范统一可以直接进入转换或训练。如果有缺失优先检查是不是增强时只复制了图片没复制标注——这是增强流程里最常见的翻车点。2.3 增强数据的识别与去重约 60% 的增强意味着原始图大约 3500 张左右增强后到 5737。增强图通常和原图共享前缀或后缀比如sl_images880和sl_images880_flip。但这份数据的文件名是纯数字编号看不出增强标记。判断方法有两个一是用感知哈希pHash找近似重复图二是看同一场景是否出现多张角度/亮度略有差异的图。我一般会先跑一遍 pHash把汉明距离小于 5 的图对挑出来人工抽查确认是增强副本还是真实不同样本。如果增强副本过多训练集和验证集之间会泄漏mAP 虚高。import imagehash from PIL import Image import os hashes {} for f in os.listdir(JPEGImages): if f.endswith(.jpg): h imagehash.phash(Image.open(os.path.join(JPEGImages, f))) hashes[f] h names list(hashes.keys()) for i in range(len(names)): for j in range(i1, len(names)): if hashes[names[i]] - hashes[names[j]] 5: print(疑似重复:, names[i], names[j])imagehash需要 pip 安装phash对亮度变化不敏感适合检测增强副本。汉明距离阈值 5 是经验值阈值越低越严格。跑完如果发现大量重复对划分数据集时要把重复组整体分到同一侧不能随机分。3. 从 VOC 到 YOLO转换脚本、data.yaml 与训练参数3.1 转换脚本与类别映射虽然压缩包里已经给了 YOLO 格式的 txt但如果你要自己重新划分数据集、或者想把意大利语标签换成中文/英文还是得会写转换。下面这个脚本把 VOC xml 转成 YOLO txt同时支持类别名重映射import xml.etree.ElementTree as ET import os # 原始类别名到新类别名的映射按需修改 name_map { Armatura in vista: rebar_exposed, Delaminazione: delamination, Fessura: crack, Scaling: scaling, Spalling: spalling, Tracce di ruggine: rust, Umidita: moisture } classes list(name_map.values()) class_to_id {c: i for i, c in enumerate(classes)} def convert(xml_path, txt_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in name_map: continue cid class_to_id[name_map[name]] bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cid} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines))关键参数是img_w和img_h必须和图片实际分辨率一致。VOC xml 里通常有size节点可以直接读不要硬编码。类别映射表决定了最终 data.yaml 里的 names 顺序一旦训练开始就不能改否则类别 ID 全乱。转换后建议抽查几张用 PIL 把框画出来肉眼确认。3.2 data.yaml 与训练命令YOLOv8 的 data.yaml 结构如下路径按实际目录改path: /data/wall_defect train: images/train val: images/val test: images/test names: 0: rebar_exposed 1: delamination 2: crack 3: scaling 4: spalling 5: rust 6: moisture训练命令用 YOLOv8n 先跑基线确认流程通再换大模型yolo detect train \ data/data/wall_defect/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/wall \ namebaselineimgsz640是默认值如果墙面缺陷目标很小比如细裂缝可以提到 1024但显存要够。patience20表示 20 轮没提升就早停避免过拟合。lr00.01是 SGD 的初始学习率用 AdamW 的话可以降到 0.001。训练完看runs/wall/baseline/results.csv重点看 mAP50-95 和每个类别的 APScaling 那类大概率垫底。3.3 类别不平衡的处理针对 Scaling 只有 240 个框的问题有三个可操作的方向。第一在 data.yaml 同级目录放一个hyp.yaml调cls损失权重但 YOLOv8 默认不直接暴露类别权重需要改源码或改用focal_loss。第二训练时用copy_paste0.3增强小类YOLOv8 内置支持。第三最直接的办法把 Scaling 和 Spalling 合并成一个大类「剥落类」因为两者在视觉上都是表面材料脱落合并后框数 2244分布立刻健康。合并与否取决于你的业务是否要求区分鳞片状和块状剥落如果只是做病害区域定位合并完全可接受。4. 避坑与排查标注、增强、训练里的五个血泪教训4.1 现象训练 loss 正常但 mAP 极低原因通常是类别 ID 和 data.yaml 的 names 顺序不一致。VOC 转 YOLO 时如果按字母序排类别而 data.yaml 按自定义顺序写ID 就错位了。解决转换脚本里显式定义class_to_id生成后随机抽 10 张图用labelImg或cv2画框核对类别名和框位置是否匹配。4.2 现象验证集 mAP 比训练集还高这是数据泄漏的典型信号。增强图被同时分到训练集和验证集模型在验证集上看到了训练时的近似副本。解决划分前先做 pHash 去重把相似图归组按组划分。如果已经划分了用sklearn的GroupShuffleSplit按组 ID 重新分。4.3 现象Scaling 类 AP 始终为 0240 个框分到训练集可能只剩 180 个再经过 dataloader 的随机裁剪某些 epoch 里一个 Scaling 样本都没有。解决要么合并类别要么在训练时设置oversample把含小类的图片重复采样。YOLOv8 可以通过自定义 sampler 实现简单点就直接复制小类图片到训练集但要注意验证集不能复制。4.4 现象xml 解析报错not well-formed部分 xml 里可能有非法字符或编码问题尤其是意大利语标签名带重音符号时。解决用lxml替代xml.etree或者在解析前用iconv统一转 UTF-8。批量检查可以用xmllint --noout *.xml报错的文件单独处理。4.5 现象增强后图片和标注不对应增强时只对图片做了旋转xml 里的框没跟着转导致框位置全错。解决如果要用自己的增强流程必须用支持同步变换标注的库比如albumentations的BboxParams。这份数据已经增强过直接用现成的 txt 即可不要再自己叠一轮几何变换。5. 验证与进阶用混淆矩阵和单类 AP 反推数据质量训练跑完不是看一个 mAP 就结束。我习惯先拉混淆矩阵看哪两类在互相误判。墙面缺陷里 Delaminazione 和 Spalling 容易混Umidita 和 Tracce di ruggine 在低分辨率下也难分。YOLOv8 训练完会自动生成confusion_matrix.png重点看非对角线上的数值。如果 Delaminazione 有 30% 被判成 Spalling说明这两类的视觉特征在 640 分辨率下不够区分要么提高输入分辨率要么合并。然后逐类看 AP。用yolo detect val加--verbose可以输出每类 APyolo detect val \ modelruns/wall/baseline/weights/best.pt \ data/data/wall_defect/data.yaml \ imgsz640 \ verboseTrue输出里crack的 AP 通常最高因为裂缝特征明显、样本多。scaling的 AP 如果低于 0.1基本可以判定这类在当前数据量下不可用考虑合并或放弃。我一般会设一个阈值单类 AP 低于 0.15 且框数少于 300 的直接合并到语义相近的大类不硬撑。还有一个容易被忽略的验证点把模型放到实际墙面图片上跑一遍看置信度分布。如果大量框的置信度集中在 0.25~0.35 之间说明模型没学到稳定特征可能是增强过度导致类内方差太大。这时候回退到原始未增强的子集重新训练往往比继续调参有效。从那以后我每次拿到标注数据集都强制先跑一遍文件名对齐、pHash 去重、类别分布统计这三步再开始写训练脚本。这三步花不了半小时但能省掉后面几天反复排查的功夫。希望帮到你。本文还有配套的精品资源点击获取