☰
混凝土缺陷检测数据集:7513张VOC与YOLO双格式实战指南
2026/9/26 4:40:48 网站建设 项目流程

简介:这份混凝土缺陷检测数据集面向从事建筑结构健康监测、工业视觉缺陷识别的研究者与算法工程师,提供VOC与YOLO双格式标注,可直接用于目标检测模型的训练与验证。包内共2000个文件,以1999个xml标注文件和1个说明txt为主,压缩包约397.27MB,xml与配套txt分别对应VOC和YOLO两种标注体系,方便不同框架直接读取。数据集包含7513张jpg图片,每张均配有同名xml与txt标注,共标注40324个矩形框,覆盖可见裂斑、分层、风化、缝隙、剥落、脱落、锈迹7个类别,标注工具为labelImg,规则统一。目前已有713人学习下载,适合需要真实混凝土缺陷样本做模型微调、类别平衡分析或数据增强实验的读者,可省去自行采集与标注的成本,快速搭建可复现的检测基线。

1. 7513 张混凝土缺陷图,为什么值得单独拆一遍

手上有个做工程质检的朋友,前阵子接了个混凝土表面缺陷识别的活,甲方给了一批现场照片,让他两周内出个能跑的检测模型。他第一反应是去网上找开源数据集,结果要么是几百张的小样本,要么是类别对不上——裂缝、蜂窝、麻面这些混凝土常见缺陷,很多通用数据集根本不覆盖。后来他拿到这份 7513 张、7 类别的混凝土缺陷数据集,VOC 和 YOLO 两种标注格式都齐了,才算把训练流程跑通。

这份资源的核心价值在于「双格式 + 中等规模 + 垂直场景」。7513 张图在缺陷检测里不算大,但胜在类别聚焦,7 个类别基本覆盖了混凝土表观检测的高频缺陷类型。VOC 格式给的是 XML 标注,YOLO 格式给的是归一化后的 txt 坐标,两种格式意味着你不用自己写转换脚本,直接对接不同框架就行。适合谁用?做土木工程智能化检测的、搞工业质检算法验证的、以及想拿真实缺陷数据练手 YOLO 训练流程的从业者。如果你只是想做通用目标检测刷指标,这份数据集的类别分布和场景单一性反而不适合你。

2. 拆开压缩包:VOC 与 YOLO 双格式到底怎么对应

2.1 两种标注格式的文件结构差异

拿到 .7z 压缩包,解压后一般会看到两个平行目录,一个放 VOC 格式,一个放 YOLO 格式。VOC 格式的典型结构是Annotations存 XML、JPEGImages存原图、ImageSets/Main存训练验证划分文件。每个 XML 里记录了图片尺寸、缺陷目标的边界框坐标(xmin、ymin、xmax、ymax)和类别名。YOLO 格式则简单得多,每张图对应一个同名 txt,每行是class_id x_center y_center width height,坐标全部归一化到 0 到 1 之间。

这里有个容易翻车的点:VOC 的坐标是绝对像素值,YOLO 是归一化相对值。如果你拿 VOC 的 XML 直接喂给 YOLO 训练脚本,模型不会报错,但框会全错——因为 YOLO 期望的是 0 到 1 的小数,你给它几百的像素值,它内部一算就飞了。常见做法是写个转换脚本,读 XML 里的size节点拿到宽高,再做除法。这份数据集既然已经提供了 YOLO 格式,说明转换这一步已经做过了,你直接用 YOLO 目录就行。

2.2 类别映射与 data.yaml 配置

7 个类别在 YOLO 格式里是用 0 到 6 的整数表示的,具体哪个数字对应哪个缺陷名,得看数据集里附带的classes.txt或者data.yaml。我一般会先打开这个文件确认顺序,因为不同来源的数据集类别索引可能不一样。假设类别顺序是裂缝、蜂窝、麻面、露筋、孔洞、剥落、泛碱,那data.yaml就长这样:

# data.yaml path: ./concrete_defect_dataset # 数据集根目录 train: images/train # 训练集图片路径 val: images/val # 验证集图片路径 nc: 7 # 类别数 names: ['crack', 'honeycomb', 'pitting', 'exposed_rebar', 'hole', 'spalling', 'efflorescence']

这个文件是 YOLOv5/v8 训练时的入口配置。path指向解压后的数据集根目录,train和val是相对于path的子路径。nc必须和names列表长度一致,否则训练启动时会直接报错。我见过有人把nc写成 8 但names只给了 7 个,结果训练到一半 loss 变 NaN,排查半天才发现是类别数对不上。

2.3 用 Python 快速校验标注完整性

在正式开训之前,我习惯先跑一段校验脚本,确认图片和标注文件一一对应,没有空标注或者越界坐标。这一步能省掉后面训练时「某张图没有标签」的玄学报错。

