ARTICLE DETAIL

资讯详情

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

塑料瓶缺陷检测数据集实战:YOLO格式解析与YOLOv8训练避坑指南

塑料瓶缺陷检测数据集实战:YOLO格式解析与YOLOv8训练避坑指南 简介本资源为面向工业质检与计算机视觉方向的塑料瓶缺陷目标检测数据集适用于YOLO系列模型训练与算法验证可帮助读者快速搭建缺陷检测实验环境。数据按YOLOv5标准文件夹结构组织已划分训练集约3200张、验证集约130张、测试集约60张每张图片均配有对应txt标注文件类别包含凹陷、缺口、扭曲三类具体以classes文件为准。压缩包共约2000个文件以1999个txt标注与类别文件为主另含1个可视化py脚本整体约117MB。脚本可随机读取一张图片并绘制边界框无需修改即可直接运行便于快速核查标注质量。目前已有91人学习下载适合从事缺陷检测、工业视觉或YOLO改进实战的开发者参考使用。1. 塑料瓶缺陷检测数据集从拿到手到跑通第一轮训练产线上吹瓶机每分钟吐出上百个 PET 瓶瓶身黑点、瓶口缺料、瓶底裂纹这些缺陷靠人眼盯漏检率随班次直线上升。你手上如果正好有一份「塑料瓶缺陷图像目标检测数据集」标注是 YOLO 格式、训练验证已经划分好、还带了 classes 文件那它省掉的恰恰是最耗时的清洗和切分环节。这类数据集通常按缺陷类别组织比如黑点、划痕、变形、瓶口破损每张图配一个同名 txt每行是类别序号 归一化中心x 归一化中心y 归一化宽 归一化高。它适合两类人一类是想快速验证 YOLO 系列模型在工业质检场景落地效果的算法工程师另一类是手里有产线相机但缺标注数据的视觉开发者。下面我按自己跑这类数据集的顺序把目录结构、类别映射、训练参数和翻车点讲清楚。2. 拆开数据集目录结构、classes 文件与标注格式核对2.1 拿到数据集先看这三样东西不管数据集来自哪里解压后第一件事不是急着写训练脚本而是确认三件事图像目录和标签目录是否一一对应、classes 文件里的类别顺序是否和标注里的数字对得上、划分文件是否真的存在。常见的目录长这样plastic_bottle_defect/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── classes.txtclasses.txt一般一行一个类别名行号从 0 开始就是标注里的类别序号。我见过不少人直接拿classes.txt当类别名列表读结果第一行是defect还是black_spot都没确认训练完混淆矩阵全是乱的。核对方法很简单写个脚本统计每个类别序号出现的次数再和 classes 文件行数对照。import os from collections import Counter label_dir plastic_bottle_defect/labels/train class_file plastic_bottle_defect/classes.txt with open(class_file, r, encodingutf-8) as f: classes [line.strip() for line in f if line.strip()] counter Counter() for name in os.listdir(label_dir): if not name.endswith(.txt): continue with open(os.path.join(label_dir, name), r) as f: for line in f: parts line.strip().split() if len(parts) 5: counter[int(parts[0])] 1 print(classes 文件类别数:, len(classes)) for idx, cls_name in enumerate(classes): print(f类别 {idx} ({cls_name}) 标注框数量: {counter.get(idx, 0)})这段脚本做两件事读 classes 文件得到类别总数再遍历训练标签统计每个类别序号出现次数。如果某个类别序号在标注里出现但 classes 文件里没有对应行或者某个类别标注数为 0就要回头查标注是否漏标或类别映射是否错位。参数上注意label_dir要指向训练集标签目录验证集单独再跑一遍确认两个划分的类别分布没有严重偏斜。2.2 YOLO 标注格式的四个边界坑YOLO 格式看着简单但工业缺陷数据集里经常出现四类边界问题。第一类是坐标越界归一化后的中心坐标或宽高小于 0 或大于 1训练时损失会直接爆掉。第二类是宽高为 0标注框退化成一条线YOLO 在计算 IoU 时会出 NaN。第三类是同一张图里类别序号超出 classes 范围比如 classes 只有 4 类但标注里出现了 5。第四类是图像和标签文件名不匹配比如图像叫bottle_001.jpg但标签叫bottle_001.png.txt。import os img_dir plastic_bottle_defect/images/train lbl_dir plastic_bottle_defect/labels/train num_classes 4 # 按 classes.txt 实际行数改 bad_coord, bad_size, bad_cls, missing [], [], [], [] for name in os.listdir(img_dir): stem os.path.splitext(name)[0] lbl_path os.path.join(lbl_dir, stem .txt) if not os.path.exists(lbl_path): missing.append(name) continue with open(lbl_path) as f: for line in f: p line.strip().split() if len(p) ! 5: continue c, x, y, w, h int(p[0]), *map(float, p[1:]) if c num_classes: bad_cls.append((stem, c)) if not (0 x 1 and 0 y 1): bad_coord.append((stem, x, y)) if w 0 or h 0 or w 1 or h 1: bad_size.append((stem, w, h)) print(缺失标签:, len(missing)) print(类别越界:, len(bad_cls)) print(坐标越界:, len(bad_coord)) print(宽高异常:, len(bad_size))这段脚本把四类问题一次性扫出来。num_classes必须和 classes 文件行数一致否则类别越界判断会误报。坐标越界和宽高异常通常来自标注工具导出时的精度问题少量可以手动修量大就要考虑重新导出或写脚本裁剪到 [0,1] 区间。缺失标签的图要么补标要么直接从训练列表里剔除别留着让 DataLoader 报错。3. 用 YOLOv8 跑通第一轮训练配置、命令与参数含义3.1 生成 data.yaml 并确认路径写法YOLO 训练不直接读 classes.txt而是通过一个 yaml 文件告诉模型图像目录、验证目录和类别名。这个文件我一般放在数据集根目录下叫data.yamlpath: /home/user/plastic_bottle_defect train: images/train val: images/val nc: 4 names: 0: black_spot 1: scratch 2: deformation 3: mouth_brokenpath是数据集根目录train和val是相对路径。nc必须等于 names 列表长度也等于 classes.txt 行数。names 的顺序必须和标注里的类别序号严格对应错一个位置训练出来的模型就会把黑点认成划痕。我习惯在写 yaml 之前先把 classes.txt 复制过来逐行核对序号这个动作花不了一分钟但能省掉后面几小时的排查。3.2 训练命令与关键参数怎么设假设你已经装好 ultralytics 包一条命令就能启动训练yolo detect train \ dataplastic_bottle_defect/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/plastic_bottle \ nameexp1modelyolov8n.pt表示从 COCO 预训练权重开始微调工业缺陷数据集通常几千张图从头训容易过拟合用预训练权重收敛更快。imgsz640是输入分辨率如果瓶身缺陷很小比如黑点只有十几个像素可以提到 1024但显存占用会明显上升。batch16在 8GB 显存上跑 640 分辨率一般够用爆显存就降到 8。lr00.01是初始学习率微调场景下如果 loss 震荡厉害可以降到 0.001。patience20表示验证指标 20 轮不提升就早停避免无效训练。训练过程中重点看三个输出box_loss是否稳定下降、mAP50是否在验证集上持续上升、cls_loss是否出现异常尖峰。如果 box_loss 下降但 mAP50 不动大概率是类别不平衡或标注框质量差。如果 cls_loss 突然飙升检查是不是某个 batch 里出现了类别越界的标注。3.3 训练完怎么验证模型真的学到了缺陷训练结束后runs/plastic_bottle/exp1/weights/下会有best.pt和last.pt。别只看 mAP 数字拿几张验证集里没见过的图跑推理肉眼确认缺陷框位置和类别yolo detect predict \ modelruns/plastic_bottle/exp1/weights/best.pt \ sourceplastic_bottle_defect/images/val \ conf0.25 \ saveTrueconf0.25是置信度阈值工业质检场景如果漏检代价高可以降到 0.1 让模型多报一些再人工复核。如果误检太多就提到 0.5。推理结果会保存在runs/detect/predict/下重点看小缺陷有没有被漏掉、瓶口和瓶底的缺陷有没有被混淆。我一般会挑 20 张出来逐张看比盯着 mAP 曲线有用得多。4. 塑料瓶缺陷检测的避坑与排查五条血泪经验4.1 类别序号错位导致 mAP 虚高但实际全错现象训练时 mAP50 能到 0.9 以上但推理时模型把黑点标成划痕把划痕标成变形。原因classes.txt 的类别顺序和 data.yaml 里 names 的顺序不一致或者标注文件里的类别序号是从 1 开始而不是从 0 开始。解决写脚本统计标注里出现的所有类别序号和 names 的 key 逐一对照。如果标注从 1 开始要么全局减 1要么在 names 里补一个占位类别。这个坑我踩过两次第一次排查了一整天才发现是序号偏移。4.2 图像和标签文件名大小写不一致现象训练启动时报No labels found但明明 labels 目录下有文件。原因图像叫Bottle_001.jpg标签叫bottle_001.txtLinux 下文件名区分大小写YOLO 按 stem 匹配时找不到。解决统一转成小写或者写脚本批量重命名标签文件使其与图像 stem 完全一致。Windows 上开发时不容易发现部署到 Linux 服务器就翻车。4.3 验证集里出现训练集图片导致指标虚高现象验证集 mAP 比训练集还高或者高得离谱。原因数据集划分时没有去重同一张图或高度相似的连拍图同时出现在 train 和 val 里。解决用图像哈希或感知哈希对全量图片做去重再重新划分。工业相机连拍产生的相邻帧相似度极高如果按随机划分很容易泄漏。我一般会按时间戳或产线批次划分确保验证集来自不同批次。4.4 小目标缺陷在 640 分辨率下直接消失现象瓶身黑点这种小缺陷在推理结果里完全看不到但标注文件里确实有框。原因YOLO 下采样 32 倍后十几个像素的缺陷在特征图上只剩不到一个像素。解决把imgsz提到 1024 或 1280或者在数据增强里关闭马赛克增强的随机缩放避免小目标被进一步缩小。如果显存不够可以改用 YOLOv8 的 P2 检测头专门针对小目标。4.5 训练中 BN 层崩溃导致 loss 变 NaN现象训练到几十轮时 loss 突然变成 NaN之后再也降不下来。原因某个 batch 里出现了宽高为 0 的标注框或者学习率过大导致梯度爆炸BN 层统计量被污染。解决训练前用 2.2 节的脚本扫一遍宽高异常把 w 或 h 小于 1e-6 的框直接删掉。如果已经出现 NaN降低lr0到 0.001 并加warmup_epochs5让模型在前几轮慢慢适应数据分布。5. 从跑通到可用提升塑料瓶缺陷检测精度的三个进阶技巧第一轮训练跑通只是起点工业质检对漏检率的要求通常比通用目标检测苛刻得多。我一般会从三个方向继续压精度。第一个方向是难例挖掘把验证集里漏检和误检的图挑出来单独复制到一个hard_examples目录在下一轮训练时通过data.yaml把它作为额外的训练集加入或者用copy_paste增强把缺陷区域粘贴到正常瓶身上生成合成样本。第二个方向是调整锚框和损失权重YOLOv8 默认的锚框基于 COCO 数据集塑料瓶缺陷的宽高比和 COCO 差异较大可以用yolo detect train的anchors参数传入自己聚类得到的锚框同时把box损失权重从默认 7.5 提到 10让模型更关注定位精度。第三个方向是推理后处理。工业场景下同一张图里同类缺陷可能相邻NMS 的 IoU 阈值设 0.5 容易把两个靠近的黑点合并成一个。我通常会把iou阈值降到 0.3 并开启agnostic_nms让不同类别的框也参与抑制减少重叠误报。下面这段代码是我常用的验证脚本把推理结果和标注真值做逐类对比输出每个类别的漏检数和误检数from ultralytics import YOLO import os model YOLO(runs/plastic_bottle/exp1/weights/best.pt) val_img_dir plastic_bottle_defect/images/val val_lbl_dir plastic_bottle_defect/labels/val classes [black_spot, scratch, deformation, mouth_broken] for img_name in os.listdir(val_img_dir)[:50]: stem os.path.splitext(img_name)[0] results model(os.path.join(val_img_dir, img_name), conf0.25, iou0.3) pred_cls [classes[int(c)] for c in results[0].boxes.cls] gt_path os.path.join(val_lbl_dir, stem .txt) gt_cls [] if os.path.exists(gt_path): with open(gt_path) as f: for line in f: p line.strip().split() if len(p) 5: gt_cls.append(classes[int(p[0])]) miss [c for c in gt_cls if c not in pred_cls] false [c for c in pred_cls if c not in gt_cls] if miss or false: print(f{img_name} 漏检: {miss} 误检: {false})这段脚本对验证集前 50 张图逐张推理把预测类别和真值类别做集合对比输出漏检和误检的类别名。conf0.25和iou0.3是我在塑料瓶缺陷场景下比较常用的组合你可以根据实际漏检和误检的比例微调。跑完这个脚本你会得到一份具体的难例清单比看整体 mAP 更有针对性。最后说个习惯每次改完参数或增强策略我都会固定用同一批 50 张验证图跑一遍这个脚本记录漏检和误检数量的变化。模型指标是波动的只有同一批图上的对比才能告诉你这次改动到底有没有用。希望帮到你。本文还有配套的精品资源点击获取
返回列表