简介面向深度学习缺陷检测与YOLO目标检测入门者这份瓷砖缺陷数据集包含已标注图片与配套txt标签已按2类crack裂缝、normal正常划分并附类别说明文件classes.txt以及翻转、噪声等数据增强版本可直接用于瓷砖裂缝识别模型训练与验证。包内含2000个文件以txt标签文件为主1765个另有234张JPG图片及1个Python可视化脚本图片与标签分目录存放结构清晰压缩包整体91.75MB。附带可视化脚本无需修改参数即可运行随机传入一张图片便能绘制边界框并保存到当前目录方便快速检查标注质量与模型输出。已有193人学习适合正在做工业质检、表面缺陷检测相关课题或希望快速获得一份规范YOLO格式小规模数据集以开展实验的读者。1. 瓷砖裂缝检测一个“划分好的数据集”到底想帮你少踩多少坑质检流水线上盯瓷砖裂缝人眼看到第两百块就麻了换到外墙或管廊巡检光线、釉面反光还让裂缝更难找。用 YOLO 做瓷砖裂缝识别与检测如今是工业视觉里相当成熟的方向但这套“瓷砖裂缝识别检测2类”数据包的价值不在模型而在它把三件最磨人的事准备好了划分好的数据集、类别 class 文件、数据可视化脚本。很多新手拿到就开训开训前忘了先检查数据本身对不对翻车后才回来补课。这篇文章就围绕这三样东西展开讲清楚怎么用、参数怎么设、坑在哪适合做工业预研、做毕设、或者第一次完整跑通 YOLO 训练流程的人。2. 把数据集拆开看2类标注怎么定义、目录怎么划分、可视化脚本怎么检查2.1 裂纹和破损的边界为什么类别定义直接决定模型上限标题里的“2类”最常见的定义是裂纹crack与破损chip/break。裂纹是线状的、长宽比很高的缺陷像头发丝一样在釉面延伸破损是边缘崩落、缺角这类块状缺陷。两者在像素形态上差异明显但在实际照片里经常同时出现——一条裂纹延伸到瓷砖边缘会把釉面带崩一小块这时同一个框里既有线状特征又有块状特征。如果你用 labelimg 或者 labelme 标注最容易被忽略的是打标框的边界裂纹要贴着裂缝走向画别把灰缝、釉面纹理包进来破损框要覆盖整个崩落区域不要把背景裁掉一半。为什么要强调类别定义因为 YOLO 学的是“类别内部的共性”和“类别之间的差异”。如果标注的人把灰缝标成裂纹另一个人把裂纹标成灰缝训练集内部互相打架模型被迫在特征空间里找一条折中线结果就是 mAP 虚高、现场漏检。我一般建议拿到这种数据集后第一件事不是数有多少张图而是随机抽 50 张图逐一看标注框确认 class_id 和形态对得上。这个步骤我管它叫“数据体检”跑得快的话一刻钟能省掉后面一整天的排查时间。选型上瓷砖裂缝检测为什么主要用 YOLO 而不是传统图像处理传统方法靠 Canny 边缘检测加形态学闭运算在单一光源、固定角度下表现尚可但一到现场瓷砖纹理、灰尘、水渍全变成伪边缘阈值调到吐也调不出通用的。YOLO 这类 CNN 模型学的是语义特征对纹理和光照有一定鲁棒性而且从训练到部署的工具链最成熟。相比分割模型检测模型只需要一个框标注成本低、推理速度快对质检场景已经够用。2.2 train/val/test 怎么划分目录结构与划分脚本的常规做法YOLO 训练要求图片和标签严格对应目录结构通常是这样的dataset/ ├── images/ │ ├── train/ # 训练图片约 70%~80% │ ├── val/ # 验证图片约 10%~20% │ └── test/ # 测试图片可选约 10% ├── labels/ │ ├── train/ # 与 images/train 同名的 .txt │ ├── val/ │ └── test/ ├── classes.txt # 每行一个类别名行号就是 class_id └── data.yaml # 训练入口配置图片和标签靠“同名”关联IMG_001.jpg必须对应labels/train/IMG_001.txt。扩展名不同没关系YOLO 在读取时会自动替换后缀。划分的核心原则是同一块瓷砖的多个角度照片尽量放进同一个集合。如果训练集里有一块瓷砖的正面验证集里又有它的侧面网络相当于见过答案再考试val 指标会虚高部署到新产线直接现原形。常规做法是先按文件名前缀或目录分组再按组划分而不是逐张随机抽。如果你需要自己写划分脚本一个最小实现是这样import random import shutil from pathlib import Path all_images list(Path(images).glob(*.jpg)) random.Random(42).shuffle(all_images) n len(all_images) for i, img in enumerate(all_images): split train if i n * 0.8 else val if i n * 0.9 else test dst_img Path(images) / split / img.name dst_lab Path(labels) / split / (img.stem .txt) shutil.move(str(img), str(dst_img)) # 标签路径要先从 images 换成 labels src_lab str(img).replace(images, labels).rsplit(., 1)[0] .txt shutil.move(src_lab, str(dst_lab))逻辑说明先按固定随机种子打乱保证每次划分结果一致便于复现。n * 0.8和n * 0.9分别切出训练集和验证集最后 10% 进测试集。标签文件的路径不能用img.with_suffix(.txt)直接推导因为图片在 images 目录下标签在 labels 目录下必须做一次字符串替换。参数说明Random(42)里的 42 是随机种子换成任意整数都可以但要保证多次运行结果一致划分比例 0.8/0.1/0.1 是通用值如果数据集总量很小比如只有 200 张建议只用 train/val 两部分把 val 比例提到 20%因为测试集会挤占训练样本。2.3 class 文件和可视化脚本开工前必须跑一遍的两个检查class 文件是一份纯文本每行一个类名比如crack chip行号从 0 开始所以训练标签里的0代表 crack1代表 chip。这个顺序必须和所有标签 txt 里的数字对得上训练时data.yaml里的names会引用它推理时输出的也是这两个名字。如果你自己补过标注导出时务必确认 labelimg 的 classes.txt 顺序没有变过这是最容易出静默错误的地方。可视化脚本的作用是“把标注画回图上”让人眼检查。YOLO 标签格式是class_id x_center y_center width height全部是归一化坐标范围 0~1画框时要乘回原图宽高。一个最小可用的检查脚本import cv2 def draw_yolo_labels(image_path, label_path, class_names, save_path): img cv2.imread(str(image_path)) h, w img.shape[:2] with open(label_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, x_c, y_c, bw, bh map(float, parts) # 反归一化归一化坐标乘回原图宽高 x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) color (0, 0, 255) if int(cls_id) 0 else (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[int(cls_id)], (x1, max(y1 - 5, 0)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(str(save_path), img) # class_names 顺序必须与 classes.txt 一致 draw_yolo_labels(images/val/IMG_001.jpg, labels/val/IMG_001.txt, [crack, chip], check_IMG_001.jpg)逻辑说明读取图片尺寸后x_c - bw / 2得到左上角 x 坐标x_c bw / 2得到右下角 x 坐标乘上宽高后转成整数像素值。map(float, parts)把标签文本转成浮点数避免字符串拼接出问题。颜色按 class_id 区分crack 画红框、chip 画绿框一眼能看出类别有没有标反。参数说明class_names列表顺序必须和 classes.txt 完全一致save_path建议放进单独的check/目录别覆盖原图发现框超出图像边界时多半是坐标归一化算错或标注越界需要回看标注工具。跑完脚本后很多问题是只有在画出来之后才看得到的框偏移了半个身位、类别名字对不上、标签和图片根本不是同一张。这步做完再谈训练才有意义。3. 从 yaml 到 resultsYOLOv8 跑通裂缝检测的最小路径与参数解读3.1 安装与最小命令先把 YOLOv8 在本地跑起来图片检查完class 文件确认无误接下来就是把训练跑通。目前大家用得多的是 ultralytics 的 YOLOv8环境配置就两步# 创建虚拟环境推荐 python 3.9~3.10 conda create -n yolo-crack python3.10 -y conda activate yolo-crack # 安装 ultralytics pip install ultralytics如果机器上有 NVIDIA 显卡装完后用nvidia-smi确认驱动能识别卡没有 GPU 就用 CPU 训练慢一点但能跑通全流程。CPU 训练 yolov8n、640 输入、100 轮大概需要几个小时到十几个小时不等取决于核心数和内存带宽GPU 则把这个时间压缩到半小时以内条件允许还是建议用 GPU。装完后把数据集根目录绝对路径填到data.yaml里。这个数据包自带的 yaml 通常已经把 names 填好你需要改的只有 path 和 train、val 的相对路径path: /home/you/datasets/tile_crack # 改成实际绝对路径 train: images/train val: images/val names: 0: crack 1: chip逻辑说明path是数据集根目录train和val是相对它的子路径正斜杠结尾不要加。如果只有一个 val 目录而没分 test不用担心训练时 val 会同时承担测试集职责names必须从 0 开始编号调换顺序会导致类别错位。最小训练命令如下yolo detect train \ modelyolov8n.pt \ datadata.yaml \ epochs100 \ imgsz640 \ batch16 \ device0逻辑说明modelyolov8n.pt表示加载 COCO 预训练权重做迁移学习。裂缝和 COCO 的类别差很远但底层特征边缘、纹理、形状是通用的预训练权重能显著加速收敛device0指定第一张显卡没有 GPU 就删掉这行默认 CPU。启动后每个 epoch 结束会打印 box_loss、cls_loss、dfl_loss 和 mAP50、mAP50-95看到 mAP 开始爬升、loss 在下降说明数据和配置没有大问题。3.2 训练参数怎么设imgsz、epochs、batch、lr 的取舍新手最容易在参数上纠结其实瓷砖裂缝这种单色背景、目标结构简单的场景ultralytics 的默认参数本身就够用。真正需要动的是下面几个参数默认参考裂缝场景建议说明imgsz640640~960细裂纹用 960 能保住特征代价是显存和训练时间翻倍epochs100100~200配合早停别死等 300batch168~32以显存不吃满为准显存不足先降 batchlr00.010.01 起步损失曲线震荡剧烈时降到 0.005patience10020~30验证集连续 N 轮不提升就停省时间这里需要解释一下 YOLO 的损失函数构成。YOLOv8 的 loss 是三块加起来box_loss 用的是 CIoU综合考虑框的重叠率、中心点距离和长宽比cls_loss 是分类用的 BCE 损失dfl_loss 是分布焦点损失用于让框回归更精确。终端打印的 loss 是这三者的加权和所以 loss 一直在降不代表模型好必须配合 val 指标看。很多人训练时只盯 mAP忽略了 loss 曲线的形状。训练结束后打开runs/detect/train/results.png会看到两组曲线train loss 一路向下val loss 起先跟着降到某个点开始横盘甚至抬升这个分叉点就是过拟合开始的地方。裂缝数据集一般不大过拟合来得快所以patience建议从默认 100 改到 20~30——早停设置得越灵敏越能避免把时间浪费在已经变差的训练上。数据增强方面ultralytics 默认开马赛克增强对小数据集帮助很大。如果发现马赛克把裂缝切碎了导致 val loss 波动明显把mosaic0.5调低到 0.3或者干脆设成mosaic0.0关掉通常能稳住验证集表现。对瓷砖这类纹理规则的物体degrees10的小角度旋转和scale0.3的随机缩放是性价比最高的增强。3.3 结果目录里有什么loss 曲线、混淆矩阵和 PR 曲线的读法训练结束后runs/detect/train/下会生成一批文件重点看三个。第一个是results.png整体曲线汇总快速判断收敛情况。第二个是confusion_matrix.png横轴是真实类别纵轴是预测类别对角线越亮越好。裂缝检测里最需要关注的是背景行——如果“crack 被预测成 background”的数量很多说明细裂纹被漏检了需要提高 imgsz 或检查标注框是不是把细小裂纹包得太松。第三个是PR_curve.png每个类别的精确率-召回率曲线曲线越贴近右上角越好如果曲线在低召回段就往下掉说明模型偏保守宁愿漏检也不误报到部署阶段调低置信度门限可以找回部分召回。另外一组容易被忽略的指标是 mAP50 和 mAP50-95 的差值。mAP50 高但 mAP50-95 明显偏低说明模型框的位置不够准预测框和真实框的 IoU 只在 0.5 附近徘徊。这个现象在裂缝检测里很常见因为裂缝是细长目标标注框又紧贴走向预测框稍微偏移一点 IoU 就掉得很快。要改善优先检查标注质量其次才考虑换更大的模型。有朋友训练一结束就拿着 best.pt 去测单张图我的建议是先在 val 集合上把混淆矩阵和 PR 曲线看明白再动手推理。整体指标比单张图的目测更能反映模型能力读这三张图花不了十分钟信息量比盲测二十张图都大。4. 裂缝检测避坑五条值得写进笔记的踩坑记录这一章写的都是常见环境里反复出现的坑每一条都按“现象 → 原因 → 解决”来说希望能帮你绕开。4.1 训练时刷屏 Warning标签文件位置对不上现象训练刚开始终端不停打印标签文件找不到的告警训练能继续但 mAP 一直很低val 指标完全没有参考价值。原因最常见的是划分脚本只分了图片没分标签标签还堆在原来的目录里另一种是 labels 目录里多套了一层子目录YOLO 按labels/train/xxx.txt相对路径找结果文件躺在labels/train/2024/xxx.txt路径对不上自然读不到。解决先对比 images 和 labels 两棵目录树确保层数一致。再用一段简短 Python 核对from pathlib import Path img_dir Path(images/train) lab_dir Path(labels/train) missing [p.name for p in img_dir.glob(*.jpg) if not (lab_dir / (p.stem .txt)).exists()] print(f缺少标签的图片数: {len(missing)}) for name in missing[:10]: print(缺失:, name)逻辑说明遍历训练集所有 jpg用p.stem拿到不带扩展名的文件名拼上.txt后去 labels 目录查是否存在。参数说明如果打印结果为 0说明标签齐全问题出在其他环节如果有缺失对比缺失文件的分布规律通常能反推出是划分脚本漏了标签还是标注时就没保存。4.2 可视化脚本画出来的框全错位现象脚本跑完生成的图片上框的位置和裂缝完全对不上有的框整体偏移有的框是镜像位置有的框跑到图外面去了。原因三个典型。第一标签坐标不是归一化的而是像素坐标脚本又按归一化公式乘了一遍宽高框自然偏出去。第二原图在标注前被缩放或裁剪过标签坐标基于缩放前的大图而脚本读取的是缩放后的图。第三OpenCV 读图是 BGR 通道顺序如果保存或显示时做了通道转换的误操作肉眼看颜色不对容易误判成框错位。解决写脚本时加一个断言只要坐标不是 0~1 范围内就直接报错不要让人眼去猜assert 0 x_c 1, f坐标未归一化: {x_c}如果报错说明标签是像素坐标先除以宽高做归一化再画。打印img.shape确认图片尺寸和标注时的基准尺寸一致这一步能排查掉大部分错位问题。框偏移不严重但整体走位时优先怀疑图片被重采样过回看数据包里的原始图片和标注工具导出设置。4.3 mAP 不低但现场漏检问题往往出在标注标准现象训练集 mAP50 到 0.9拿到新厂房的照片一测裂纹漏检、灰缝误检成裂纹现场根本不敢用。原因训练集和现场数据存在分布差异是天然的光线、相机角度、瓷砖批次都不同但更常见的是标注标准不统一。有人把边缘阴影、釉面纹理也画进了框模型学到的是“纹理密度大”而不是“裂缝”换到干净的新瓷砖上就失灵有人画裂纹框时故意多包一圈背景模型学到的边界比实际裂缝粗导致细小裂纹全部漏掉。解决用现成数据集时先通过可视化脚本理解原有标注风格特别是框的松紧程度如果是自己补数据一定要写一份标注规范裂纹框紧贴裂缝走向、框的宽度不超过裂缝本身的两倍不标灰尘、不标水渍、不标釉面纹理同一块瓷砖的多角度照片只取一张进训练集。把规范写进文档让每个人读一遍再标注比调任何参数都管用。4.4 train loss 贴地、val loss 高位震荡过拟合的典型信号现象训练到第五十个 epochtrain loss 掉到 0.1 以下val loss 却在 1 以上来回震荡验证集的 mAP 不再上升。原因数据集小模型把训练集背下来了。几百张图的裂缝数据包用 yolov8s 以上的模型很容易过拟合。另一个隐蔽原因是划分时数据泄漏——同一块瓷砖的不同角度照片同时出现在 train 和 val模型见过类似纹理val 指标虚高等到新数据上才暴露。解决先确认划分脚本按组分配同一瓷砖的照片只进一个集合然后把模型换成更轻的 yolov8n减少参数量同时加强数据增强重点用degrees10和scale0.3模拟不同拍摄姿态让模型学到的是裂缝本身而不是背景。如果 val loss 依然压不住把 epochs 砍到 60 左右靠早停掐断训练。4.5 细裂纹一张都检不出来输入尺寸与锚框的取舍现象粗裂纹检得不错头发丝一样的细裂纹全漏把单张图放大仔细看能看见裂缝但模型就是没反应。原因YOLOv8 的下采样倍数决定了它能看到的最小特征尺度。输入 640 时最小特征图是 20×20每个格子对应原图 32×32 的区域一条只有 2~3 像素宽的裂缝在这个格子里的响应几乎为 0。另外训练时 imgsz 如果小于原图分辨率resize 会把细裂纹直接磨平相当于信息在输入端就丢了。解决优先把 imgsz 提到 960 甚至 1280让裂缝在特征图上占据更多像素。显存不够时换 yolov8n 并调低 batch把省下来的显存投给输入尺寸如果单张图太大用切片训练把大图切成若干 640×640 的小块训练推理时用滑窗拼接。切片方案会显著增加训练时间但对细长目标的召回提升最明显是工业场景里常用的手段。5. 验证模型而不是自我感动置信度门限、单图测试与导出部署训练结束不等于交付。我见过不少人拿 val 集测个 mAP 就宣布完成结果在真实照片上被灰缝、水渍打得满地找牙。验证阶段要做两件事单图目测和置信度门限调节。from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict(test_01.jpg, conf0.25, saveTrue)逻辑说明加载训练产出的 best.pt对单张图做推理saveTrue会把带框结果存到runs/detect/predict/下。conf0.25是最常用的起步门限。参数说明如果发现画面里到处都是灰缝误报把 conf 提高到 0.4~0.5如果发现裂纹漏检降到 0.1~0.15。这个数值没有标准答案本质是在误报和漏报之间选一个业务上更能接受的平衡点。工业现场建议宁可多出几个误报框让人工复核也不要漏检漏检的代价通常比误检高一个量级。如果模型要部署到边缘设备下一步是导出yolo export modelruns/detect/train/weights/best.pt formatonnx导出的 ONNX 可以用 ONNX Runtime 或 TensorRT 加速推理。导出时注意保持和训练一致的 imgsz否则特征图尺度变了精度会掉一截。导出后再跑一遍上面的单图测试对比导出前后框的位置和置信度确认没有精度损失再进入部署流程。最后补一句个人习惯我现在拿到任何数据集第一件事永远是跑一遍可视化脚本抽 30~50 张图把标注框逐一看过确认类别顺序、坐标格式、划分逻辑三件事没有翻车才舍得花算力去训练。这个习惯源自一次白跑了一周训练的经历从那以后再没犯过。希望帮到你。本文还有配套的精品资源点击获取