import os from pathlib import Path img_dir = Path("./concrete_defect_dataset/images/train") label_dir = Path("./concrete_defect_dataset/labels/train") img_files = {p.stem for p in img_dir.glob("*.jpg")} label_files = {p.stem for p in label_dir.glob("*.txt")} # 找出有图无标签、有标签无图的情况 missing_labels = img_files - label_files missing_images = label_files - img_files print(f"图片总数: {len(img_files)}") print(f"标注总数: {len(label_files)}") print(f"有图无标签: {len(missing_labels)}") print(f"有标签无图: {len(missing_images)}") # 抽查标注文件,检查坐标是否在 0-1 范围内 for lbl in list(label_dir.glob("*.txt"))[:5]: with open(lbl) as f: for line in f: parts = line.strip().split() if len(parts) == 5: cls, x, y, w, h = parts coords = [float(x), float(y), float(w), float(h)] if any(c < 0 or c > 1 for c in coords): print(f"坐标越界: {lbl.name} -> {line.strip()}")

这段脚本做了两件事:第一,用集合差集找出图片和标注不匹配的文件;第二,抽查前 5 个标注文件,检查归一化坐标是否落在 0 到 1 之间。如果输出里「有图无标签」数量很大,说明数据集划分可能有问题,需要手动核对。坐标越界的情况在人工标注里偶尔出现,一般是标注员拖框时超出了图片边界,这种样本建议直接剔除或者重新标注。

3. 从零跑通 YOLOv8 训练:环境、参数与断点续训

3.1 Anaconda 环境配置与依赖版本锁定

YOLOv8 对环境的要求不算苛刻,但版本冲突是新手最容易卡住的地方。我一般用 Anaconda 建一个独立环境,避免和系统里的其他包打架。下面这套配置在 Windows 和 Linux 上都跑过,比较稳:

# 创建虚拟环境,Python 版本选 3.9 或 3.10 conda create -n concrete_yolo python=3.10 -y conda activate concrete_yolo # 安装 PyTorch,根据你的 CUDA 版本选对应命令 # CUDA 11.8 的情况 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics pip install ultralytics # 验证安装 yolo checks

yolo checks会输出当前环境的信息,包括 PyTorch 版本、CUDA 是否可用、以及 ultralytics 的版本号。如果 CUDA 显示不可用,但你有 NVIDIA 显卡,大概率是 PyTorch 装成了 CPU 版本,需要卸载重装对应 CUDA 的 wheel。我一般会锁定 ultralytics 的版本,比如pip install ultralytics==8.0.200,因为不同小版本之间 API 偶尔有变动,教程和实际代码对不上就很烦。

3.2 训练命令与关键参数含义

环境好了之后,一条命令就能启动训练。假设data.yaml放在数据集根目录,模型用预训练的yolov8n.pt:

yolo detect train \ data=./concrete_defect_dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=./runs/concrete \ name=exp1 \ resume=False

逐个说下关键参数。data指向刚才配好的 yaml 文件。model用yolov8n.pt是 nano 版本,参数量小、训练快,适合先跑通流程;如果精度不够再换yolov8s.pt或yolov8m.pt。epochs=100是训练轮数,7513 张图在单卡上大概几个小时能跑完。imgsz=640是输入分辨率,混凝土缺陷的裂缝有时候很细,如果显存够,可以提到 1024 试试,但训练时间会翻倍。batch=16根据显存调整,8G 显存跑 640 分辨率大概能到 16,不够就降到 8。patience=20是早停耐心值,验证集 loss 连续 20 轮不降就停,避免过拟合。resume=False表示从头训,如果中途断了想接着跑,把这里改成True并指定上次的project和name。

3.3 训练过程监控与断点续训

训练启动后,终端会实时打印每一轮的 box_loss、cls_loss、mAP50 等指标。我一般同时开一个 TensorBoard 看曲线:

tensorboard --logdir ./runs/concrete

重点盯三个东西:box_loss是否稳定下降、mAP50是否在涨、以及验证集的cls_loss有没有反弹。如果box_loss降但mAP50不涨,可能是学习率太小或者数据标注质量有问题。如果cls_loss在后期突然往上走,说明过拟合了,早停这时候就该起作用。

断点续训的场景很常见——比如服务器被抢占、或者你手动停了想调参数。YOLOv8 会在runs/concrete/exp1/weights/下保存last.pt和best.pt。续训命令是:

yolo detect train resume model=./runs/concrete/exp1/weights/last.pt

注意resume后面直接跟模型路径,不需要再指定data和epochs,这些参数会从last.pt里自动读取。我踩过一次坑:手动改了data.yaml的路径后想续训,结果报错说找不到数据集,原因是last.pt里存的是旧的绝对路径。解决办法是把数据集挪回原路径,或者重新指定data参数覆盖。

