
简介面向墙面与水泥路面裂缝检测任务的目标检测数据集提供Pascal VOC与YOLO两种格式的标注文件标注类别统一为crack合计11741个矩形框适合计算机视觉学习者、算法工程师快速开展裂缝检测模型的训练、验证与调优适用于智慧交通、建筑质检等场景。资源包内含约2000个文件主要文件类型为XML标注文件与TXT说明文件压缩包大小约622.83MB整体紧凑便于本地下载与迁移使用。已有388人学习。数据集由labelImg工具标注矩形框准确贴合裂缝区域类别单一、标签文件与图像对应关系明确可直接接入YOLO与VOC系列检测框架同时提供说明文件辅助理解标注规范与目录结构省去格式转换和整理成本数据集仅提供准确且合理的标注不附带模型权重文件方便使用者专注于数据清洗、增强与模型迭代。1. 墙面水泥路面裂缝检测数据集8678张图只标一个类别为什么反而更难训墙面水泥路面裂缝检测数据集是一份纯监督训练底料8678张真实墙面与水泥路面jpg图像每一张都有对应的VOC格式XML和YOLO格式TXT标注文件目标类别只有crack裂缝合计11741个矩形框全部由labelImg人工框出。目标检测圈子里这种「单类别、矩形框、数量过万」的数据集看似门槛低实际训练时反而比多类任务更容易踩坑——裂缝是典型的细长目标宽高比极端标注框尺度跨度大类别又只有一种模型稍不注意就收敛到「背景全判负」的假阴性状态。如果你正在做裂缝检测相关的毕业设计、路面巡检项目或者想用YOLO系列完整跑通「数据集→训练→验证」流程这份资源可以直接拿来做模型底料省掉爬图、清洗、标注三个最耗时间的环节。2. 先拆数据格式VOC的XML与YOLO的TXT如何对应同一批裂缝标注2.1 文件清单与三方对齐关系解压这份数据集后目录里存在三种核心文件jpg图片、xml标注、txt标注文件名主体完全相同只是扩展名不同。从文件列表能看到xyxr_images_4227.xml、xyxr_images_5004.xml这类命名规律对应的图片实体就是xyxr_images_4227.jpgtxt就是xyxr_images_4227.txt。这种「同名不同后缀」的组织方式是最常见的LabelImg导出结构也是YOLO系列训练时最容易因为文件名不匹配而翻车的地方。文件类型命名规则作用jpgxyxr_images_编号.jpg原始图像训练输入xmlxyxr_images_编号.xmlPascal VOC标注含类别名与绝对坐标txtxyxr_images_编号.txtYOLO标注含类别ID与归一化坐标我拿到任何数据集的第一件事永远是核对三件套数量是否一致本数据集摘要明确写了jpg 8678个、xml 8678个、txt 8678个三方数量完全对齐说明不是半成品。但注意这里说的txt是纯YOLO检测格式不包含分割路径——也就是说这份数据不能直接喂给YOLOv8-seg这类实例分割模型它只服务于目标检测任务。2.2 解析VOC格式XMLobject与bndbox是唯一有效标注用文本编辑器打开任意一个xml文件结构非常标准。以xyxr_images_4227.xml为例核心内容如下annotation folderxyxr_images/folder filenamexyxr_images_4227.jpg/filename size width960/width height540/height depth3/depth /size object namecrack/name bndbox xmin120/xmin ymin80/ymin xmax340/xmax ymax210/ymax /bndbox /object /annotation重点是object里的两个子项name是类别名本数据集只有crackbndbox是矩形框的绝对像素坐标。坐标原点在图像左上角x向右增大y向下增大xmin/ymin是左上角点xmax/ymax是右下角点。这个坐标体系与OpenCV和PIL完全一致做可视化或裁剪时不需要任何变换。如果你怀疑某个xml标注有问题可以用一段小脚本快速统计每个xml里的框数量确认是否与摘要的11741个总框数吻合import xml.etree.ElementTree as ET import glob xml_files glob.glob(*.xml) total_boxes 0 for f in xml_files: tree ET.parse(f) root tree.getroot() boxes root.findall(.//object) total_boxes len(boxes) if len(boxes) 0: print(f发现空标注文件: {f}) print(fxml文件数: {len(xml_files)}, 总框数: {total_boxes})这里用findall(.//object)是因为有些xml会嵌套annotation直接取对象标签更保险输出空标注文件能提前发现漏标问题。摘要写了总框数11741、xml数8678跑完脚本如果对不上说明文件里有空xml或冗余标注需要先清理再训练。2.3 YOLO格式TXT换算归一化坐标与类别IDYOLO的txt标注和VOC完全不是一套坐标系。每行表示一个目标格式为类别ID x_center y_center width height其中x_center、y_center、width、height全部是相对于图片宽高的比值取值在0到1之间。例如xml里xmin120、xmax340、图片宽960那么归一化中心x就是(120 340) / 2 / 960 ≈ 0.2395。对应上面的xmltxt内容应该是0 0.239583 0.268519 0.229167 0.240741第一个0代表类别ID因为只有一个crack类所以恒为0。如果你在txt里看到其他数字比如1或2那多半是类别编号错位问题后面避坑章节会细说。完整转换脚本在YOLO训练前经常要用到我一般这样写import os import xml.etree.ElementTree as ET def xml_to_yolo(xml_path, out_dir, classes[crack]): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt lines [] for obj in root.findall(.//object): name obj.find(name).text if name not in classes: continue cls_id classes.index(name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines))这段脚本的核心是坐标从绝对像素换算成比例值保留6位小数可以避免精度丢失。注意类别列表classes的顺序就是模型训练时类别ID的顺序如果以后要新增类别必须从0开始逐个排不能跳号。3. 训练前整理目录划分、标签校验与data.yaml配置一次到位3.1 划分train/val/test目录YOLO系列训练不认单目录平铺结构它要求按images/train、images/val、labels/train、labels/val分层组织而且图片和标签要在各自的根目录下保持相对路径一致。常见做法是按照8:1:1或8:2划分训练集和验证集测试集可以单独留一份做最后评估。我习惯用一段shuffle脚本做划分保证随机性import os import random import shutil random.seed(42) split_ratio {train: 0.8, val: 0.2} jpg_files [f for f in os.listdir(.) if f.endswith(.jpg)] random.shuffle(jpg_files) for name, ratio in split_ratio.items(): part jpg_files[:int(len(jpg_files) * ratio)] jpg_files jpg_files[int(len(jpg_files) * ratio):] for jpg in part: base os.path.splitext(jpg)[0] shutil.copy(jpg, fimages/{name}/{jpg}) shutil.copy(base .xml, fannotations/{name}/{base}.xml) shutil.copy(base .txt, flabels/{name}/{base}.txt)随机种子固定为42能让每次划分结果可复现这对对比实验很重要。划分后建议在train里放80%的数据、val放20%不要另立test目录因为验证集本身就是调参主力。如果你要提交论文或做精度报告可以再从train里匀出10%当test但日常训练迭代阶段不必。3.2 标签三方对齐校验防止「有图无标」和「有标无图」这是我最看重的步骤。从网上下载的数据集经常遇到某个jpg的xml存在但txt缺失或者反过来。这种文件一旦混进训练集轻则训练报错重则标签文件错位导致模型学到错误对应关系。写一个校验脚本强制检查#!/bin/bash for jpg in *.jpg; do base${jpg%.jpg} if [ ! -f ${base}.txt ]; then echo 缺失txt: ${base} fi if [ ! -f ${base}.xml ]; then echo 缺失xml: ${base} fi done这个脚本逐个检查jpg对应的txt和xml是否存在输出缺失清单。如果缺失数量不多我一般直接删除对应jpg宁缺毋滥如果缺失超过总文件的5%说明这数据集整理有问题要谨慎使用。用bash跑一次也就十几秒值得每次换数据集都养成习惯。3.3 编写crack.yaml配置YOLO训练需要知道类别名和数据集路径data.yaml是唯一入口path: /your/datasets/crack_detection train: images/train val: images/val nc: 1 names: 0: crackpath是数据集绝对路径建议直接用绝对路径相对路径经常因为工作目录不同而找不到数据。nc填1names列表顺序必须和txt里的类别ID一致——这里只有crackID恒为0。注意这个yaml不能放在images同级目录下否则会被模型误当成训练数据读入。4. 用YOLO训练裂缝检测基线参数与精度指标的实操判读4.1 单类检测为什么更考验参数大多数入门教程做的是80类COCO多类检测单类裂缝检测看似更简单实际恰恰相反。因为类别只有crack背景占绝对主导模型很容易学到「什么都预测成背景」就能拿到极低的loss——训练集里背景像素占比超过95%是常态。另一个特征是裂缝框的宽高比极端很多框长宽比超过10:1这种细长目标在常用anchor配置下匹配率很低你可能发现训练完精度不低但实际推理时漏检严重。这里要修正一个常见认知单类检测不能直接搬COCO预训练参数不调优跑完就完事必须在imgsz、batch、anchor分配策略上做针对性调整。4.2 一组可直接上手的基线训练命令用ultralytics系框架训练命令行参数可以直接覆盖大部分默认值yolo train datacrack.yaml modelyolov8n.pt epochs150 imgsz640 batch16 patience30 single_clsTrue逐项解释modelyolov8n.pt表示用nano规模的预训练权重做迁移学习小模型在单类任务上通常够用且训练快epochs150是因为裂缝数据集类别简单但需要足够轮次让细长特征收敛150轮比默认100轮多出50轮冗余patience30是早停耐心值连续30轮验证集mAP不涨就自动停防止过拟合single_clsTrue虽然数据里只有一个类但这个开关会强制模型忽略类别数差异对单类鲁棒性更好。如果显存比较紧张把batch降到8或者4同时开启梯度累积。显存只有6G的话推荐用yolov8n.yaml从头训练而不是加载预训练权重因为nano模型本身参数量小从零训单类也不难收敛。4.3 验证指标怎么判读mAP50与PR曲线训练结束后关注三个指标mAP50、mAP50-95、precision/recall。在裂缝检测这个场景里mAP50比mAP50-95更有参考价值——裂缝框本身是矩形框与真实裂缝形状重叠率天然不高mAP50-95偏低不代表模型不行。如果precision和recall失衡比如precision高但recall低说明模型极度保守很多裂缝没框出来反过来recall高precision低说明框得太泛把纹理噪声也当成裂缝。单类检测我一般优先保recall漏检裂缝在实际巡检中比误报更致命。现场最直观的检查方法是抽一批验证集图片做预测可视化yolo predict modelruns/detect/train/weights/best.pt sourceval_images预测输出图里能看到每个检测框的置信度重点看看细长裂缝能不能被完整框住以及有没有把水泥路面接缝误判成crack。这比单纯看loss曲线靠谱得多因为loss降得漂亮不代表细长目标真的被正确匹配了。5. 避坑排查标注错位、小目标漏检、显存溢出三个高频翻车点5.1 txt中的类别ID与训练配置不一致现象训练能正常启动loss也能降但验证时预测框全部被标成错误的类别或者某些框的置信度极低。原因txt文件里的类别ID与data.yaml的names列表顺序不对应。比如有工具把background也算成了一类导致crack的ID变成1而不是0。另一类情况是训练时没有设置single_clsTrue模型默认读coco.yaml的80类自己的数据类别ID直接冲突。解决先抽查一个txt文件的第一列数字确认全部是0然后再确认data.yaml的nc1、names0为crack。我一般直接用3.2节的校验脚本把全量txt的类别ID去重统计一遍看到有非0数字立刻排查来源。5.2 细长裂缝大量漏检模型只框出粗裂缝现象短粗裂缝检测效果好长且细的裂缝在置信度阈值调到0.25时依然检不出。原因裂缝宽高比极端金字塔特征图上细长目标的有效特征很少下采样倍数过高时甚至只剩几个像素宽这本质上是小目标检测问题在细长形态上的变种。解决先提高imgsz比如从640改成1024虽然训练时间增加但效果立竿见影如果显存不支持1024可以换yolov9c.pt这类带可编程梯度信息的模型架构再不行就上SAHI切片推理把图像切成小块分别推理再合并这是处理裂缝这类极端长宽比目标的通用解法。5.3 训练时CUDA out of memory报错在backward阶段现象forward能跑完一进入loss回传就显存溢出。原因batch_size设置过大或者imgsz调高后特征图显存占用翻倍backward阶段要保存中间梯度显存峰值出现在反向传播。解决降batch_size是首选16降到8、8降到4如果batch降到4仍溢出加梯度累积参数比如batch4 device0 rectTrue配合accumulate8等效于batch32但峰值显存低很多。另外把workers8降低到workers2能减少CPU到GPU的搬运开销有时也能缓解显存毛刺。5.4 xml里存在重复object标签导致框数虚高现象用脚本统计总框数和11291或更多和摘要说明的11741对不上。原因部分xml在标注过程中出现过多次保存object块被重复写入或者labelImg在编辑模式下一次拖框生成了两个相同坐标的bndbox。解决写脚本遍历每个object的bndbox坐标完全相同的坐标去重同时检查同一个xml里是否存在xminxmax这种逆序坐标一旦出现基本就是标注工具卡死产生的脏数据。去重后再跑一次统计直到和11741完全一致再进训练流程。6. 进阶用法用裂缝标注框做长度估算与像素占比统计很多人拿到数据集训完模型就结束了但裂缝检测的工程落地往往需要量化输出这条裂缝有多长、占比多少、严重等级怎么定。我在巡检项目里常用一个做法——利用矩形框本身做快速粗算不依赖分割模型。原理很简单裂缝框通常是细长的如果框的宽高比超过5:1说明裂缝主方向接近长边方向此时用矩形对角线长度近似裂缝实际长度误差在15%以内如果接近正方形说明裂缝是块状碎裂用面积替代长度更合理。脚本如下import cv2 import glob for xml_file in glob.glob(*.xml): tree ET.parse(xml_file) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) for obj in root.findall(.//object): box obj.find(bndbox) w float(box.find(xmax).text) - float(box.find(xmin).text) h float(box.find(ymax).text) - float(box.find(ymin).text) diag (w * w h * h) ** 0.5 if diag 200: print(f{xml_file}: 疑似主裂缝像素长度约 {diag:.1f}px)这个脚本的关键是把框的长边当作裂缝走向当框的对角线长度超过200像素时视为主裂缝输出像素长度。如果你想换算成物理长度需要在采集时记录每像素对应多少毫米一般是固定相机高度和焦距后标定一次。从那以后我每次做完检测都会强制走一遍这个粗算流程快速判断模型是否真的在框细长裂缝——如果一个trained模型输出的平均框宽高比明显偏离训练集的统计分布说明模型学歪了应该回到参数调整而不是继续堆轮数。希望这个思路对你有用。本文还有配套的精品资源点击获取