ARTICLE DETAIL

资讯详情

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

瓷砖裂缝检测YOLO数据集使用指南:从标注检查到训练避坑

瓷砖裂缝检测YOLO数据集使用指南:从标注检查到训练避坑 简介这套瓷砖裂缝检测YOLO数据集面向工业质检、视觉缺陷检测开发者及计算机视觉学习者可快速用于YOLO系列模型的训练与验证。数据约1700张采用LabelImg标注图片为PNG格式标签为txt文本并分区存放类别包含裂缝和正常两类训练集、验证集已划分完毕配合classes.txt即可直接训练。压缩包内共2000个文件以1765个txt标注、234张jpg图像和1个Python可视化脚本为主整体约91.75MB。其中可视化脚本无需修改随机传入一张图片即可绘制检测框并自动保存方便即时核验标注效果部分数据已做翻转、加噪声等增强处理有利于提升模型在复杂纹理下的泛化能力。目前已有194人学习下载适合希望缩短数据准备周期、专注模型调优的研究者直接使用。1. 瓷砖越光滑裂缝越难查一份2类YOLO数据集到底解决了什么做瓷砖表面质检的都知道裂缝这种缺陷最折磨人。砖面越光滑反光越强裂缝在成像里就越是细、窄、对比度忽高忽低肉眼盯产线都容易漏更别提让模型去数。你拿到的这份YOLO数据集解决的恰恰不是模型结构而是“根本没法好好开始训练”的前置问题数据是划分好的不用自己再动 train/val类别class文件已经写好不用对着文档猜 ID还附了数据可视化脚本能直接把标注框画到原图上检查错误。它适合两类人一类是刚入手瓷砖裂缝识别、打算用 YOLO 跑检测的新手另一类是已经在产线上做过一版模型、被脏数据坑到想重来的工程师。后面我会按“怎么看数据、怎么跑训练、怎么排查翻车”的顺序把这份数据集的用法讲透。2. 这份瓷砖裂缝数据集的目录结构、标注格式与2类划分逻辑2.1 目录结构图像和标注为什么必须按“同名对应”归位拿到数据集后先别急着训练花两分钟把目录结构看清能省掉后面大部分报错。一个规范的 YOLO 分类检测数据集目录长相一般是这样tile_crack/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/ ├── classes.txt └── visualize_labels.pyimages 里放的是 JPG、PNG 这类原始图片labels 里放的是同名 txt 标注文件。比如images/train/00001.jpg对应labels/train/00001.txt后缀不一样、名字必须完全一样否则训练时 YOLO 找不到标注会直接跳过那张图。这种同名匹配是 YOLO 系列一贯的约定从 YOLOv5 到 YOLOv8 都没变过自己整理数据时也不要创新。txt 文件的每一行代表一个目标框格式是五个值class_id x_center y_center width height注意后面四个坐标全是归一化后的相对值范围在 0 到 1 之间不是像素坐标。举个例子一行0 0.5012 0.4823 0.0187 0.0056意思是类别 ID 为 0目标中心点位于图像横向 50.12%、纵向 48.23% 的位置框的宽度占整张图宽度的 1.87%高度占 0.56%。瓷砖裂缝的框通常都很扁、很窄所以 width 和 height 往往差一个数量级这非常正常。2.2 为什么是2类类别边界比你想的模糊得多这份数据集标的是 2 类。务必要先打开classes.txt确认两个类名到底叫什么不要凭经验猜。常见做法是两个正类比如“裂纹 crack“和”崩边 scratch“也有可能是”裂缝“和”非裂缝区域“两种框。我倾向于按两个正类理解因为检测任务里背景不会作为带框的类别出现——没有砖面缺陷的图通常不带任何标注直接参与训练作为负样本。2 类划分看着简单实际标注时边界非常难拿捏。瓷砖上的纹理、针孔、色差在低分辨率下和细裂缝长得几乎一样标的时候觉得是裂缝训的时候模型会认为那是背景纹理特征。所以拿到数据后不要只看类别名要配合可视化脚本逐个看框确认类别边界是不是你理解的那个。如果发现某个类里混入了大量纹理误标宁可把那部分数据删掉也别硬留脏数据对检测模型的影响远大于数量不足。2.3 训练集/验证集划分逻辑与常见错误标题特别强调“划分好的数据集”这个不起眼的点其实很关键。自己划分数据最常见的错误不是比例而是泄漏。假设你拍了一块砖的多个视角图像随机洗牌后一部分进了 train、另一部分进了 val那么验证集里会出现和训练集极度相似的图val 指标虚高等模型上产线换一块新砖立刻现原形。正确的划分方式是按砖块或按拍摄批次切分同一块砖的所有图要么全部进 train、要么全部进 val。另一个要注意的是类别均衡。2 类目标在 train 和 val 里的框数量不需要完全相等但至少要保证 val 里每一类都出现了足够多的样本别让某一类在验证集里只有两三张图否则 mAP 这类指标的方差会大到失去参考意义。你可以先数一下两部分里每类框的数量如果 val 里某个类明显偏少建议重新划分而不是继续往下训。拿到这份数据集后我一般会先跑一遍下面的统计脚本确认 no label 的空标注文件数量。瓷砖数据里大量负样本图不带任何框这是允许的但如果空标注文件比例超过 30%就要留意是不是标注漏标太多import os label_dir labels/train total 0 empty 0 for name in os.listdir(label_dir): if not name.endswith(.txt): continue total 1 if os.path.getsize(os.path.join(label_dir, name)) 0: empty 1 print(f总标注文件数: {total}, 空标注文件数: {empty})3. 把类别class文件对牢、把数据可视化脚本跑出框训练前的两次把关3.1 class文件生成与检查标签序号错位是最安静的坑先说清楚这里的 class 文件不是 Java 编译出来的 .class而是类别清单文件一般就是classes.txt每行写一个类别名行号就是类别 ID从 0 开始。例如crack scratch如果你把两行换个顺序那么原来所有 ID 为 0 的标注就全变成 scratch 了而模型训练时根本不会报错只会安静地训出一个错乱模型。这个坑隐蔽就隐蔽在 loss 会正常下降可视化画框也看不出异常直到你发现类别名和框完全对不上。拿到数据集后先做一件事扫描所有 txt 标注里实际出现过的类别 ID和 class 文件行数对比。可以直接用一段小脚本import os label_dir labels/train classes_txt classes.txt class_ids set() for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname), encodingutf-8) as f: for line in f: line line.strip() if not line: continue class_ids.add(int(line.split()[0])) class_count len(open(classes_txt, encodingutf-8).readlines()) print(标签中出现过的类别ID:, sorted(class_ids)) print(classes.txt 中的类别数量:, class_count)输出里出现过的类别 ID 应该是 0 和 1 这样的连续整数且最大 ID 小于 class 文件行数。如果出现 ID 为 5 但 class 文件只有 2 行说明标注里混入了其他数据集的标签训练前必须清掉否则会触发索引越界或静默错标。3.2 可视化脚本的工作逻辑归一化坐标怎么还原成画框坐标数据可视化脚本是判断标签质量最直接的工具。它的核心逻辑只有一步把 txt 里的归一化坐标乘以图像的像素宽高还原成整数像素坐标然后用 OpenCV 画矩形框。我给一个可以直接运行的参考实现和你手上的 visualize_labels.py 作用一致。import cv2 import os def draw_one(image_path, label_path, class_names, out_path): img cv2.imread(image_path) if img is None: print(图片读取失败:, image_path) return h, w img.shape[:2] if not os.path.exists(label_path): print(标签文件不存在:, label_path) return with open(label_path, 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) x1 max(0, x1) y1 max(0, y1) x2 min(w, x2) y2 min(h, y2) color (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) label class_names[int(cls_id)] if int(cls_id) len(class_names) else str(int(cls_id)) cv2.putText(img, label, (x1, max(0, y1 - 6)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(out_path, img) print(已保存:, out_path) if __name__ __main__: class_names open(classes.txt, encodingutf-8).read().splitlines() draw_one( image_pathimages/train/00001.jpg, label_pathlabels/train/00001.txt, class_namesclass_names, out_pathvis/00001.jpg, )逻辑说明先读图片拿到高 h 和宽 w再把 txt 里的 x_center、y_center、width、height 分别乘以 w 或 h得到像素中心点和像素宽高换算成左上角 x1、y1 与右下角 x2、y2 后画矩形。参数里 class_names 从 classes.txt 读取这样画出来的框直接显示类别名字而不是数字眼睛一扫就能发现问题。实际批量使用的时候我会把这段代码改成遍历整个 train 目录把所有可视化结果输出到一个 vis 文件夹然后按顺序翻看。标题里说“附数据可视化脚本”你拿到的脚本大概率也是这个思路如果它不支持批量输出最简单的方式是外层套一个循环调用。3.3 可视化结果怎么读三种最隐蔽的标注错误画完框之后不要只看框框有没有要看三类错误。第一类是漏标。图像里明明有一段裂缝但整张图没有框。漏标会让模型把裂缝当成背景后果比错标更麻烦因为它是反向学习。检查时重点看负样本图也就是没有任何标注的图确认它真的是干净砖面而不是漏标。第二类是坐标错位。框偏移目标半个身位或者框只框住了裂缝的一小段。裂缝是长条状目标如果标的时候只点了一小段模型会学成“见着裂缝只出一小框”训练集的 mAP 可能还不错但实际推理时框的置信度会飘。比较靠谱的标准是框要完整包住整条裂缝主体可以略有外扩但不要只框三分之一。第三类是类别颠倒。上一节说的 class 文件顺序问题在可视化结果里会表现得非常直白——crack 的框全显示成 scratch 这个名字。真遇到这种问题直接改 class 文件顺序就好不要去改几千个标签文件。4. 基于这份数据集在 YOLOv8 上跑通训练yaml、最小命令、损失曲线4.1 数据 yaml 的写法路径和 names 最容易翻车在 YOLOv8 里训练自己的数据集第一步是写一个数据 yaml。路径和 names 各有一个容易踩的坑。一个可用的 tile_crack.yaml 长这样path: /home/user/tile_crack train: images/train val: images/val nc: 2 names: 0: crack 1: scratchpath是数据集根目录的绝对路径train和val是相对于 path 的子目录路径。常见翻车点是用了相对路径然后训练时换了工作目录导致 YOLO 找不到图片报 FileNotFoundError。我的习惯是直接用绝对路径写死省心。另一个点是names必须和classes.txt里的顺序一致。YOLOv8 训练时不会自动去读 classes.txt它只认 yaml 里的 names。如果 yaml 里把 crack 写在 1、scratch 写在 0那你训练出来的模型输出含义就和标注完全错位。稳妥做法是写 yaml 前先打开 classes.txt 复制粘贴不要凭记忆打字。4.2 训练最小命令与必调参数环境准备好后训练命令可以这样启动yolo detect train \ datatile_crack.yaml \ modelyolov8s.pt \ epochs150 \ batch16 \ imgsz640 \ device0 \ patience40逻辑说明data 指向 4.1 的 yamlmodel 用预训练权重 yolov8s.pt不要在纹理数据集上从头训练预训练权重里的低级特征对裂缝识别帮助很大epochs150 是上限实际经常跑不到那么久patience40 表示验证集指标连续 40 轮不提升就早停。参数说明方面有几个需要认真对待。imgsz 我建议用 640 打底如果显存有余量提到 800 或 960 对细裂缝有明显帮助因为裂缝在原始图像里往往只有十几个像素宽下采样后容易消失。batch 先从小往大试显存不够就把 batch 降到 8同时用 accumulate4 来模拟更大的 batch 稳定性。workers 默认值可以但 Windows 下偶尔会卡死遇到 DataLoader worker 报错就设 workers2 重试。学习率 lr0 建议保持默认 0.01如果你的 loss 曲线完全不动优先降 lr 而不是加 batch。数据增强参数值得说一下。YOLOv8 默认开启 mosaic1.0对砖面这种大面积同色目标本来没问题但裂缝是细长目标mosaic 把四张图拼在一起时裂缝经常被切到图片边缘甚至截断模型学到的正样本就变残缺了。我一般会把 mosaic 降到 0.5 左右同时关掉 hsv_h 这类色调增强瓷砖颜色变化不大过强的颜色扰动反而制造伪差异。如果你更喜欢用 Python 脚本方式启动等价写法是from ultralytics import YOLO model YOLO(yolov8s.pt) model.train( datatile_crack.yaml, epochs150, batch16, imgsz640, patience40, mosaic0.5, )两种方式底层同源选哪种纯粹看习惯。我在服务器上一般用命令行方便记录日志在本机调试时用 Python 方式因为可以顺手把数据集统计脚本和训练脚本串在一起。4.3 训练期间的 loss 曲线怎么读什么时候该停YOLOv8 的损失函数拆成三块box_loss 用的是 CIoU 变体管预测框位置和尺寸cls_loss 是 BCE管分类对不对dfl_loss 是分布焦点损失主要影响框的边框回归精度。日志里在 val 阶段会分别打印这三个值别只盯着总的 loss 看要分开看趋势。训练最初十几轮 box_loss 快速下降是正常的后面进入平台期下降变缓。cls_loss 在类别容易区分时通常降得很快如果 cls_loss 一直居高不下回 3.1 检查 class 文件是不是错位了。dfl_loss 对裂缝这种窄框相对敏感一般会慢慢下降如果它突然反弹多半是出现了异常标注——比如某个框的 width 接近 0模型不知道怎么拟合。早停机制看的是验证集的总指标。但瓷砖数据集通常照片数量不大val 集可能只有几百张mAP 波动会很明显。如果你发现 val 指标忽高忽低、训练被频繁早停别急着信把 patience 调大到 60 或者干脆设一个固定 epoch 数训练完再看。训练中途想看曲线就用自带的日志yolo detect train ... projectruns nametile_crack tensorboard --logdir runs浏览器打开 TensorBoard 就能看到三组 loss 曲线和 mAP 曲线。我对曲线的基本判断标准是train loss 持续下降、val loss 没有在早期就掉头向上这说明数据划分基本健康如果 train loss 一直降但 val loss 一直在涨那就是过拟合了回头查第 5 章的数据泄漏问题。5. 瓷砖裂缝 YOLO 训练避坑笔记5条翻车记录的排查方向5.1 现象loss 曲线完全不动甚至直接变成 NaN第一次训练就遇这种情况别急着怀疑模型。常见原因有三个学习率太高、标签文件里有畸形数据、图片本身有问题。检查顺序是先跑数据可视化脚本把框全部画出来看有没有 width 或 height 为 0 的非法框再用脚本检查图片能否被 OpenCV 正常读取个别损坏的 JPG 会让 loss 当场爆炸。都没问题就调小 lr0 到 0.001 再试YOLOv8 默认学习率对很多工业小数据集来说偏激进。关闭 AMP 混合精度也是一个排除手段有少量异常样本在 FP16 下会触发 NaN。5.2 现象推理时预测框糊成一大片几乎覆盖整个目标区域这个翻车现场很经典——模型训练时 loss 降得还行预测时输出的框却大到离谱。多数情况是标签文件里的坐标没有归一化直接写了像素值。比如标注工具导出了0 521.8 482.3 30.2 15.6如果这五个值里的后四个都大于 1说明是像素坐标。YOLO 会把这些值当归一化数据去算相当于告诉模型目标中心在图像 521 倍宽的位置模型当然学不出正常框。解决方法是重新写一轮转换脚本把所有像素坐标除以对应图片的宽高做归一化。训练前先打印一个标签文件看看数值范围最省事。5.3 现象train 的 mAP 很高val 的 mAP 很差典型的数据划分问题。如果你拿到的是已经划分好的数据集仍然要确认同一个砖块的照片有没有被切到两个集合里。瓷砖数据常常是一次拍摄几十张图相邻照片背景高度重叠。验这一类泄漏没有捷径只能抽样对比 train 和 val 的图片看有没有同一块砖不同角度的图。另一种原因是增强参数过强mosaic1.0 加上大范围旋转模型在训练时看到的裂缝形态过于扭曲而验证集是原始图分布就不对齐了。降到 mosaic0.5关闭垂直翻转通常能缓解。5.4 现象显存溢出一启动训练就 CUDA out of memory模型选择、batch、imgsz 三者会同时决定显存占用。如果你上来就用 yolov8m.pt batch32 imgsz960那 8GB 显卡基本必炸。降低优先级是先降 batch 到 8接着把 imgsz 降到 640最后才考虑换更小的模型。如果业务上必须用 960 输入就用 yolov8s.pt 并把 batch 压到 4然后靠 accumulate 参数补偿 batch 太小带来的梯度抖动。数据集的“图片尺寸很大”不影响显存影响显存的是 imgszYOLO 训练时会把所有图缩放到 imgsz 再进网络。5.5 现象细裂缝检测不出来只输出一些似有似无的小碎框这是瓷砖裂缝识别的核心难点。裂缝在 640 分辨率下经常不超过 10 个像素宽经过模型多次下采样后小目标特征已经非常微弱。YOLOv8 默认从 80×80 的特征图开始检测再小的目标在更深的层次基本消失。常见解决路径是把 imgsz 提到 960优先保证裂缝主体占据更多像素关掉或调低 mosaic避免裂缝在增强时被切碎换用自带 P2 小目标检测头的模型结构还有一个思路是换损失函数比如对小目标更友好的 NWD 改进 yolo 的做法用 Wasserstein 距离替代部分 IoU 计算对裂缝这类细长目标的空间偏差容忍度更高。实际效果视数据而定但值得在调参进入瓶颈时试一轮。6. 用深这份数据结构化验证清单与两个值得试的调整方向6.1 训练前的一张验证清单我习惯在正式训练前把以下项目逐项过一遍全部通过才启动训练检查项操作方法通过标准目录结构比对 images 和 labels 下的文件名同名文件完全一一对应class 文件用脚本统计标签出现过的 IDID 为 0 和 1且与 classes.txt 顺序一致标签坐标范围抽查标签文件数值五个数值中后四个均在 0 到 1 之间可视化抽检每类至少抽 30 张画框无漏标、无错位、无类别颠倒划分泄漏比对 train 与 val 的砖块来源同一砖块没有跨集合出现空标注比例统计空 txt 文件占比不过高负样本合理这张表看着繁琐但做一次之后能挡住 80% 的无效训练。我吃过亏曾跳过可视化直接训练两天后才发现 class 文件顺序反了白白浪费一轮时间。现在数据到手先花 20 分钟过清单这是最值的投资。6.2 两个值得试的调整方向第一个方向是分辨率策略。瓷砖表面裂缝的宽窄直接决定检测难度如果原始图像是 2000×2000 以上直接缩到 640 会让裂缝信号严重衰减。更好的做法是保持 960 或 1280 输入配合显存调整 batch。显存撑不住时可以考虑用切图策略把大图切成若干 640×640 的 patch 再训练相当于兼顾分辨率和显存。前提是切图的标注框也要同步切分这部分可以用脚本自动完成。第二个方向是损失函数层面的调整。如果你的模型其他都正常就是小裂缝召回率差可以试一下 NWD。具体做法是在损失计算中把基于 IoU 的匹配方式替换为基于 Wasserstein 距离的相似度度量它对位置偏差更宽容——裂缝框比普通目标框小得多几个像素的偏移就会让 IoU 骤降换成 NWD 后梯度更平滑训练更容易收敛。这个改动不需要改数据只动训练逻辑适合作为调参瓶颈期的最后一个备选。电子瓷砖质检这个方向数据质量永远比模型结构重要。哪怕你只用 YOLOv8n只要数据集干净、划分合理效果也会超过脏数据加一个大模型的组合。我现在的习惯是每次训练前都强迫自己跑一遍可视化宁可多看十分钟的框不愿再吃一轮无效训练。希望帮到你。本文还有配套的精品资源点击获取
返回列表