简介面向工业视觉检测场景这套玻璃表面缺陷实例分割数据集覆盖110twohightglass、GlassDirty、GlassLoss、PolymeDirty四类常见缺陷标注采用YOLO格式多边形点坐标可直接加载至主流框架开展实例分割模型训练。数据集图片总计1230张训练集854张、验证集248张、测试集128张划分均衡方便直接进行模型训练、验证与精度评估。压缩包共2000个文件以768张jpg原始图像和1230个txt标注文件为主体另附1个yaml配置与1个docx说明文档整体约75.66MB结构清晰便于快速定位。缺陷样本覆盖多种形态与场景、边界标注精细适用于玻璃及聚合物材料产线的缺陷检测系统开发、自动化质量控制及学术研究亦可用于教学培训。已有355人学习查看对有工业缺陷检测建模需求或算法研究需求的开发者来说是一份可直接落地的标注数据支撑。1. 玻璃表面缺陷为什么必须用实例分割而不是普通目标检测玻璃表面缺陷检测是工业质检里最容易被低估的场景。划伤、擦伤、气泡、杂质点这些缺陷肉眼看着都费劲普通目标检测的矩形框一画直接把缺陷周边的正常纹理、背景货架、反光区域全包进去了。更麻烦的是玻璃是透明的透过缺陷能看见背后的东西检测框会把背景也算进特征里模型很容易学歪。实例分割的粒度是像素级的——每一个缺陷像素都要标出来这直接决定了后续量测缺陷长度、面积、判断严重等级能不能落地。这份“玻璃表面缺陷实例分割数据集”解决的正是这件事把缺陷逐像素抠出来而不是画个框交差。适合正在做工业质检、玻璃制造产线视觉方案、以及纠结“用检测还是分割”的从业者也适合想拿真实工业数据练手 YOLOv8 实例分割的新手。数据集的标注格式、类别体系、以及训练时的坑下文逐个拆开讲。2. 数据集内部结构标注格式、类别体系与拍照样本分布2.1 解压后你能拿到什么拿到的是一个 zip 压缩包打开之后里面是标准的图像分割数据集目录。无论你之前用的是 COCO 还是 YOLO 格式这套数据集的目录设计都比较接近主流习惯。常见的目录布局如下glass_defect_dataset/ ├── images/ │ ├── train/ # 训练图像 │ ├── val/ # 验证图像 │ └── test/ # 测试图像 ├── annotations/ │ ├── instances_train.json # COCO 格式训练标注 │ ├── instances_val.json │ └── instances_test.json ├── labels/ │ ├── train/ # YOLO 格式训练标注txt │ └── val/ # YOLO 格式验证标注txt ├── classes.txt # 类别清单 └── data.yaml # YOLO 训练配置这个布局的好处是既保留了 COCO 的完整标注信息又预生成了 YOLO 实例分割需要的 txt 标签省去了自己写转换脚本的功夫。不过我还是建议你把instances_train.json打开看一眼因为 COCO 标注里藏着很多 YOLO txt 里看不到的数据——比如每个缺陷的面积、bbox 坐标、iscrowd 标记这些信息在后续做数据分析和清洗时非常有用。我拿到任何一份数据集的第一件事永远是检查类别清单和标注数量而不是直接开训。这里也一样。2.2 类别体系玻璃缺陷到底有哪几类从工业玻璃缺陷检测的常见分类来看这份数据集的类别大概率落在以下范围里类别名称缺陷特征检测难点划伤细长线条状方向随机长宽比极高小目标居多擦伤片状磨痕灰度变化小对比度低易漏检气泡圆形或椭圆内部中空边界模糊反光干扰杂质点黑色或其他颜色颗粒面积小数量多崩边边缘块状缺损位置固定在边缘区域打开classes.txt可以确认实际的类别数量和名称。如果只有三四类训练难度会低一些如果超过五类类别间相似度高比如擦伤和划伤在视觉上就有重叠对分割精度就会有明显挑战。为什么类别这件事重要因为实例分割模型对类别数量非常敏感YOLOv8-seg 默认是 80 类 COCO 预训练权重你的数据集类别只有几类微调时最后一层的卷积核结构会改变配置必须改对。2.3 COCO 标注长什么样instances_train.json里最核心的两个字段是images和annotations。images记录每张图的文件名、宽高和 idannotations记录每个缺陷实例的分割多边形、bbox 和类别 id。一个典型的标注片段长这样{ id: 1, image_id: 0, category_id: 1, bbox: [120.5, 88.3, 45.2, 12.8], area: 578.56, segmentation: [ [120.5, 88.3, 145.2, 89.1, 165.7, 96.2, 150.3, 101.1, 120.5, 88.3] ], iscrowd: 0 }bbox是 [x, y, width, height] 格式segmentation是多边形顶点坐标列表。注意这里的area不是像素面积而是多边形面积在做数据筛选时可以按这个字段过滤掉面积过小的标注。检查这份 json 时重点看三件事第一有没有iscrowd1的标注如果有意味着某些重叠区域被标注为大块群体训练时会被跳过第二area的分布是否均匀如果小目标占绝大多数后面训练必须调small类的超参数第三segmentation多边形的顶点数量顶点过多在转 YOLO 格式时会被简化损失精度。2.4 YOLO 格式的 txt 标签怎么对应YOLOv8 实例分割的 txt 标注格式是每一行代表一个实例格式为class_id x1 y1 x2 y2 x3 y3 ... xn yn所有坐标都归一化到 0~1 之间用图像宽高做除法。比如刚才那个 json 的 bbox 如果是 1200x800 的图像第一个归一化坐标就是 120.5/12000.1004、88.3/8000.1104。打开一个 txt 标签检查确认坐标是否都在 0~1 范围内类别 id 是否从 0 开始连续编号。这是最容易翻车的地方——很多数据集转换脚本会把类别 id 从 1 开始YOLO 模型会直接报错或者把背景当第一类。3. 用 YOLOv8 训练玻璃缺陷实例分割从配置到跑通3.1 为什么选 YOLOv8-seg 而不是 Mask R-CNN玻璃缺陷数据集的标注量通常不会特别大几百张到几千张左右。这种量级下两步检测器如 Mask R-CNN 也能工作但训练时间和显存占用都很不友好而且对数据增强的依赖更强。YOLOv8-seg 是单阶段的推理速度快显存占用少在 GPU 有限的情况下也能跑得动最关键的是配合这份数据自带 YOLO 格式标签几乎零成本就能接进来。YOLOv8-seg 的分割头和检测头是并行的输出同时包含每个实例的 bounding box 和 mask 多边形。它跟语义分割最大的不同在于同一类别的两个相邻缺陷会被当成两个实例分别输出——这就是“实例分割”的核心价值玻璃上两相邻的划伤如果连在一起会被当成一个实例但如果是两个独立事件模型会输出两个单独的 mask 和两个置信度。质检时你要的是每个缺陷单独计数、单独量测而语义分割给不了这个。3.2 准备工作装环境、确认显卡我建议直接用官方 ultralytics 包命令很简单pip install ultralytics装完以后先跑一个快速自检确认 GPU 是否被正确识别。这一步很多人会跳过然后训练到一半才发现用 CPU 在跑十几分钟一个 epoch 直接心态炸裂。python -c import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU only)如果输出True和你的显卡型号就没问题如果是False要么是 PyTorch 装成了 CPU 版本要么是 CUDA 驱动版本不匹配。先卸载再装对应 CUDA 版本的 PyTorch别硬着头皮用 CPU 跑。3.3 修改 data.yaml打开数据集里的data.yaml确认路径正确。这个文件是 YOLOv8 训练时读取数据集的入口路径错了会直接报Dataset not found。长这样path: /path/to/glass_defect_dataset train: images/train val: images/val test: images/test names: 0: scratch 1: abrasion 2: bubble 3: impurity把path改成你实际的绝对路径names的顺序必须与classes.txt完全一致。顺序错了模型训练时类别对应就会全部错位推理出来的缺陷类别就是乱的。3.4 安装训练脚本并跑通第一个 epoch确认环境后直接用 ultralytics 的命令行接口训练。我一般先跑一个最小的 epoch 数验证流程确认数据加载没有坑再正式开训yolo segment train modelyolov8n-seg.pt datadata.yaml epochs1 batch8 imgsz640 device0如果第一个 epoch 能跑完并且 loss 有输出说明数据加载、标签读取、模型前向传播都正常。如果报错先看是不是标签格式问题——最常见的报错是Label shape error或者坐标超出边界。打开出错的 txt 标签看一眼确认归一化坐标计算正确。能跑通之后再把 epoch 提到 100 或者 150batch 大小根据显存调整。8GB 显存跑yolov8n-seg用 batch8 没问题跑yolov8m-seg或更大模型时 batch 降到 4。3.5 训练参数对照表训练时最常调的几个参数列个表记一下参数默认值建议说明imgsz640640~1280玻璃缺陷很小可适当提高到 1024但显存占用翻倍batch164~16以显存不爆为前提越大越好epochs100100~200看验证集 mAP 是否还在涨patience10050早停轮数防止过拟合死磕workers84~8数据加载线程数Windows 上过高容易报错optimizerautoSGD 或 AdamW小数据集我用 SGD momentum0.937注意imgsz对实例分割的影响比目标检测更大因为 mask 是像素级输出分辨率不够小缺陷的轮廓会糊。但也不要盲目拉高640 是 16 的倍数1088、1152 这类 32 倍数会更快训练和推理速度差异明显。3.6 训练完必须做的事训练完后会自动保存best.pt和last.pt在runs/segment/train/weights/下。best.pt是按验证集 mAP 选的最优权重默认用它做后续推理和导出。先跑验证确认精度yolo segment val modelruns/segment/train/weights/best.pt datadata.yaml输出里会给出mAP50、mAP50-95和每个类别的 AP。看一眼是不是有某个类别的 AP 明显比其他低比如杂质点的 AP 只有 0.5 而划伤是 0.9那就说明这个类别的样本量不够或者特征太弱后面要么加数据要么调权重。4. 避坑记录从 zip 解压到训练损失不降的四条实战教训4.1 解压报错导致数据不完整现象zip 文件解压到一半报CRC failed或者unexpected end of data但解压出来的目录看起来是完整的训练也能跑起来就是验证精度始终上不去。原因zip 在传输过程中文件损坏或没下载完整解压工具碰到错误自动跳过了部分文件。你看到的是残缺的数据集缺的恰恰可能是某些类别的关键样本。解决重新下载 zip用命令行解压并开启测试模式不要用什么“静默解压”。Linux 上用unzip -t file.zip测试压缩包完整性Windows 上用 7-Zip 的「测试归档」功能。确认无报错再解压。从那以后我每次下载数据集第一件事永远是unzip -t这能省掉后面所有莫名其妙的问题。4.2 类别 id 对不齐导致模型白训现象训练过程中没有任何报错loss 照常下降但验证集上所有类别的 mAP 都是 0 或者极低推理时输出完全错乱。原因data.yaml里的names顺序与classes.txt不一致。比如classes.txt里第 0 类是 scratch但你data.yaml里第 0 类写的是 bubble模型学到的特征和标签对不上全乱了。解决写一个小脚本自动比对别肉眼核对# 检查类别对齐是否一致 with open(classes.txt, r) as f: class_lines [line.strip() for line in f.readlines()] import yaml with open(data.yaml, r) as f: data_cfg yaml.safe_load(f) yaml_names list(data_cfg[names].values()) print(classes.txt:, class_lines) print(data.yaml :, yaml_names) assert class_lines yaml_names, 类别顺序不一致立即停止训练 print(类别对齐正常)跑这个脚本比对结果把data.yaml改成与classes.txt完全一致的顺序。很多人以为这类问题只会出现在新手身上实际上我见过不止一次把 pre-trained 权重的类别顺序带过来的情况——迁移学习时类别映射错了模型训练一百个 epoch 都是空转。4.3 小目标缺陷太多loss 不降反升现象训练时box_loss和seg_loss在前面几个 epoch 降得很快但到 30 个 epoch 之后开始震荡甚至上升验证集的 mAP50 始终在 0.6 徘徊上不去。原因玻璃缺陷中的划伤和杂质点大多数是小目标像素占比可能不到 1%。YOLOv8 默认的 anchor 和分配策略对中大型目标做了加权小目标的梯度信号弱模型容易在小目标上反复震荡。解决改两个地方。第一把imgsz从 640 提高到 1024 或 1280相当于把小目标放大后送入网络第二开启 mosaic 和 copy-paste 增强让模型在小目标样本上多“看”几次。训练命令改成yolo segment train modelyolov8n-seg.pt datadata.yaml epochs150 imgsz1024 batch4 mosaic1.0 copy_paste0.5如果显存不够跑 1024就降到 896同时把 batch 调到 2~4。我自己的经验是小目标问题上imgsz的提升比增加 epoch 更有效——你让模型多看小目标不如让模型“看仔细”一点。4.4 反光区域被当成缺陷现象验证集上 mAP 不低但到新产线的图片上测试时玻璃反光区域的误检率特别高。模型把光照反射的亮斑识别成了杂质点或者气泡。原因数据集的标注人员在标注时没有把反光区域标注成背景模型就学了两个特征——缺陷像反光反光像缺陷。本质是训练数据的背景多样性不够模型没有见过足够多的、没有缺陷的反光玻璃表面。解决这类问题靠调参是治不了的只能从数据上补。把产线上拍到的反光严重的坏图收集起来单独建一个backgrounds文件夹用脚本切成训练同尺寸的图块不需要标注作为负样本混进images/train里对应的 txt 标签为空文件。训练时模型会把这些图片当成“什么目标都没有”从而学会反光不等于缺陷。这个操作对提升精确率的帮助立竿见影。4.5 训练时显存溢出现象CUDA out of memory在训练中期出现前面几个 epoch 明明挺正常。原因前面 epoch 用的是随机 crop后面 mosaic 增强把多张图拼在一起实际输入尺寸可能超过imgsz设置几倍显存压力峰值出现在后半程。解决降低 batch 到 2 或者 4同时关掉cacheTrue这个参数会把数据集全缓存到显存很吃显存。如果还爆就换yolov8n-seg或把imgsz降到 640。别硬扛分布式训练或者梯度累积对单卡来说都是绕远路直接降 batch 最有效。5. 进阶用法大图切片推理与 mAP 评估的落地技巧5.1 大图切片推理产线相机拍出来的图通常不止 640x640很多是 2000 万像素以上的大图。直接把大图丢给训练好的模型推理有两个问题一是小缺陷被压缩到十几个像素根本保不住二是显卡显存扛不住一张 4000x3000 的图完整推理。标准做法是切块sliding window。我维护了一套简单的切片推理流程def tile_inference(model, image, tile_size640, overlap0.2, conf_thres0.25): h, w image.shape[:2] step int(tile_size * (1 - overlap)) detections [] for y in range(0, h, step): for x in range(0, w, step): # 边界裁剪保证切片不超过图像范围 tile image[y:ytile_size, x:xtile_size] # 使用训练好的模型推理切片 results model(tile, confconf_thres, verboseFalse) for box in results[0].boxes: cls int(box.cls) conf float(box.conf) x1, y1, x2, y2 map(int, box.xyxy[0]) # 坐标映射回原图坐标系 detections.append({ class: cls, confidence: conf, bbox: [x1x, y1y, x2-x1, y2-y1] }) # 合并重叠区域的检测结果用 NMS 去重 merged non_max_suppression(detections, iou_threshold0.5) return mergedoverlap 设 0.2 就够用太小切片边缘的缺陷会被切没太大会让同一处缺陷被重复推理NMS 合并的算力开销变大。还需要注意推理前把conf_thres调低到 0.15~0.2因为切片后小缺陷的置信度本来就偏低用训练时的 0.25 会滤掉很多真缺陷。5.2 用 mAP50-95 评估而不是只看 mAP50很多人训练完只看 mAP50——也就是预测框和真实框的 IoU 在 0.5 时算出来的平均精度这个数值很容易到 0.9显得模型很能打。但玻璃缺陷检测真正关心的是 IoU0.75 甚至 0.9 时的表现因为缺陷的面积、长度量测需要 mask 边界足够贴近真实轮廓。边界偏移了几个像素质检系统算出来的划伤长度就会有偏差。所以评估时我建议记住两组数mAP50 判断“找到没找到”mAP50-95 判断“找得准不准”。如果 mAP50 还行、mAP50-95 拉胯说明模型目标的位置大致对但 mask 边缘质量差原因大概率是标注多边形的顶点数太少转成 YOLO 格式时轮廓丢失了细节。解决办法是用标注工具重新生成高密度多边形或者接受当前精度、在生成切片时把 overlap 调高一点来补偿边界误差。5.3 从预测 mask 里量测缺陷尺寸实例分割模型的输出本质是一组 mask 坐标对这和 bbox 完全不同——mask 算面积、算长度、算主轴方向都比 bbox 稳定。我在玻璃缺陷项目上经常做一个后处理对每个预测 mask 计算面积和等效椭圆的长轴长度用这两个数值做缺陷等级分类。面积小于一定阈值的直接当作粉尘忽略长轴超过阈值的才判定为致命划伤这个逻辑完全依赖实例分割的像素级输出普通目标检测是给不了这种量测精度的。从那以后我每次拆一份工业缺陷数据集都会强制走一遍这套流程先验压缩包完整性再比类别对齐然后拿最小配置试跑一个 epoch最后才动imgsz和增强参数。这套习惯帮我避开过太多看起来“毫无来由”的翻车数据集的坑拦在训练之前总比训完一百个 epoch 才暴露要好。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?