
简介瓶装白酒疵品检测数据集包是面向工业质检场景的计算机视觉训练资源旨在通过图像识别瓶身划痕、标签破损、密封不良等瑕疵适合机器学习与深度学习初学者、质检方案开发者用于疵品检测模型训练和算法验证。压缩包约213MB内含2000个文件以jpg格式酒瓶图像为主体另附json标注文件可直接支撑目标检测或图像分类任务中的数据准备与标注解析。目前已有292人学习/下载根据文件名与目录结构推测数据来自某竞赛的第一轮训练集采集视角多样疵品类型覆盖较全面。借由这份数据读者可以完成从数据加载、标注解析、模型训练到性能评估的完整流程复现疵品检测基线并进一步调整网络结构与超参数开展对比实验对于希望进入工业视觉方向的研究者和学生是一个不错的实践入口。1. 瓶装白酒疵品检测数据集开箱之前先想清楚的三件事拿到一个“瓶装白酒疵品检测数据集.zip”通常的冲动是解压、丢进 yolo 仓库、跑一个晚上然后对着 mAP 数字欢呼。但产线上做过视觉落地的人都清楚数据集才是决定模型上限的杠杆训练代码只是把这个杠杆按住的手。白酒灌装线上的疵品检测要输出的是瓶盖歪斜/松脱、标签褶皱/错位/破损、液位线异常、瓶身裂纹和瓶内异物这几类缺陷的定位信号再换算成分拣机构的剔除指令背后是一套“小样本 强纹理 高一致性”的工业视觉任务。这个 zip 本身的命名已经暴露了它要服务的工作流拿到标注数据走一遍数据清洗配置 yolov8 训练自己的数据集再部署回产线。下面顺着数据集解构、训练参数、高频踩坑到验收方法这条路径往下拆有命令、有参数、有对照实验思路。适合正在做工业检测落地的算法工程师也适合第一次用 YOLO 系数据集练手的新手。2. 数据集结构与标注格式解读工业检测数据集和公开数据集最大的区别是“脏”。coco2017 数据集结构里 80 个类一张图一张图标得规规矩矩而产线上导出再打包的数据集常见问题包括训练集和验证集有重叠、个别图片没有对应标注文件、标注坐标为 0 的越界框、文件名带中文字符导致脚本崩溃。从数据集下载渠道拿到压缩包后第一轮操作不是训练而是把家底盘清楚。2.1 解压先做三件事校验、看树、查空标注先做完整性校验。网络传输过程中 zip 文件头损坏会导致解压到一半报invalid zip archive或could not find eocd这种情况重下比修复更省时间。md5sum 瓶装白酒疵品检测数据集.zip unzip -t 瓶装白酒疵品检测数据集.zip unzip 瓶装白酒疵品检测数据集.zip -d baijiu_dataset cd baijiu_dataset find . -type d | sort参数说明md5sum核对发布方给的校验值确认下载过程没有丢字节unzip -t只测试压缩包完整性不解压内容-d指定解压目标目录避免文件散落在当前目录。如果终端里中文文件名显示成乱码是 zip 内部编码不统一导致用 Python 的zipfile按cp437转gbk批量重命名不要在 Windows 自带解压工具里手工改几十个目录改起来会怀疑人生。注意长文件名或中文文件名在个别 zip 工具里会截断。若某个子目录解压后文件数对不上用unzip -O gbk指定解压编码再试一次。解压后第一件事是数图片数量和标注数量是否对得上。典型层目录结构如下标注文件和图片一一对应baijiu_dataset/ ├── images/ │ ├── train/ # 约 3500 张 │ ├── val/ # 约 600 张 │ └── test/ # 约 800 张 └── labels/ ├── train/ ├── val/ └── test/2.2 标注格式决定你走哪条训练管线白酒疵品数据集最常见的标注格式有三种YOLO txt、VOC XML、COCO JSON。拿到手先随便打开一个标注文件确定格式再决定训练管线选型。标注格式一行/一条的数据组织坐标系统典型配套框架YOLO txtclass_id x_center y_center w h归一化到 [0,1] 的相对坐标yolov5 / yolov8 / YOLOXVOC XMLobjectname../namebndbox四角绝对像素绝对像素坐标转换后进入 YOLO 系或 Detectron2COCO JSONimagesannotations数组细化 bbox 与 segmentation绝对像素坐标左上角宽高mmdetection / detectron2 / YOLOv8YOLO txt 一行六个字段类别 id、中心点 x、中心点 y、框宽、框高全部除以图片宽高做归一化。注意第 0 维是类别 id 而不是类别名若发布方在 txt 里写的是字符串类别名需要先做一次类别到 id 的映射表否则 yolov8 读数据时直接报类型错误。VOC 的 XML 通常在标注阶段由 labelImg 产生转换到 YOLO 格式时要重点检查filename里的文件名和实际图片文件名是否一致两者不一致的情况在产线导出的数据集里出现频率不低。2.3 用 Python 统计类别分布第一眼就发现不平衡不管标注格式是什么先把每个类别的框数量和样本图片数统计出来。这一步能避免“训了两天发现某个类一张都没进训练集”这种事故。# stats_labels.py import glob from collections import Counter counter Counter() # 按类别统计标注框数量 empty_txt [] # 记录空标注文件 for txt_path in glob.glob(labels/train/*.txt): lines [l.strip() for l in open(txt_path) if l.strip()] if not lines: empty_txt.append(txt_path) continue for line in lines: cls_id line.split()[0] # 取每行第一个字段类别 id counter[cls_id] 1 print(框总数:, sum(counter.values())) print(类别分布:, dict(counter)) print(空标注文件数量:, len(empty_txt))说明逻辑Counter统计的是框数量而不是图片数量一张图上有 5 个瓶身裂纹和 1 个标签错位对 loss 的贡献完全不同。空标注文件要单独列出来训练集里混入空 txt 会干扰分类分支的学习最常见的处理是直接删掉空文件同时确认这些图片是否属于允许漏检的背景样本。类别分布跑完之后重点关注两类情况某个类别框数量不足整体 5%或者两个可视觉混淆类比如标签褶皱和标签破损的比例悬殊。产线上的数据集往往还带时序信息比如拍摄班次、光源批次、灌装线编号。如果图片文件名里有这类后缀尽量保留。后面做验证集切分时按批次切而不是随机切否则模型在跨班次生产时性能骤降这一点在真实项目里比调学习率重要得多。3. 用 YOLOv8 在瓶装白酒疵品数据集上跑通训练确认标注格式和类别分布没问题之后进入训练流程。选 yolov8 的理由很实际ultralytics 仓库把数据加载、增强、验证、导出连成一条链工业落地最需要的 ONNX 导出和 TensorRT 部署都是内置能力对白酒瓶身这种高对比、结构化背景的检测场景yolov8s 的精度性价比通常高过 nano训练开销又远小于 m。3.1 整理目录并生成数据配置 yamlYOLOv8 要求数据配置 yaml 里的train和val指到 images 目录labels 目录按同名规则自动匹配。这里有一个最常见的坑images/train下的图片对应labels/train下的 txt不要自己另起一个annotations目录名除非你打算写自定义 Dataset 类。# baijiu.yaml path: /data/baijiu_dataset train: images/train val: images/val # test: images/test names: 0: cap_loose 1: cap_tilted 2: label_wrinkled 3: label_misaligned 4: level_low 5: bottle_crack 6: foreign_body说明逻辑path建议写绝对路径names的索引顺序必须与标注 txt 中的类别 id 完全一致。cap_loose、level_low这类可读标签不影响训练影响的是混淆矩阵和验证输出的可读性。如果数据集原始类别名是中文建议统一转成英文小写后续画confusion_matrix.png时避免 matplotlib 中文字体踩坑。注意原图是 PNG 或 BMP 时不必先转成 JPGultralytics 会自动解码。但 label 与 image 同名不同后缀时图片文件名必须以磁盘上的实际文件为准。3.2 训练命令与关键参数表基础训练命令如下使用预训练权重做迁移学习yolo detect train \ data/data/baijiu_dataset/baijiu.yaml \ modelyolov8s.pt \ imgsz640 \ batch16 \ epochs150 \ lr00.005 \ lrf0.01 \ cos_lrTrue \ patience30 \ fliplr0.0 \ mosaic0.8 \ plotsTrue \ projectruns/baijiu \ nameexp_cap这里的参数需要按白酒检测场景单独解释不能直接抄默认值。参数推荐值说明imgsz640精度与速度的平衡点标签区纹理细节不够时试 1280batch16按显存调整单卡 24G 可到 328G 建议 8lr00.005迁移学习的安全起点过大会在前 10 轮破坏预训练特征cos_lrTrue配合 lrf0.01 让学习率后期平滑下降fliplr0.0白酒标签上有汉字水平翻转会让字形镜像mosaic0.8对瓶盖小目标有增益loss 震荡大时先关掉对比一轮patience30验证损失连续 30 轮不降则自动早停fliplr0.0是白酒场景最容易忽略的一项。瓶身标签上的汉字和 logo 被水平翻转后变成镜像模型会学到错误的字形特征真实产线上出现镜像误判很难排查。mosaic0.8保留较高比例的马赛克增强对瓶盖、瓶内异物这类小目标有帮助但当验证 loss 震荡幅度持续偏大时优先关掉 mosaic 做对照实验。训练完成后runs/baijiu/exp_cap/下会生成results.png、confusion_matrix.png、F1_curve.png和weights/best.pt。用tensorboard --logdir runs/baijiu打开标量曲线更直观。优先看val/box_loss如果验证损失在某个 epoch 后开始回升训练曲线早就说明过拟合开始了不要等到 150 轮跑完才干预。3.3 验证集评估与第一次迭代训练结束后执行验证命令拿到每类 AP 和 mAPyolo detect val \ modelruns/baijiu/exp_cap/weights/best.pt \ data/data/baijiu_dataset/baijiu.yaml \ splitval \ imgsz640 \ conf0.25 \ plotsTruesplitval指定用 yaml 中的 val 集conf0.25只影响推理时的置信度阈值不影响 mAP 本身的计算。跑完之后第一件事是看confusion_matrix.png两个类之间互相误检的现象会非常直观地暴露出来。白酒瓶场景典型的混淆是“标签褶皱”和“标签破损”的互相误判以及“瓶盖歪斜”在低置信度下被漏检。这类混淆靠调参救不回来通常需要核对原始标注是否区分得足够干净必要时把这两个类合并把决策边界交给业务方去定。4. 三大训练坑小目标漏检、类别不平衡与过拟合yolov8 训练自己的数据集跑通很容易但白酒疵品检测真正难受的是细节剪纸大小的瓶身异物是极小目标液位线是长宽比悬殊的条状目标标签起皱的纹理特征极其细腻。这三个问题对应工业检测里最典型的三个坑诊断信号和应对手段完全不同。4.1 小目标漏检滑窗推理兜底YOLO 系模型在 640×640 输入下过小的目标会由于下采样彻底丢失特征。瓶身内部的絮状物、纸屑只有十几个像素宽直接整图训练会在 val 集上 AP 惨淡。常见做法是把原图切块训练或切块推理。滑窗推理的核心思路是把大图裁成小块分别送进模型再把框坐标映射回原图坐标# sliding_window_infer.py from ultralytics import YOLO import cv2 model YOLO(runs/baijiu/exp_cap/weights/best.pt) img cv2.imread(../baijiu_dataset/images/val/bottle_017.jpg) H, W img.shape[:2] win_h, win_w H // 2, W // 2 # 滑窗尺寸按目标大小调整 stride win_w // 3 # 重叠步长控制重叠率 for y0 in range(0, H - win_h 1, stride): for x0 in range(0, W - win_w 1, stride): crop img[y0:y0 win_h, x0:x0 win_w] res model(crop, conf0.25, imgsz640, verboseFalse) for box in res[0].boxes: x1, y1, x2, y2 map(int, box.xyxy[0].tolist()) # 映射回原图坐标 abs_box (x1 x0, y1 y0, x2 x0, y2 y0) print(class:, int(box.cls), bbox:, abs_box)逻辑说明滑窗推理的代价是推理次数成倍上升产线节拍不允许所有图都走滑窗时用两阶段策略——整图先跑一遍把置信度低于 0.3 的候选区域裁出来二次精细检测或者用 SAHI 这类切图推理库做候选框合并它内部已经处理了跨窗口的 NMS。白酒瓶固定工位场景还有个更工程化的做法把每个瓶身裁剪成固定区域瓶盖区、标签区、瓶身下部对三个区域分别训练专用小模型从根上避开小目标问题。4.2 类别不平衡先看 per-class 的漏检再谈调参若统计阶段发现foreign_body瓶内异物只有 200 个框而label_wrinkled有 4000 个框直接训练出来的模型会对异物类全面漏检。处理顺序一定是先确认产线对异物漏检的容忍度如果异物漏检是最严重事故优先保证这一类的召回用高召回换取后续分拣环节去消化误报。常见做法是少样本类别过采样。直接复制图片会导致模型死记样本正确姿势是复制的同时叠加随机色彩抖动# oversample_minority.py import glob, shutil import cv2 minority_cls 6 src_dir labels/train img_dir images/train copied 0 for txt_path in glob.glob(f{src_dir}/*.txt): if not any(l.startswith(minority_cls ) for l in open(txt_path)): continue img_path txt_path.replace(labels, images).replace(.txt, .jpg) if not shutil.os.path.exists(img_path): continue # 每个少数类样本复制 3 份文件名加后缀避免覆盖 for k in range(3): new_id f{shutil.os.path.splitext(img_path)[0]}_aug{k} cv2.imwrite(new_id .jpg, cv2.imread(img_path)) shutil.copy(txt_path, new_id.replace(images, labels) .txt) copied 1 print(过采样图片数:, copied)说明逻辑这段脚本对包含第 6 类的样本复制三份并落盘实际操作中要避免所有少数类复制次数一致把相对多数类比例压过头要按类别数量差距做反向计算。YOLOv8 原生没有按类别设置损失权重的入口但可以在 mosaic 拼图阶段提高少数类样本的出现频次来等价实现。训练后对比两组实验——原始分布与过采样分布——逐类记录 AP50而不是只看 mAPmAP 会被多数类掩盖。还有一类从 yolov5 训练自己的数据集迁移到 yolov8 时容易忽略的现象yolov5 会在训练前重新聚类 anchoryolov8 也保留了类似逻辑。白酒标签多是竖长条形原始 COCO anchor 的宽高比分布不匹配时训练日志里 anchor 重聚类后的值变化大是正常现象不要人为关闭。4.3 过拟合与光环境把数据增强看成正则化白酒产线采集的照片高度集中同一光源、同一角度、背景颜色一致这既是诅咒也是祝福。用 150 个 epoch 硬训会得到训练集表现极佳、验证集 AP 很差的模型典型信号是train/box_loss持续下降但val/box_loss在第 60 epoch 开始回升。应对方法是把增强当成正则化工具逐项拨光源颜色差异大的工厂把hsv_h、hsv_s调高模拟不同色温产线偶尔有瓶子晃动失焦适度打开blur增强禁止或调低fliplr文字镜像问题前面说过旋转增强degrees5足够白酒瓶大多垂直摆放过大的角度会引入无效样本分布。三类坑的诊断信号可以汇总成一张速查表训练中间隔几个 epoch 就对照一次。坑训练曲线信号验证结果信号首选对策小目标漏检box_loss 收敛快、整体偏低小目标类 AP50 明显低于均值滑窗推理或按区域拆分模型类别不平衡多数类 cls_loss 先降少数类震荡少数类 AP 接近 0过采样 色彩抖动增强过拟合train loss 降、val loss 回升验证集 mAP 远低于训练集增强强度加大并接受提前早停超参数调整要有对照组。每轮只改一个变量记录 mAP、推理速度和最小类 AP。如果数据集里存在需要旋转框才能充分表达的缺陷形态比如瓶盖封膜边缘的倾斜压痕常规水平框会框进大片背景可以考虑走旋转框检测路线类似 mmrotate 训练 dota 数据集那套流程代价是标注成本和后处理复杂度显著上升。5. 验收技巧从 per-class AP 到产线过杀率训练曲线的 mAP 只能说明模型在验证集上的整体表现落到产线上要看两件事每类到底漏检多少以及误检会不会拖垮分拣系统。用验证集逐类导出 AP 数据yolo detect val \ modelruns/baijiu/exp_cap/weights/best.pt \ data/data/baijiu_dataset/baijiu.yaml \ save_jsonTruesave_jsonTrue会把每张验证图片的预测结果导出成 JSON便于和标注做逐框比对指标结果同步写入results.csv。逐类查看 AP50重点关注两个值最小的类 AP以及混淆矩阵中互相串检的那对类。产线过杀率的来源往往不是平均精度低而是少数几个类别的置信度阈值调不到合适区间——异物类提置信度能降误检但漏检飞涨标签褶皱类降阈值能保召回但把正常标签大量误杀。处理技巧是先把产线节拍折算成推理预算在这个预算下做置信度扫描# tune_conf.py from ultralytics import YOLO model YOLO(runs/baijiu/exp_cap/weights/best.pt) for conf in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]: m model.val(databaijiu.yaml, splitval, confconf) print(conf, round(m.box.map50, 3), [round(a, 3) for a in m.box.maps])这里box.maps是每个类别的 AP 列表打印出来能看出每个置信度下最小类 AP 的变化曲线。注意每跑一个 conf 都是一次完整验证时间开销按分钟计。过杀率的精确估算需要把验证集按产线实际良品/疵品比例重新加权而不是按数据集原始分布。最后上线时把模型从 PyTorch 导出 ONNX 再转 TensorRT用验证集里最具挑战性的 30 张样本在推理引擎上做一次回归测试比对每张图的框坐标与置信度和训练框架输出是否一致。选 conf 阈值有个实用经验在 0.25 到 0.6 之间做网格搜索优先保证关键缺陷类别召回率达到业务红线再压低误报数而不是一味追求 mAP 数字最好看。mAP 最高的 checkpoint 往往不是产线上最好用的模型把best.pt换成根据过杀率曲线选出的那个 checkpoint 再导出这才是数据集落到产线真正的最后一步。本文还有配套的精品资源点击获取