ARTICLE DETAIL

资讯详情

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

塑料瓶缺陷检测数据集实战:YOLO标注格式解析与训练配置指南

塑料瓶缺陷检测数据集实战:YOLO标注格式解析与训练配置指南 简介本资源为面向工业质检与计算机视觉方向的塑料瓶缺陷目标检测数据集适用于YOLO系列模型训练、算法验证与课程实践帮助解决塑料瓶表面缺陷自动识别问题。数据集按YOLOv5目录结构组织可直接投入检测训练涵盖凹陷、缺口、扭曲三类缺陷类别定义详见classes文件。压缩包共约2000个文件以1999个txt标注文件与1个Python可视化脚本为主整体约117MB训练集约3200张图片及对应标签验证集约130张测试集约60张划分清晰。配套show.py脚本无需修改随机传入一张图片即可绘制边界框并保存至当前目录便于快速核对标注质量。目前已有91人学习下载适合需要现成标注数据、快速复现缺陷检测流程的开发者与研究者参考使用。1. 塑料瓶缺陷检测数据集从拿到手到跑通第一轮训练产线上塑料瓶的凹陷、缺口、扭曲这三类缺陷靠人眼在高速传送带上盯漏检率随班次往后飙升这是很多做包装质检的团队都遇到过的现实问题。这份塑料瓶缺陷图像目标检测数据集就是冲着这个场景来的它按 YOLOv5 的目录规范组织训练集约 3200 张、验证集约 130 张、测试集约 60 张每张图都配好了 YOLO 格式的 txt 标注类别只有三个——凹陷、缺口、扭曲具体以 classes 文件为准。拿到手不用自己再划 train/val/test也不用纠结标注格式转换直接就能喂给 YOLO 系列模型开跑。适合两类人一类是想快速验证缺陷检测方案可行性的算法工程师另一类是刚入门目标检测、需要一个真实工业缺陷数据集练手的新手。下面我按自己拆包的顺序把结构、可视化、训练配置和踩过的坑一条条讲清楚。2. 数据集结构与 YOLO 标注格式先看懂再动手2.1 目录布局与文件对应关系这份数据按 YOLOv5 的标准结构存放核心就是 images 和 labels 两个平行目录各自再分 train、val、test。图片和标签靠文件名主干一一对应xxx.jpg对应xxx.txt缺一个都会在训练时被跳过或报错。项目正文里那串TicketID-10344-h1-asb250_3_exh-_jpg.rf.b50b2e60254a1c8aeb177308716a8f4c.txt就是典型的标签文件名前缀是原始 TicketID 加缺陷类型标识后缀是哈希这种命名在工业数据集里很常见好处是天然去重、不会重名坏处是人眼读起来费劲排查问题时得靠脚本匹配。典型结构长这样dataset/ ├── images/ │ ├── train/ # 约3200张 jpg │ ├── val/ # 约130张 jpg │ └── test/ # 约60张 jpg ├── labels/ │ ├── train/ # 与train图片同名的txt │ ├── val/ │ └── test/ └── classes.txt # 三行凹陷、缺口、扭曲提示classes.txt 里的顺序就是类别索引 0、1、2 的顺序训练配置里的 nc 必须和它一致改一个就得改另一个否则标签全错位。2.2 YOLO 标注格式逐字段拆解YOLO 的标签是每行一个目标格式为class_id x_center y_center width height后四个都是归一化到 0~1 的相对值不是像素。这一点新手最容易翻车拿像素坐标直接写进去训练时框会飞到图外。归一化公式是x_center (x_min x_max) / 2 / img_w宽高同理除以图宽图高。一个凹陷目标的标签行示例0 0.512 0.634 0.187 0.221含义是类别 0凹陷框中心在图片横向 51.2%、纵向 63.4% 处框宽占图宽 18.7%框高占图高 22.1%。三个类别对应关系以 classes 文件为准常见是 0凹陷、1缺口、2扭曲但一定要打开文件确认别凭猜。用一段脚本快速校验标签合法性这是每次拿到新数据集我都会先跑的一步import os import glob def check_labels(label_dir, num_classes3): bad [] for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt, r) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: bad.append((txt, i, 字段数不对)) continue cid int(parts[0]) vals [float(v) for v in parts[1:]] # 类别越界 或 归一化值超出[0,1] if cid 0 or cid num_classes: bad.append((txt, i, f类别越界:{cid})) if any(v 0 or v 1 for v in vals): bad.append((txt, i, f归一化越界:{vals})) return bad if __name__ __main__: issues check_labels(dataset/labels/train) print(f发现 {len(issues)} 处问题) for it in issues[:10]: print(it)逻辑说明遍历标签目录下所有 txt逐行检查字段数是否为 5、类别 id 是否在[0, num_classes)内、四个坐标是否落在 0~1。参数num_classes要和 classes 文件行数一致这里默认 3。跑完如果输出 0 处问题说明标注格式干净可以进入下一步如果有越界多半是类别索引写错或坐标没归一化得回头找标注环节。2.3 训练/验证/测试划分的合理性3200 / 130 / 60 这个比例训练集够厚验证集偏薄。验证集只有 130 张评估 mAP 时波动会比较大同一模型两次评估差几个点都正常别因为一次验证掉点就急着改网络。测试集 60 张更适合做最终一次性验收不适合反复调参看。我的习惯是调参阶段盯验证集趋势别死磕绝对值定稿后再用测试集跑一次作为对外汇报的数字。如果发现验证集评估方差太大可以从训练集里再切一小部分补充验证集但要注意别把测试集污染了。3. 可视化脚本与数据自检先眼见为实再开训3.1 可视化脚本怎么用数据集自带一个可视化 py 文件随机传入一张图片就能画出边界框并保存到当前目录脚本无需改动直接运行。这类脚本的价值在于训练前用眼睛过一遍能提前发现标注框偏移、类别标错、图片和标签不对应这些脏数据问题。工业数据集里 TicketID 命名混乱光看文件名根本判断不了标注质量必须画出来看。典型用法是命令行传图片路径python show.py --image dataset/images/train/TicketID-10344-h1-asb250_3_exh-_jpg.rf.b50b2e60254a1c8aeb177308716a8f4c.jpg脚本内部逻辑一般是读图 → 在同级 labels 目录找同名 txt → 逐行解析归一化坐标 → 乘回图宽图高 →cv2.rectangle画框 →cv2.imwrite存到当前目录。如果你拿到的脚本是随机抽图的版本直接python show.py不带参数也能跑它会自己随机选一张。3.2 自己写一个批量抽检脚本单张看效率太低我一般会写个批量抽检一次画 16 张拼成网格快速扫一遍整体标注质量import cv2 import os import glob import numpy as np import random def draw_one(img_path, label_path, classes): img cv2.imread(img_path) h, w img.shape[:2] if os.path.exists(label_path): with open(label_path) as f: for line in f: cid, xc, yc, bw, bh line.strip().split() cid int(cid) xc, yc, bw, bh map(float, [xc, yc, bw, bh]) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, classes[cid], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img def grid_check(img_dir, label_dir, classes, n16): imgs random.sample(glob.glob(os.path.join(img_dir, *.jpg)), n) tiles [] for p in imgs: name os.path.splitext(os.path.basename(p))[0] lp os.path.join(label_dir, name .txt) tiles.append(cv2.resize(draw_one(p, lp, classes), (320, 320))) rows [np.hstack(tiles[i:i4]) for i in range(0, n, 4)] cv2.imwrite(check_grid.jpg, np.vstack(rows)) if __name__ __main__: classes [凹陷, 缺口, 扭曲] grid_check(dataset/images/train, dataset/labels/train, classes)逻辑说明draw_one负责单张解析并画框grid_check随机抽 16 张缩放到 320×320 拼成 4×4 网格输出。参数classes顺序必须和 classes 文件一致否则框上的文字会张冠李戴。跑完打开check_grid.jpg重点看三件事框是否贴合缺陷区域、类别文字是否合理、有没有该标没标的漏标。这一步花五分钟能省下训练几小时才发现数据有问题的后悔药。3.3 图片与标签配对完整性检查命名带哈希的数据集最容易出的问题是图片有、标签丢或者反过来。训练时 YOLO 默认会跳过没有标签的图但不会大声提醒你结果就是你以为用了 3200 张实际只用了 3000 张。用下面这段对账import os def pair_check(img_dir, label_dir): imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(.jpg)} labs {os.path.splitext(f)[0] for f in os.listdir(label_dir) if f.endswith(.txt)} only_img imgs - labs only_lab labs - imgs print(f图片总数:{len(imgs)} 标签总数:{len(labs)}) print(f有图无标签:{len(only_img)} 有标签无图:{len(only_lab)}) return only_img, only_lab if __name__ __main__: pair_check(dataset/images/train, dataset/labels/train)逻辑说明用集合差集找出单边存在的文件。参数就是图片目录和标签目录。正常情况两个差值都应该是 0如果「有图无标签」数量大说明标注没做完或标签没同步「有标签无图」则说明图片丢失这种标签在训练时会被忽略但会污染你的数据统计。发现异常先别删备份后人工确认。4. 训练配置与参数设置把数据集接进 YOLO4.1 data.yaml 怎么写YOLOv5/v8 系列都靠一个 yaml 描述数据路径和类别。这份数据集已经分好yaml 直接指向三个目录即可path: ./dataset train: images/train val: images/val test: images/test nc: 3 names: 0: 凹陷 1: 缺口 2: 扭曲参数说明path是数据集根目录train/val/test是相对 path 的路径别写成绝对路径换机器会失效。nc是类别数必须等于 names 的行数也等于 classes 文件行数。names的顺序就是标签里 class_id 的含义写反了整个训练结果都是错的。中文类别名在部分版本里可能显示乱码如果遇到改成英文拼音或英文单词更稳。4.2 训练命令与关键参数以 YOLOv5 为例一条能直接跑的命令python train.py \ --data data/plastic_bottle.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/train \ --name bottle_defect参数逐个说--weights用预训练权重小数据集从零训容易过拟合迁移学习收敛快得多--img 640是输入分辨率缺陷目标如果很小可以提到 960 或 1280但显存和速度要权衡--batch 16按显存调8G 显存跑 640 一般能到 16--epochs 100是起步值看验证集 mAP 不再涨就可以早停--device 0指定第一块 GPUCPU 训练会慢到怀疑人生。如果用的是 YOLOv8/11 的 ultralytics 接口命令换成yolo detect train data... modelyolov8s.pt imgsz640 epochs100 batch16参数含义一致。4.3 三个类别不均衡时的处理凹陷、缺口、扭曲这三类在真实产线里的出现频率往往不一样凹陷可能远多于缺口。类别不均衡会让模型偏向多数类少数类召回上不去。常见做法有三种一是训练时用--cls权重或 focal loss 思路加权二是对少数类做数据增强比如复制粘贴、随机裁剪三是评估时别只看整体 mAP要分类别看每一类的 AP。我一般先跑一版基线看每类 AP 差多少差得离谱再针对性增强而不是一上来就堆技巧。5. 避坑与排查这些坑我替你踩过了5.1 训练 loss 正常但 mAP 一直是 0现象训练日志里 box_loss、cls_loss 都在降但验证 mAP 始终 0。原因九成是 data.yaml 里的 names 顺序和标签 class_id 对不上或者 nc 写错。解决打开 classes 文件核对顺序用第 2 章的校验脚本确认标签里出现的 class_id 范围再检查 yaml 的 nc 是否等于类别数。改完重跑mAP 立刻正常。5.2 可视化框位置整体偏移现象画出来的框整体偏左上或偏右下。原因标注时用了像素坐标没归一化或者归一化时除错了基准比如用了缩放后的图宽而非原图宽。解决用校验脚本查坐标是否超出 0~1超出的就是没归一化如果都在范围内但偏移检查可视化脚本里乘的是不是原图宽高别用 resize 后的尺寸。5.3 验证集指标忽高忽低现象相邻两个 epoch 的 mAP 差十几个点。原因验证集只有 130 张样本太少统计方差大。解决调参阶段看趋势不看单点或者从训练集再切 100~200 张补充验证集。别因为这个去改学习率或网络结构那是治标不治本。5.4 图片有标签丢导致实际训练量缩水现象以为用了 3200 张实际日志里显示的样本数明显偏少。原因部分图片没有对应标签YOLO 静默跳过。解决跑第 3 章的配对检查脚本把「有图无标签」的文件列出来要么补标要么从训练集移除别让它们占着位置不干活。5.5 中文类别名乱码或报错现象训练时 names 里的中文显示成方块或直接报编码错误。原因部分环境对 yaml 中文支持不好。解决把 names 改成英文比如 dent、gap、distort同时确认 classes 文件也同步改保持索引一致。类别名只是显示用不影响训练本身但一致性必须保证。6. 进阶技巧用测试集做一次可信的验收训练跑完很多人直接看验证集 mAP 就收工但验证集参与过调参数字偏乐观。真正对外汇报我习惯用那 60 张测试集做一次独立验收流程固定三步。第一步用训练好的权重在测试集上推理并保存结果python val.py \ --data data/plastic_bottle.yaml \ --weights runs/train/bottle_defect/weights/best.pt \ --img 640 \ --task test \ --save-txt \ --save-conf--task test指定用测试集--save-txt把预测框存成 txt--save-conf带上置信度方便后续按阈值筛选。第二步把预测结果和真值标签做逐类对比重点看少数类比如缺口的召回别被整体 mAP 掩盖。第三步挑几张漏检和误检的图用第 3 章的可视化脚本画出来人工判断是标注问题还是模型问题——如果是标注本身有争议那这部分数据就该从测试集里剔除别让脏数据拉低你的真实水平。一个容易忽略的细节测试集只有 60 张单张图对指标的影响很大汇报时最好给出置信区间或至少说明样本量别把 60 张上的 0.5 个点差异当成模型优劣的铁证。我吃过这个亏曾经为了测试集上高 2 个点换了个更复杂的模型结果上线后产线表现反而更差后来才明白是小样本波动骗了我。从那以后我每次定稿前都强制走一遍「验证集看趋势、测试集做验收、坏例人工复核」这三步再也不敢只看一个数字就下结论。希望帮到你。本文还有配套的精品资源点击获取
返回列表