4. 避坑与排查:标注、显存、类别不均衡的五个血泪教训

4.1 现象:训练 loss 正常但 mAP 始终为 0

原因:YOLO 格式的类别索引从 0 开始,但data.yaml里的names列表顺序和标注文件里的class_id对不上。比如标注里 0 代表裂缝,但names第一个写的是蜂窝,模型学出来的类别全错位。

解决:打开一个标注 txt,看第一列的数字分布,再对照classes.txt或data.yaml的names顺序,确保一一对应。如果不确定,干脆把names改成通用的['defect_0', 'defect_1', ...],先跑通再改回可读名称。

4.2 现象:训练到一半报 CUDA out of memory

原因:batch设太大,或者imgsz提太高。7513 张图里如果有几张分辨率特别大(比如 4000x3000),YOLO 在数据加载时虽然会 resize,但极端长宽比可能导致显存峰值飙升。

解决:先把batch降到 8 或 4,如果还爆,检查数据集里有没有异常大图,用脚本筛出来单独处理。另外可以开amp=True(自动混合精度),显存占用能降不少,但要注意某些老显卡对 AMP 支持不好,开了反而 loss 变 NaN。

4.3 现象:某些类别检测效果极差,mAP 个位数

原因:类别不均衡。7 个类别里,裂缝可能占了一半以上,而泛碱、剥落这种缺陷样本很少,模型见得太少,学不会。

解决:先统计每个类别的标注框数量,如果最少和最多差 10 倍以上,就得做数据增强或者重采样。常见做法是对少样本类别做离线增强(旋转、裁剪、加噪声),或者在训练时用copy_paste增强策略。YOLOv8 自带mosaic和mixup,但对极端不均衡帮助有限,还是得从数据层面补。

4.4 现象:验证集 mAP 很高,但拿现场新图测试全漏检

原因:数据集里的图片可能来自同一批拍摄条件(同一工地、同一光照、同一角度),模型过拟合了背景特征。换一个工地、换一种光照,分布偏移就暴露了。

解决:如果条件允许,留出一部分不同来源的图做测试集,不要全用来训练。另外可以在训练时加degrees、hsv_h、hsv_s等增强参数,提升对旋转和光照变化的鲁棒性。我一般会把hsv_h=0.015、hsv_s=0.7、hsv_v=0.4作为默认值,对混凝土这种纹理场景比较合适。

4.5 现象:标注框明显偏大或偏小,框住了整个墙面

原因:人工标注时偷懒,或者标注规范没统一。有的标注员把整块缺陷区域框进去,有的只框了缺陷最明显的一小块,导致同一类缺陷的框尺度差异巨大。

解决:训练前抽 20 张图可视化标注框,用cv2.rectangle画出来看一眼。如果发现框明显不合理,要么重新标注,要么在训练时用anchor聚类重新适配。YOLOv8 是 anchor-free 的,对框尺度没那么敏感,但太离谱的标注还是会拉低上限。

5. 进阶技巧:用混淆矩阵和置信度门限把误检压下去

训练跑完,runs/concrete/exp1/下会生成confusion_matrix.png和results.csv。混淆矩阵是排查类别混淆的利器——如果裂缝被大量预测成剥落,说明这两个类别的视觉特征在模型看来太像,要么合并类别,要么补更多区分性样本。我一般会先看矩阵对角线,对角线越深越好,非对角线上的高值就是重点优化对象。

置信度门限的调整是另一个实战技巧。YOLO 默认conf=0.25,但在混凝土缺陷检测里,漏检的代价往往比误检高——裂缝没检出来可能意味着结构安全隐患,而误检最多让人工复核一遍。所以我会把推理时的conf降到 0.15 甚至 0.1,先把召回率拉上去,再通过后处理过滤明显不合理的框。命令很简单:

yolo detect predict \ model=./runs/concrete/exp1/weights/best.pt \ source=./test_images \ conf=0.15 \ iou=0.5 \ save=True

iou=0.5是 NMS 的阈值,控制重叠框的合并程度。如果同一处缺陷被重复框了好几次,把iou调低到 0.3 到 0.4;如果相邻缺陷被误合并成一个,就调高到 0.6。这个参数没有绝对最优,得拿几张典型图试出来。

还有一个容易被忽略的点:验证集和测试集的划分。如果数据集自带的val划分是随机切的,可能同一张图的不同裁剪版本同时出现在训练和验证里,导致 mAP 虚高。我一般会按拍摄批次或者工地来源做划分,确保验证集里的图在训练时完全没见过。7513 张图的规模,按 8:1:1 切训练、验证、测试比较合理,如果类别不均衡严重,还得做分层抽样。

从那以后我每次拿到新数据集,都强制先跑一遍标注校验和类别统计,再开始配环境。这个习惯帮我省掉了至少三次「训练三天发现标签全错」的后悔药。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询