ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YOLO目标检测实战:瓷砖裂缝数据集解析与可视化避坑指南

YOLO目标检测实战:瓷砖裂缝数据集解析与可视化避坑指南 简介面向瓷砖表面缺陷检测任务这套YOLO格式数据集包含裂缝与正常两个类别约一千七百余张经过标注的瓷砖图像并已划分好训练目录附带说明两个类别的classes.txt文件和Python可视化脚本适合工业质检、目标检测入门或算法快速验证。压缩包采用7z格式共两千个文件其中一千七百多个文本标签记录边界框坐标两百多张实际图像用于训练另有一个无须修改即可运行的绘图脚本整体约九十一点七五MB。目前已有约两百人学习。数据对部分样本做翻转、加噪等增强可帮助提升模型的泛化能力可视化脚本随机传入一张图片即可绘制边界框并保存到当前目录方便直接核对标注质量节省人工检查与重复开发的时间拿到后便能接入YOLOv5等主流框架进行训练。1. 先看明白这份瓷砖裂缝数据集到底能解决什么问题真正把新手卡在YOLO门外的常常不是网络结构而是那份“拿到手就能直接跑”的数据集。瓷砖表面裂缝就是一类典型的细长小型缺陷它在釉面纹理里只有几个像素宽颜色与底色接近人工标注费眼模型训练起来又特别容易学偏所以一套带完整标签、划分好训练与验证集的裂缝数据价值往往比一打理论PPT高得多。这份资源收录了大约1700张瓷砖表面图像PNG格式用labelImg按YOLO格式标注一共2类——裂缝和正常标签文件与图片分目录存放classes.txt已写清类别顺序还附带一个可视化脚本随机传一张图就能画出边界框并存到当前目录不需要改任何路径。想做工业缺陷检测的算法验证或者想入门YOLO训练全流程这份资源可以作为第一个能直接跑的样本项目。2. 拆解数据集结构标签格式、目录划分与增强边界2.1 先读懂标签文件YOLO格式没你想的那么玄学标签是txt文本每一行代表一个目标框格式固定为class_id x_center y_center width height坐标都是归一化后的相对值也就是真实像素坐标除以图片宽高。labelImg导出时默认就输出这种格式。数据集文件名里藏着信息N217、N188这类前缀对应normal类别正常C209、C39这类前缀对应crack类别裂缝原始图片在标注后统一转成PNG保存。刚上手的人最容易把归一化坐标当成像素坐标来画框画出来全部偏到图外面这类问题在后面的避坑章节会展开讲。在一头扎进训练之前先写一小段脚本把标签读明白。下面这段可以视为可视化脚本的最小核心能帮你把任意一张图和它的txt还原成带框图片import cv2 def draw_from_txt(img_path, txt_path, output_path): img cv2.imread(img_path) h, w img.shape[:2] # 原图尺寸归一化坐标要乘回来 with open(txt_path, r, encodingutf-8) as f: for line in f.readlines(): line line.strip() if not line: continue parts line.split() cls_id int(parts[0]) # 类别ID x_center, y_center float(parts[1]), float(parts[2]) bw, bh float(parts[3]), float(parts[4]) # 归一化 - 像素坐标 x1 int((x_center - bw / 2) * w) y1 int((y_center - bh / 2) * h) x2 int((x_center bw / 2) * w) y2 int((y_center bh / 2) * h) color (0, 0, 255) if cls_id 0 else (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, str(cls_id), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 1) cv2.imwrite(output_path, img)这段逻辑是整个可视化脚本的地基。x_center、y_center是0到1之间的相对值必须乘以原图宽高才能还原成像素坐标width、height同理。cls_id为0时画红色框对应裂缝为1时画绿色框对应正常这个颜色习惯在工业缺陷可视化里最常用。注意cv2.imread按文件内容解码而不是按后缀判断所以就算图片后缀是.jpg但实际编码是PNGOpenCV也能正确读出来——这一点在后面的避坑章节还会专门提。顺带说一句这套标签格式不止瓷砖能用轴承表面缺陷检测、齿轮损伤检测这类工业缺陷任务标注格式和读取逻辑几乎一模一样。2.2 目录结构与class文件YOLO能直接吃的标准组织方式labelImg标注完成后图片和txt标签分别保存在不同目录中这是YOLO系列训练脚本默认接受的布局。拿到资源后建议先按下面这个结构核对一遍dataset/ ├── images/ │ ├── train/ │ │ ├── C209_jpg.rf.b672214ed5ee6f2384b9f8db39305224.jpg │ │ └── N217_jpg.rf.cc836bba4d8c9d066097b32b5915fd3f.jpg │ └── val/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── C209_jpg.rf.b672214ed5ee6f2384b9f8db39305224.txt │ │ └── N217_jpg.rf.cc836bba4d8c9d066097b32b5915fd3f.txt │ └── val/ │ └── ... └── classes.txtYOLO训练时要求同名的图片和标签分别放在images/与labels/下靠文件名一一对应只有前缀不同、后缀不同.jpg对.txt。所以拿到数据集第一件事是检查有没有图片文件找不到对应txt、或者txt是空文件的情况这类问题训练时不会直接报错但会表现为验证集精度莫名其妙很低。classes.txt这里只有两行内容是类别ID类名说明0crack裂缝1normal正常类别顺序就是模型输出的ID映射。第一行crack对应class_id0第二行normal对应class_id1。这个顺序一旦和训练配置里的names不一致检测结果就会把裂缝全标成正常属于最隐蔽的翻车方式。目录各角色在训练中的作用可以这样对应目录/文件作用在YOLO训练中的角色images/train训练图片集train路径images/val验证图片集val路径labels/train训练标注文本读取标签目标labels/val验证标注文本评估时读取classes.txt类别名列表与data.yaml中的names对应2.3 为什么做翻转和噪声增强而不是旋转和颜色抖动这份数据集的说明里提到“对部分数据集进行翻转、添加噪声点数据增强”这两个操作不是随手选的。瓷砖裂缝的特点是走向随机有的横、有的竖水平翻转和垂直翻转能让模型对裂缝方向不敏感本质上是免费扩充样本的方向多样性。而噪声点模拟的则是产线低照度环境下相机传感器的热噪点、瓷砖表面的粉尘颗粒让模型学会在干扰中定位裂缝而不是靠“图片很干净”这种捷径。相比之下随机旋转、随机缩放、颜色抖动这类通用增强在裂缝检测里容易出事。裂缝只有几个像素宽旋转一定角度就变成断线缩放倍数稍大就会抹掉细缝细节颜色抖动在浅色瓷砖上会让裂缝对比度进一步丢失模型学到的特征直接失效。翻转和加噪声是相对安全的两类增强这也是这个数据集选择它们的原因。做翻转增强时有一个必须同步处理的环节——标签。图片翻转了框的坐标不跟着变训练就是在学错位映射import cv2 def flip_image_and_label(img, txt_path, flip_code1): # flip_code: 0垂直翻转, 1水平翻转, -1水平垂直 img_flip cv2.flip(img, flip_code) with open(txt_path, r) as f: lines [ln.strip() for ln in f if ln.strip()] new_lines [] for ln in lines: parts ln.split() cls_id, cx, cy, bw, bh parts[0], float(parts[1]), float(parts[2]), \ float(parts[3]), float(parts[4]) if flip_code 0: # 垂直翻转Y方向映射 cy 1.0 - cy elif flip_code 1: # 水平翻转X方向映射 cx 1.0 - cx else: # 两者都翻 cx, cy 1.0 - cx, 1.0 - cy new_lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) return img_flip, new_lines增强的核心原则是“图片变了标签必须跟着变”。水平翻转时x_center变成1 - x_center垂直翻转时y_center变成1 - y_center否则框就跑到错误位置。椒盐噪声的比例一般控制在0.01左右太高会把浅色砖面搞得像花斑模型反而去学噪声太低又起不到抗干扰的作用。1700张的规模对单个工业场景来说不算大但配合翻转和噪声增强用来做迁移学习预训练或者验证检测流程已经够用。真正需要注意的是类别不平衡——正常样本数通常远大于裂缝样本数增强应该优先补裂缝这一侧而不是盲刷正常样本。3. 可视化脚本实战不改路径跑通、看出标签问题3.1 脚本核心逻辑读图片、解析txt、画框、存当前目录数据集自带的可视化脚本逻辑上是上一章draw_from_txt函数的完整封装做了三件事读取图片和它的同名txt把归一化坐标还原成像素坐标画框把结果写到当前目录。脚本开头定义类别颜色映射中间通过glob找到图片对应的txt文件末尾用cv2.imwrite保存为vis_前缀的新文件。默认情况下脚本自动从图片目录里随机挑一张传参时则画指定图片所以“无需更改路径直接运行”这件事靠的是目录约定。贴近自带脚本行为的简化版长这样import cv2 import glob import random import os CLASS_COLORS { 0: (0, 0, 255), # crack 裂缝红色 1: (0, 255, 0), # normal 正常绿色 } def visualize_one(img_path): img cv2.imread(img_path) h, w img.shape[:2] # 按目录约定找到同名标签images - labels后缀 .jpg - .txt txt_path img_path.replace(/images/, /labels/).rsplit(., 1)[0] .txt if not os.path.exists(txt_path): print(f找不到标签: {txt_path}) return with open(txt_path, r, encodingutf-8) as f: for line in f: line line.strip() if len(line) 0: continue parts line.split() cls_id int(parts[0]) cx, cy, bw, bh map(float, parts[1:]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) color CLASS_COLORS.get(cls_id, (255, 255, 255)) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, str(cls_id), (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 1) output vis_ os.path.basename(img_path) cv2.imwrite(output, img) print(f已保存: {output}) if __name__ __main__: # 不带参数随机挑一张带参数画指定图片 candidates glob.glob(images/train/*.jpg) glob.glob(images/val/*.jpg) path candidates[random.randrange(len(candidates))] visualize_one(path)这一版在自带脚本思路上简化到只剩核心正好能看到可视化脚本在黑匣子里做的事。replace(/images/, /labels/)是把图片路径切到标签路径前提是目录结构符合2.2节的约定rsplit(., 1)[0] .txt是把后缀换成txt。CLASS_COLORS里红绿区分两个类别如果画出来的颜色和预期不一致第一反应就应该是class_id读错了。脚本默认随机选图适合快速浏览想画指定图片把路径传给visualize_one即可。自带脚本默认“不用改路径就能跑”靠的就是这套约定优于配置的目录假设。3.2 随机选图跑一遍三条判断标准拿到资源后的第一步建议是直接运行可视化脚本python visualize.py # 无参数随机抽取一张图画框后保存为 vis_xxx.jpg 到当前目录 python visualize.py images/val/N244_jpg.rf.4c37c002bb2014efd44707997c9985c8.jpg # 带参数指定要检查的图片输出同样保存到当前目录第一次跑的时候不带参数连抽十几张观察不同图片的画框结果。重点看三处裂缝框是否贴合裂缝两端而不是把大片空白区域包进去正常样本是不是也画了框文件名前缀不同的图片crack和normal的框颜色是否符合CLASS_COLORS定义。这个动作很快但能暴露大部分数据集质量问题也是训练前性价比最高的检查手段。3.3 用可视化结果反向检查标注质量跑完可视化后可以按下面这个对照表快速定位问题可视化现象可能的标注问题建议处理框明显比裂缝大一圈标注框未收紧包进了太多砖面纹理用标注工具打开沿裂缝端点重新画同一张裂缝图没显示任何框标签文件与图片文件命名不匹配检查txt是否与jpg同名、是否在同一目录层级两张正常样本的颜色标签不一致类别ID映射与classes顺序不一致以classes.txt顺序为准检查映射代码框大量偏移、一半在图外归一化坐标被当成像素坐标直接使用按2.1节的转换公式重新计算这里想多说一句“正常”类别的标注策略。正常样本的框有两种标法一种是把整块砖面框出来另一种是干脆不标任何框。这两种策略YOLO都能训练因为未标注区域会被当作背景负样本但如果标了整砖normal类学到的就是“全图框”检测时告诉你“这块砖没问题”这类训练在验证时mAP会很高实际表现却一般。关键不在于哪种策略更好而在于train和val必须保持同一个标注口径否则评估指标会非常奇怪——可视化脚本能帮你一眼看出两边的标注口径是否一致。4. 避坑瓷砖裂缝数据集实战中最容易翻车的5个坑4.1 标注与目录结构相关的坑坑一图片实际是PNG文件名后缀却是.jpg。现象训练脚本跑起来不报错但偶尔有图片读取后颜色通道错乱或者某些按后缀解析的库直接解码失败。原因很多数据集在采集时原始文件是jpg后期经过增强、转码后存成PNG文件名后缀却没同步改。OpenCV的imread按文件内容探测编码所以没问题但PIL的Image.open、部分数据加载库按后缀判断解码方式就会花屏或报错。解决训练前统一跑一遍格式检查用cv2.imread读入后校验img.shape和img.dtype或者干脆把所有图片统一转成PNG并同步改名。我一般会写一个三行的遍历脚本把不满足要求的文件单独列出来避免训练中途才暴露。坑二classes.txt类别顺序被改动导致标签错配。现象训练时loss下降正常但跑出来的检测结果把裂缝全识别成normal可视化时颜色也全部反掉。原因classes.txt的顺序就是模型输出的ID映射一旦和训练配置文件里的names不一致标签与类别名就全错位了。解决永远以classes.txt为准。训练前打印一次names对照确认第一项是crack、第二项是normal不要用自己手写的类别名单替换。坑三标签文件里混入空行、或一行只有class_id没有坐标。现象训练时偶尔报错或者YOLO解析标签时静默跳过该文件导致某张图的标签缺失精度莫名下降。原因labelImg保存过程中误操作、人为删改、传输损坏都会产生坏标签文件。空行会被continue跳过还好只有一列或四列的残缺行会让解析器直接翻车。解决写脚本遍历所有标签文件过滤掉空行和字段数少于5的记录输出坏文件名的清单。人工核对清单后再考虑是重新标注还是删掉这张图。4.2 数据增强与数据划分相关的坑坑四翻转图片后标签没有同步翻转。现象增强后的训练图里裂缝在左边但框画在右边训练时模型学的是“左边裂缝配右边框”的错位映射收敛慢且检测偏移明显。原因很多人只对图片做cv2.flip忘了对归一化坐标做对应修正。这是数据增强里最常见的翻车点没有之一。解决水平翻转必须执行cx 1.0 - cx垂直翻转必须执行cy 1.0 - cy2.3节的代码可以直接复用。做完增强后再跑一遍可视化脚本抽查十几张确认框和裂缝重合。坑五随机划分训练集和验证集导致评估指标虚高。现象验证集mAP轻松到0.95以上一上实际检测线就漏检严重黑匣子怎么调都救不回来。原因同一批次瓷砖的图像高度相似——光照、纹理、拍摄角度几乎一致。随机划分会把同批相似图片同时放进train和val模型相当于在考场上见过“相似答案”验证分数自然漂亮。解决按文件名前缀分组划分。这份数据集里N和C开头的图片分别对应不同状态建议按前缀或者按采集批次切片而不是随机打散。更稳妥的做法是先跑一遍可视化把同一块砖的多个视角找出来成组划分到同一侧。这类问题不是这份数据集特有几乎是所有工业缺陷数据集共有的通病。拿到任何带标注的检测资源第一步都应该是先跑检查脚本再谈训练。5. 收尾技巧训练前强制过一遍可视化再核对data.yaml两处路径我拿到这份瓷砖裂缝数据集后的固定流程是两件事。第一件全量跑一遍可视化脚本按3.3的对照表抽样检查二十张以上确认标注口径统一。第二件写data.yaml时严格核对路径与类别名。YOLOv5和YOLOv8通用的配置长这样path: ./dataset # 数据集根目录 train: images/train # 相对path的训练图片目录 val: images/val # 相对path的验证图片目录 nc: 2 # 类别数 names: [crack, normal] # 与classes.txt保持一致path字段定义根目录train和val用相对路径。很多训练报错都出在这个配置上——path写错成绝对路径、names和classes.txt顺序不一致、val指向了空目录可视化脚本能暴露前两类问题但val目录为空只能靠ls检查。顺手看一眼images/val里的文件数量确认不是0再启动训练。训练过程中还有一个小技巧值得养成习惯看box_loss和cls_loss两条曲线的下降节奏。box_loss在降、cls_loss不动优先怀疑类别ID错位或类别不平衡两条都在降但验证集mAP上不去再回头看数据划分是否泄漏。YOLO的损失函数看起来复杂但训练日志里最值得盯的就是这两个分量。从那以后我每次拿到一份新的检测数据集都强制自己先跑一遍可视化脚本再碰训练参数这个习惯帮我躲掉过至少三次因为标签错位、白训几小时的尴尬。希望帮到你。本文还有配套的精品资源点击获取
返回列表