简介:面向瓷砖表面质检场景的 YOLO 目标检测数据集,涵盖边异常、角异常、点块瑕疵、光圈瑕疵、记号笔、划伤等 9 类常见表面缺陷,适用于工业视觉检测算法训练、模型微调与检测效果对比验证。资源共 2000 个文件,核心是 1999 个 txt 格式的 YOLO 标注文件,另附一个 Python 可视化脚本,压缩包整体约 63.81MB;数据按 YOLOv5 目录规范存放,训练集含 3552 张图片及对应标签,验证集合计 888 张图片及对应标签,每个标注文件均使用类别、中心点横纵坐标、宽高四维相对坐标,可直接导入主流 YOLO 检测框架进行训练与验证。包内还提供 class 类别文本与无需修改即可运行的可视化脚本,脚本支持随机读取一张图片、绘制边界框并自动保存在当前目录,便于快速检查标注质量并建立直观的缺陷形态认知;同时图片与标签一一对应,目录划分清晰,省去手动整理标签和格式转换的额外工作。目前已有 181 人学习下载,适合需要快速获得可训练数据集的缺陷检测初学者、算法工程师及工业视觉项目开发人员。
1. 瓷砖表面瑕疵检测,为什么值得先拿到一份称手的数据集
做工业视觉的同行应该都有体会:算法选型往往不是瓶颈,真正卡住项目进度的,是数据。瓷砖表面瑕疵检测就是这样一类任务——生产线上的瓷砖速度快、表面纹理复杂、光照还会波动,瑕疵种类又多又杂,光是把数据准备好、标注规范对齐,就要耗掉一大半精力。如果你拿到的是一份已经划分好训练集、验证集、测试集,带好类别 class 文件和可视化脚本的 YOLO 数据集,等于直接把项目推进到“打开就能训练”的状态,省下的时间足够你再调两轮模型。
这份数据集是典型的工业落地形态:9 类瑕疵,涵盖瓷砖表面最常见的缺陷类型,划分好的目录结构直接对接 YOLO 系列训练流程。对正在做毕业设计、工厂项目预研、或者想快速验证 YOLO 算法在表面缺陷检测上效果的人来说,它都是一个可以直接上手的起点。下面我从数据集结构、标签含义、训练配置、可视化脚本到踩坑记录,按实际做项目的顺序拆开讲。
2. 数据集的目录结构与 9 类标签:先用 tree 看清家底
动手训练之前,第一件事不是打开训练脚本,而是把数据集目录结构完整看一遍。很多数据集下载下来之后,图片、标签、划分文件混在一起,路径对不上、类别顺序不一致,训练时各种报错。这一份数据集我拿到手后第一感觉是:结构是规范的 YOLO 格式,目录分层清楚,省掉了最让人头疼的重新整理环节。
2.1 标准 YOLO 目录树:images 与 labels 严格对应
dataset/ ├── images/ │ ├── train/ │ │ ├── img_0001.jpg │ │ ├── img_0002.jpg │ │ └── ... │ ├── val/ │ │ ├── img_0100.jpg │ │ └── ... │ └── test/ │ ├── img_0200.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_0001.txt │ │ ├── img_0002.txt │ │ └── ... │ ├── val/ │ │ ├── img_0100.txt │ │ └── ... │ └── test/ │ ├── img_0200.txt │ └── ... ├── classes.txt ├── data.yaml └── visualize.py这个结构几乎是 YOLOv5/v8 训练的标准输入形态。images和labels两个根目录下各自有三份子集,文件前缀名一一对应,比如img_0001.jpg对应的标注文件一定是img_0001.txt,这个命名规则不要随意改动,训练脚本就是靠文件名前缀来找配对文件的。
每个.txt标注文件里,每一行代表一个目标框,格式是五列:class_id x_center y_center width height。注意 YOLO 格式的坐标是归一化后的相对坐标,不是像素绝对值。比如某一行是2 0.513 0.427 0.082 0.166,表示类别 id 为 2 的目标,框中心在图片宽度 51.3%、高度 42.7% 的位置,框宽占图片宽 8.2%、高占图片高 16.6%。
classes.txt文件则是按行排列的类别名,每一行的索引位置就是这个类别的 id。比如第 3 行是crack,那上面举例中的2就代表crack类。这个顺序一旦定了,训练时就不要再去改classes.txt里的行序,否则模型训练和推理时的类别对应关系会乱掉。
2.2 9 类标签的含义与 id 对应表
拿到classes.txt之后,我建议你立刻打开看一眼,把它对应的类别和中文含义记下来。这份数据集的 9 类标签,按照常见瓷砖产线的缺陷命名习惯,大概是下列这些:
| class_id | 英文类别名 | 中文含义 | 典型形态 |
|---|---|---|---|
| 0 | blush | 釉料不均匀、色斑 | 表面局部颜色深浅不一 |
| 1 | broken | 断裂/崩瓷 | 边角崩裂、裂纹穿透 |
| 2 | crack | 裂纹 | 细线状裂缝 |
| 3 | glaze | 釉面缺陷 | 釉层起泡、缩釉 |
| 4 | line | 线条瑕疵 | 长直线状印痕 |
| 5 | pinhole | 针孔 | 微小孔洞 |
| 6 | spot | 斑点 | 局部染色点/杂质点 |
| 7 | structural | 结构缺陷 | 变形、边角不齐 |
| 8 | trim | 边缘毛刺/切割不良 | 边缘崩边或多余釉料 |
这个表格和具体数据集的classes.txt内容可能有细微出入,但整体方向一致。在开始训练前,你应该先数一下每个类别的样本数量,看看是不是存在严重的类别不平衡。如果某类只有几十张图,而另一类有几千张,后面训练时就需要针对性地调整 class weight 或做数据增强。
提示:不要凭文件名猜类别。瓷砖瑕疵的命名在不同厂家、不同数据集里差异很大。以
classes.txt和data.yaml中的实际定义为准。
2.3 data.yaml 的字段要逐行核对
YOLO 训练时读的不是classes.txt,而是data.yaml。打开这个文件,你会看到类似这样的内容:
# data.yaml train: dataset/images/train val: dataset/images/val test: dataset/images/test nc: 9 names: ['blush', 'broken', 'crack', 'glaze', 'line', 'pinhole', 'spot', 'structural', 'trim']这里的train、val、test写的是图片目录的路径,不是标签目录。YOLO 会自动把images替换成labels去找对应的标注文件。路径建议用相对路径,或者在你训练机器上的绝对路径,否则换一台机器跑就要改配置。
nc是类别总数,这里必须等于 9。names是一个长度为 9 的列表,顺序必须和classes.txt完全一致。训练过程中,日志里打印的类别名就是从names来的。
有一个细节容易忽略:有些数据集会把test目录也写进data.yaml,YOLOv8 默认只在val上做验证,test目录是留给最终评估用的。训练阶段不会用到test的标注数据,这很正常,不要以为代码没跑就是坏了。
3. 用划分好的数据集跑通 YOLO 训练:从预训练权重到损失曲线
数据没问题,接下来就是训练。这里我以 YOLOv8 为例来讲,因为它是当前工业缺陷检测里用得最顺手的版本,验证集指标和推理速度的平衡做得比较好。YOLOv5 的流程大同小异,命令和配置文件略有差异,但核心逻辑相同。
3.1 环境准备与 YOLOv8 安装:两条命令的事
# 创建虚拟环境,Python 版本建议 3.9 或 3.10 conda create -n yolo_tile python=3.10 -y conda activate yolo_tile # 安装 ultralytics 包,会一并带上 torch 的 CPU 版 pip install ultralytics如果你的机器有 NVIDIA 显卡,建议先安装好 CUDA 版本的 PyTorch,再装ultralytics。常见做法是去 PyTorch 官网复制对应 CUDA 版本的安装命令,比如pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118,然后再pip install ultralytics。这样训练速度会比 CPU 快一个数量级。
安装完成后,用一条命令验证环境是否正常:
yolo predict model=yolov8n.pt source=dataset/images/val/img_0001.jpg如果能正常输出检测结果,说明安装成功。这一步会顺便自动下载yolov8n.pt预训练权重,这也是标题相关热词里“yolo预训练模型下载”的常见场景。下载失败的话,多半是网络问题,手动把权重文件放到当前目录即可。
3.2 训练命令与关键参数说明
# 在数据集根目录下执行训练 yolo train \ model=yolov8n.pt \ data=data.yaml \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ workers=4 \ patience=20 \ project=runs/tile_defect \ name=yolov8n_9cls逐项拆解这些参数的用意:
model=yolov8n.pt:这是 COCO 预训练权重。用预训练权重做迁移学习,收敛速度比从零训练快很多,尤其是工业小数据集,从零训练很容易过拟合。YOLO 系列在 COCO 上学到的通用特征(边缘、纹理、颜色)对瓷砖表面瑕疵同样有效。data=data.yaml:指向数据集配置文件。路径相对于当前执行命令的工作目录,建议在数据集根目录下运行。imgsz=640:输入图片尺寸。瓷砖瑕疵有相当一部分是小目标(针孔、裂纹、斑点),输入分辨率太低会把小目标直接糊掉。如果显存够大,用 768 或 1024 通常对细小瑕疵更友好,但训练时间会相应上涨。batch=16:批量大小。显存不够就降到 8 或 4,梯度累积效果可以弥补一部分。工业数据集普遍在几千张的量级,batch 小一点问题不大。patience=20:早停机制。验证集指标连续 20 个 epoch 不提升就自动停止,防止训练后期浪费时间。这个参数在项目初期跑基线时特别有用。project和name:输出目录。训练日志、权重文件、混淆矩阵、PR 曲线都会写到runs/tile_defect/yolov8n_9cls/下。
训练结束后,runs/tile_defect/yolov8n_9cls/weights/目录里会有best.pt和last.pt两个文件。best.pt是验证集指标最优的那一版,做测试和部署都优先用它。
3.3 训练过程中的关键监控指标
训练日志里,每过一个 epoch 会打印一组指标:box_loss、cls_loss、dfl_loss、precision、recall、mAP50、mAP50-95。前三个是损失值,后面是检测指标。
作为工程师,我关注的重点顺序是:mAP50-95反映整体检测精度,recall反映漏检率。瓷砖产线上最怕的是漏检——有瑕疵的砖被当成合格品流到下一道工序,所以 recall 的优先级高于 precision。如果训练结束时 recall 明显偏低,多半是某些类别的样本太少或特征太不明显,后面需要在数据增强和类别权重上做文章。
mAP50和mAP50-95的区别在于 IoU 阈值。mAP50 只计算 IoU 阈值 0.5 的精度,mAP50-95 则是对 0.5 到 0.95 不同阈值取平均。对于瓷砖瑕疵这种目标框偏小、形态不规整的任务,mAP50-95 更能反映模型对框位置精度的把控。
训练曲线图会存成results.png,直接查看这个图片比盯着终端数字直观得多。重点关注训练损失和验证损失的差距:如果训练损失持续下降但验证损失不降反升,就是过拟合信号,需要增加数据增强或者减小模型规模。
4. 数据可视化脚本:训练前必须跑一遍的 3 个检查
数据集里附带的visualize.py脚本,是这个数据集的加分项。很多数据集只给图片和标注,可视化要自己写,而这个直接给了现成的。不要只把它当成看效果的玩具,它在训练前排查数据问题上有三个实际用途:确认标注框是否贴合目标、统计类别分布、检查是否存在标注错误。
4.1 画标注框:用 OpenCV 把 YOLO 标签还原到图片上
# visualize.py 核心逻辑(节选) import cv2 import os import random def draw_boxes(image_path, label_path, class_names, output_path): img = cv2.imread(image_path) h, w = img.shape[:2] with open(label_path, 'r') as f: lines = f.readlines() for line in lines: parts = line.strip().split() cls_id = int(parts[0]) x_center = float(parts[1]) * w y_center = float(parts[2]) * h box_w = float(parts[3]) * w box_h = float(parts[4]) * h x1 = int(x_center - box_w / 2) y1 = int(y_center - box_h / 2) x2 = int(x_center + box_w / 2) y2 = int(y_center + box_h / 2) color = (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls_id], (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(output_path, img) # 批量遍历 train 目录,随机抽 20 张出图 # 运行方式: python visualize.py --mode draw --num 20这个脚本的作用,是把归一化的 YOLO 坐标还原成像素坐标,然后把框和类别名画到原图上。手动打开几张输出图,重点看三件事:框有没有完全包住目标、框是不是明显偏大偏小、类别名和框内缺陷是否对应。
YOLO 格式用的是中心点加宽高,还原时容易犯的错是忘记乘回原图的宽高。上面的代码做了这个转换,逻辑上没毛病。真实世界的标注框往往会有少量偏移——标注人员描框时多留了一圈背景,这在工业瑕疵检测里常见,影响不大,但不能偏得太离谱。
4.2 类别统计:一张柱状图看穿样本分布
# visualize.py 核心逻辑(节选) import matplotlib.pyplot as plt from collections import Counter def count_classes(labels_dir, class_names): counter = Counter() total_boxes = 0 empty_files = 0 for filename in os.listdir(labels_dir): if not filename.endswith('.txt'): continue filepath = os.path.join(labels_dir, filename) with open(filepath, 'r') as f: lines = f.readlines() if len(lines) == 0: empty_files += 1 for line in lines: cls_id = int(line.strip().split()[0]) counter[cls_id] += 1 total_boxes += 1 # 绘制柱状图 plt.bar(class_names, [counter[i] for i in range(len(class_names))]) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('class_distribution.png') print(f"总标注框: {total_boxes}") print(f"空标签文件: {empty_files}") return counter # 运行方式: python visualize.py --mode stats --labels labels/train这个统计比画框验证更关键。类别分布直接决定训练策略:如果某个类别的框数量只有其他类别的十分之一,模型大概率学不好这一类。看到极端不平衡时,优先考虑的做法不是增加模型复杂度,而是去补充数据或者对该类别做复制粘贴式的数据增强。
空标签文件也是这个脚本能帮你发现的隐患。训练目录里如果混入了空标注的图片,YOLO 训练时会把这张图当成背景样本,不会报错,但会影响梯度方向。数量少(个位数)可以忽略,多了就要筛查是不是图片和标注文件对不上。
4.3 检查标注错误:最容易被忽略的坑
# visualize.py 核心逻辑(节选) def check_label_bounds(labels_dir, images_dir): errors = [] for filename in os.listdir(labels_dir): if not filename.endswith('.txt'): continue label_path = os.path.join(labels_dir, filename) img_path = os.path.join(images_dir, filename.replace('.txt', '.jpg')) if not os.path.exists(img_path): errors.append(f"缺少图片文件: {filename}") continue img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path, 'r') as f: lines = f.readlines() for idx, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: errors.append(f"{filename} 第{idx+1}行格式错误: {line}") continue x_center = float(parts[1]) y_center = float(parts[2]) box_w = float(parts[3]) box_h = float(parts[4]) x1 = (x_center - box_w / 2) * w y1 = (y_center - box_h / 2) * h x2 = (x_center + box_w / 2) * w y2 = (y_center + box_h / 2) * h if x1 < 0 or y1 < 0 or x2 > w or y2 > h: errors.append(f"{filename} 第{idx+1}行框超出图片边界") return errors # 运行方式: python visualize.py --mode check这段脚本做的事情是检查两类问题:一是标注文件对应的图片是否存在;二是标注框坐标是否超出图片边界。框出界的标注往往来自数据增强时的错误裁剪或标注工具的手误,训练时会导致损失异常波动。
提示:在跑任何训练之前,先运行
python visualize.py --mode check。它能帮你筛掉接近 90% 的“训练突然崩了”类问题,尤其是那些只在特定 epoch 出现的 NaN 损失,很多时候就是标注数据里有脏样本。
5. 常见问题排查与避坑记录:5 条血泪经验
做瓷砖瑕疵检测这个方向,有五个坑我基本每次都会遇到,写在这里给后来者省点时间。这些都是真实项目里踩过的,不是理论推演。
5.1 类别名顺序不一致导致训练指标异常
现象:训练日志显示 mAP 全程在 0.1 以下,但可视化画框看起来标注没问题。
原因:data.yaml里的names列表顺序和classes.txt不一致。比如classes.txt里第 1 行是blush,而data.yaml里names[0]写的是crack。模型训练时拿到的类别 id 对应的语义就错位了,验证时用同一个错位逻辑评估,看起来指标正常,实际模型学的是错的东西。
解决:写个小脚本读取classes.txt和data.yaml,逐行比对后打印差异。比对通过后再开训练。这个脚本可以直接放到visualize.py里作为--check模式的一部分。
5.2 验证集图片尺寸和训练集不一致
现象:训练损失正常下降,但验证集 mAP 波动剧烈,同一权重两次验证结果完全不同。
原因:数据集里混入了不同分辨率、甚至不同长宽比的图片。YOLO 训练时会统一 resize 到imgsz,但验证时如果rect参数开启,会自动按 batch 内最大宽高填充,导致不同 batch 的验证结果不可比。
解决:训练前统计数据集所有图片的尺寸分布。如果发现有1920x1080和480x640混在一起的情况,统一 resize 到同一尺寸再训练是更稳妥的做法。工业现场拍照的相机通常固定安装,分辨率应该是一致的,出现不一致大概率是数据集整合时混入了来源不同的图片。
5.3 小目标漏检严重,recall 上不去
现象:pinhole和spot两个类别的 recall 只有 30% 左右,其他类别正常。
原因:这两类目标在 640 分辨率下可能只占十几个像素。YOLO 的下采样倍数会直接把这么小的目标过滤掉,模型根本没机会学。
解决:三个方向按优先级尝试。第一,把imgsz提到 1024,这通常是最直接有效的方式。第二,在训练配置里开启 mosaic 增强,让小目标样本在拼接图里的出现频率升高。第三,如果前两个还不够,考虑用基于切片推理的 SAHI 方案,把大图切成重叠小块分别检测再合并结果。
5.4 背景样本过多导致误检率上升
现象:训练后 model 在正常瓷砖上频繁标出瑕疵,precision 极低。
原因:数据集里大量图片是完全没有标注框的干净瓷砖,且这些图片在训练时被当作普通背景正常参与负样本学习。如果干净样本和瑕疵样本比例失衡,模型会倾向于把所有纹理变化都当作瑕疵。
解决:检查数据集中空标注文件的比例。超过 30% 可以考虑对这些干净样本做降采样,或者在data.yaml里通过scale和flip参数限制增强强度,减少模型对正常纹理的过度敏感。更精细的做法是给这些干净样本分配更低的损失权重,需要改数据加载逻辑,多数场景用降采样就够了。
5.5 显存不足导致训练中断
现象:训练跑到第 10 个 epoch 突然报CUDA out of memory,前面没有明显异常。
原因:不同 epoch 的数据经过 mosaic 增强后,拼接图大小是动态变化的,有些组合方式产生的中间张量特别大,占满显存。
解决:batch从 16 降到 8,同时开启cache=ram让数据预加载到内存而不是每次从磁盘读。另外把workers调低到 2 或 4,避免多个数据加载进程同时搬运数据到 GPU 时额外占用显存。这两个调整结合后,16GB 显存跑yolov8m的 640 分辨率训练基本不会出问题。
6. 进阶验证方法:用验证脚本把 best.pt 变成可交付的检测器
训练结束不是终点,重点是验证模型在真实场景下的表现。数据集里的test目录在训练时没有派上用场,这时候就体现出价值了。用best.pt跑一遍测试集,输出 PR 曲线和混淆矩阵,是判断模型能不能交付的最后一道关口。
6.1 用 val 模式跑详细指标
# 在测试集上做最终评估 yolo val \ model=runs/tile_defect/yolov8n_9cls/weights/best.pt \ data=data.yaml \ split=test \ imgsz=640 \ batch=8 \ save_json=True \ save_txt=Truesplit=test是关键参数,它告诉 YOLO 用data.yaml里test字段指定的图片目录做评估,而不是默认的val。save_txt会把每张测试图的预测结果保存为 YOLO 格式的文本文件,方便你自己写脚本做边界框级分析——比如统计每个类别的框数量、计算误检和漏检的具体分布。
save_json=True会生成 COCO 格式的评估结果文件,里面包含每个类别的precision、recall、ap等详细指标。如果你要在项目报告里附上指标表,这个 JSON 文件可以直接转成表格。
6.2 自己写一个混淆矩阵辅助分析
YOLO 自带的混淆矩阵图是归一化后的,对于工业场景,我更习惯看绝对数量的版本——知道具体哪两个类别最容易互相搞混。比如crack和line在视觉上确实难分,如果混淆矩阵显示这两个类互相误检很多,就要考虑是否把这两个类别合并成一个,或者给这两个类的损失加上更大的权重。
验证脚本跑完后,用一个推理脚本在测试图上实际画出预测框和置信度:
# predict_and_visualize.py from ultralytics import YOLO model = YOLO('runs/tile_defect/yolov8n_9cls/weights/best.pt') results = model.predict( source='dataset/images/test', conf=0.25, # 置信度阈值,工业场景建议 0.3~0.5 iou=0.45, # NMS 的 IoU 阈值 save=True, project='runs/predict_test', name='tile_9cls' )这里的conf参数值得多提一句:训练时 mAP 的计算基于很低置信度阈值,但实际产线上如果置信度阈值设得太低,误检会大量涌现。我一般建议从 0.25 起步,观察误检情况再上调到 0.4 或 0.5。调参时关注的不只是 mAP,还有每张图的平均误检数——这个指标产线上更实际。
最后的验证闭环是拿几张从未出现在训练和测试集里的现场图片来跑推理。数据集划分得再好,也替代不了现场实际拍摄的光照和纹理差异。我见过太多数据集指标 98% 的项目,一到产线就掉到 80%——原因多半是现场光照角度和数据集里的照片差异太大。在做项目交付时,一定要预留一部分现场数据做最终验证,不然上线后翻车是大概率事件。
这个数据集本身的价值,在于把“从零开始整理数据”这个最耗时耗力的环节直接跳过了。你用它的正确姿势,是先跑可视化脚本确认数据质量,再跑基线模型拿到第一版指标,然后根据指标暴露出的短板决定是补数据还是调参。我自己做工业检测项目时,最深的教训是:永远不要把数据集指标当成最终结果,测试集上的绝对数字远不如模型在真实场景里的误检漏检分布更有参考价值。希望这份拆解能帮你把第一条验证跑通,少走几步弯路。
本文还有配套的精品资源,点击获取