YOLOv8训练瓶装白酒疵品检测模型:从数据集校验到标注优化
简介面向瓶装白酒质量检测的计算机视觉数据集压缩包约213MB文件总数2000主要包含4516张JPG图片与1个JSON标注文件。图片采集了瓶身划痕、标签破损、密封不良等多种常见疵品特征同时也包含正常瓶装样本覆盖正面、侧面等多角度视图可用于疵品识别、图像分类、目标检测与异常检测等任务为工业质检自动化模型提供基础训练素材。标注文件提供对应类别或位置信息便于进行监督学习时的训练集、验证集与测试集划分也方便使用准确率、精确率、召回率等指标评估模型。目录结构对应某一轮训练赛数据可作为竞赛复现、算法研究或课程设计的直接输入。数据集在采集时考虑了光照、背景和焦点等因素有助于减少无关变量干扰适合训练卷积神经网络等模型逐步提升产线上瓶装白酒质量的自动检测能力。已有292人学习下载适合计算机视觉、工业自动化方向的研究人员、学生及质检系统开发者参考。1. 瓶装白酒疵品检测数据集先看清这张图里有什么一个几千张图片的 zip 包摆到桌面上真正决定模型上限的往往不是之后传入训练脚本的那行命令而是包里图像与标注有没有和产线工况对齐。瓶装白酒疵品检测数据集核心要解决的是灌装流水线上那几类高频缺陷瓶盖歪斜与缺失、标签褶皱或破损、喷码模糊、液位异常、瓶身异物与裂纹。看起来是通用的目标检测任务实际上它是一个强约束的固定工位场景——相机位姿基本不变、光照可控、被检物体是同一批瓶型。这种场景里背景差异小缺陷与正常形态的差异反而更细微比如标签褶皱和正常反光在视觉上只差几个像素的纹理梯度。需要这套数据的人通常是拿它快速验证 YOLOv8 训练闭环、标注质量和模型在固定工位检测上的可用性而不是把它当成通用 benchmark 来刷分。数据集的真实工作量也集中在解压校验、目录解析、标注审查和按缺陷类别做评估这几步。2. 数据集的目录结构与标注格式YOLO 标签怎么和图像对上2.1 目录组织别急着猜用 find 看一遍再写解析脚本拿到 zip 包后先把文件解压到干净的目录再全量看目录结构。很多人在这一步直接打开 annotations 目录发现里面有 JSON 或 XML就默认按 COCO2017 数据集结构去写解析脚本但瓶装白酒产线数据更常按「train / val 分离 images / labels 平行目录」组织标注格式以 YOLO txt 为主偶尔带一个 data.yaml 或 classes.txt。先跑一段命令把目录看全比什么都稳unzip -q bottle_quality_dataset.zip -d ./baijiu_data cd ./baijiu_data find . -maxdepth 3 -type d | sort find . -name *.txt | wc -l find . -name *.jpg -o -name *.png | wc -l第一条命令把压缩包解压到 baijiu_data 目录-q是安静模式避免大文件解压时刷屏第二条列出前 3 层目录重点看 images、labels、train、val 这几个目录是否存在且同级后面两条分别统计标注文件和图片数量。如果标注 txt 数量和图片数量差得很大说明存在大量空标注图片这类图片对缺陷检测模型是「负样本」后面类别分布统计时要单独看。这里不建议用 Windows 解压工具自带的重命名功能很多中文文件名在跨平台传输后会变成乱码Linux 环境里直接用 unzip 最稳。2.2 YOLO 坐标归一化每个标签都藏在 0 到 1 之间YOLO 格式的每个 txt 文件对应一张同名图片每行代表一个目标格式是固定的五列class_id x_center y_center width height其中四个坐标值全部归一化到 0 到 1 之间分别除以图片宽高得到。如果标注工具导出的是 COCO 格式或 VOC 格式转成 YOLO 时还要额外做一次坐标除法很多瑕疵检测数据集在转换这一步就埋了雷比如某张 4032×3024 的产线原图缩放到 640 后标签没跟着缩框直接偏到图像外。0 0.591406 0.294973 0.117188 0.063492 2 0.328125 0.870370 0.271094 0.216931第一列是类别编号0和2必须和 data.yaml 里的类别顺序严格对应模型按编号读取类别名编号错了预测结果就张冠李戴。后四列是归一化后的框坐标框的中心点和宽高都在 0 到 1 区间内这是 YOLO 系列模型统一要求的输入格式。拿到数据集后抽三个 txt用下面这段 Python 脚本验证坐标是否有越界、宽高是否为负比肉眼翻图片效率高得多import os from pathlib import Path label_dir Path(./baijiu_data/labels/train) error_lines [] for txt_path in label_dir.glob(*.txt): for line_no, line in enumerate(txt_path.read_text().splitlines(), 1): parts line.split() if len(parts) ! 5: error_lines.append((txt_path.name, line_no, 列数不为5)) continue cid, x, y, w, h parts[0], *map(float, parts[1:]) if not (0 x 1 and 0 y 1): error_lines.append((txt_path.name, line_no, 中心点越界)) if w 0 or h 0 or x w / 2 1 or y h / 2 1: error_lines.append((txt_path.name, line_no, 宽高非法或框越界)) print(f共检查 {len(list(label_dir.glob(*.txt)))} 个标签文件) for err in error_lines[:20]: print(err)这段逻辑分三层先检查列数是否为 5列数不对说明标注工具导出格式有问题再检查中心点是否在 [0, 1] 范围内最后检查宽高是否是正数且框右下角是否超出图像边界。框越界在酒瓶检测数据里很常见因为酒瓶颈部细长标注时框容易画到图外这类目标在训练时梯度会异常影响边界回归的稳定性。越界的标注建议直接用脚本过滤或重算而不是留到训练后让模型自己学。2.3 解压与数据一致性校验EOCD 报错、图片损坏和名字错位数据集以 zip 形式分发最容易出问题的是压缩包在传输过程中出现截断。在 Linux 下解压时若出现failed to copy spatial iop zip或invalid zip archive: could not find EOCD一般是包不完整EOCDEnd of Central Directory记录被截掉这时任何解压工具都救不回来只能重新获取源文件。包本身完好的情况下也建议先做一次完整性校验unzip -t bottle_quality_dataset.zip | tail -n 5-t会让 unzip 逐文件计算 CRC 校验值并与压缩包内记录比对tail 只显示最后几行其中有No errors detected就说明包完整。不要跳过这步直接解压ZIP 的目录结构在文件末尾部分解压工具读到目录就开始暴力解压磁盘写了一半才发现文件损坏后面再排查反而浪费时间。解压完成后还有一个常见问题是图片和标注文件名错位比如img_0231.jpg对应的标签写成了img_0232.txt这会让模型拿瓶盖缺陷的标签去学瓶身裂纹的图像训练曲线看起来正常但验证集 mAP 永远卡在低位。用 2.2 节里的脚本检查坐标合法性之外还要补一层文件名对拍把同目录下前缀相同但扩展名不同的文件做一一对应数量对不上就说明有脏数据混入。3. 用 YOLOv8 训练瓶装白酒疵品检测模型的全流程命令与参数3.1 data.yaml 里的三个关键配置类别顺序、路径映射与尾随空格YOLOv8 训练自己的数据集第一步是写好 data.yaml。这个文件决定了模型看到多少个类别、从哪里读训练和验证图片。以下是一个瓶装白酒缺陷检测场景的配置示例path: /data/baijiu_data train: images/train val: images/val names: 0: cap_defect 1: label_wrinkle 2: label_broken 3: code_blur 4: liquid_abnormal 5: bottle_crackpath 指向数据集根目录train 和 val 是相对 path 的目录不要写绝对路径到 images 那一层YOLOv8 会自动拼接。names 里的编号顺序必须和标签文件第一列的数字保持一致编号 0 是背景之外第一个类别。这里有个容易踩的坑标签里出现6但 names 只定义到 5训练会直接报错 class index out of range标签里类别编号从 1 开始而 yaml 从 0 开始模型会把所有目标当成第二类表现是某个类别 mAP 为 0其他类别全部错位。另外 yaml 文件不要用记事本编辑并保存为带 BOM 的 UTF-8ultralytics 解析时会报 Unexpected character用 VS Code 或 vim 重写一遍就好。3.2 第一次训练跑通的最小命令与 5 个必调参数命令本身不复杂关键在参数取舍。固定工位的瓶装白酒检测成像条件稳定模型容量不需要太大第一次训练我一般会用 yolov8s 作为基线跑 100 轮看收敛曲线再决定是否换模型。yolo detect train \ modelyolov8s.pt \ data/data/baijiu_data/data.yaml \ epochs100 \ imgsz640 \ batch16 \ workers4 \ device0 \ patience20 \ project./runs/baijiu \ namev8s_baseline参数说明分段来看。imgsz640是训练分辨率产线原图多为 3000 像素以上的大图模型内部会做缩放640 是速度和精度的平衡点batch16按显存调12GB 显存跑 640 分辨率一般能到 16显存不够就降到 8不要动 imgsz 去迁就 batch酒瓶裂纹这类细小缺陷对分辨率很敏感patience20是早停轮数验证集指标连续 20 轮不涨就停避免无效训练时间。下面这张表是几个关键参数对训练结果的影响方向参数调大后的效果典型风险imgsz小目标召回率上升边界更精细显存翻倍训练时间变长batch梯度更稳定收敛更快显存溢出BN 统计量失真patience减少无效等待过大容易过拟合验证集workers数据加载更快过大时 CPU 成为瓶颈mosaic丰富背景和尺度分布固定工位场景下可能引入无关背景这里单独说 mosaic。YOLOv8 默认开启 mosaic 数据增强训练时把 4 张图拼成一张对通用检测很有效。但瓶装白酒产线场景背景高度一致物体永远在画面中央mosaic 拼出的图反而偏离真实分布尤其是 bottle_crack 这种只占几十像素的小目标拼图后边界更容易被截断。如果训了 20 轮发现验证集 mAP 震荡剧烈先把 mosaic 关掉跑一轮对比固定工位场景常常涨点。3.3 标注审查从预测框反推错标与漏标第一次训练结束后先别急着调参用训练好的权重跑一遍验证集预测然后抽查预测结果这一步能暴露大量标注问题。常见做法是把预测结果保存成图片按缺陷类别分组人工看一遍。下表是瓶装白酒场景里几类典型标注问题在预测结果上的表现标注问题预测表现原因分析框画得过大预测框比缺陷区域大一圈标注时把阴影或反光区域也包进框里漏标同一位置有时有框有时没框该缺陷在部分图片里没被标出类别贴错两类的置信度接近且持续互换标注规范里对类别边界定义不清框偏移预测框偏移方向与标注一致标注工具默认框中心线偏移这一步最关键的是区分「模型没学好」和「标注本身就是错的」。我的经验是每类抽 20 张预测图按上述四条逐一对照如果某类缺陷 20 张里有 5 张以上标注有问题修标注比调参收益大得多。4. 训练集常见的坑类别失衡、小目标和标注噪声4.1 先算类别分布再决定要不要调权重瓶装白酒疵品数据集里类别不平衡几乎是必然的标签破损可能只有几百个框液位异常却有两万个框。YOLOv8 默认按类别频率采样多数类会主导梯度方向少数类学不好。先跑一段统计脚本把每类目标数量和每张图的框数分布打出来from collections import Counter from pathlib import Path label_dir Path(./baijiu_data/labels/train) class_counter Counter() boxes_per_image [] for txt_path in label_dir.glob(*.txt): lines txt_path.read_text().splitlines() boxes_per_image.append(len(lines)) class_counter.update(int(line.split()[0]) for line in lines if line.strip()) print(类别编号 - 目标数量) for cid in sorted(class_counter): print(f {cid}: {class_counter[cid]}) print(平均每图框数:, sum(boxes_per_image) / len(boxes_per_image))判断是否要调权重的标准不是看类别数量差而是看绝对量。如果某个类别只有 50 个框再怎么调权重也很难学会这时候应该想的不是权重而是补数据或对该类做针对性增强。如果某个类别有 2000 个框但只出现在 100 张图里说明这 100 张图是从同一批次采集的背景高度相似模型学到的可能是背景而不是缺陷本身这种情况下要检查训练集里该类图片的多样性。固定工位数据很容易出现这种「数量够但多样性差」的假象。4.2 小目标缺陷的两种处理思路更大的 imgsz 与滑窗切图酒瓶裂纹、喷码模糊这类缺陷在 640×640 下往往只有 20×20 像素大小属于典型小目标。YOLOv8 在 COCO 上的小目标 AP 本来就偏低直接训产线数据效果不会好。两种调整手段我都很常用各有侧重。第一种是把 imgsz 从 640 提到 960 或 1280简单直接对小目标召回率的提升立竿见影代价是训练时间翻倍、显存占用大幅上升。第二种是滑窗切图把 3000×3000 的产线原图切成若干 640×640 的 patch再按 patch 训练。切图后图像信息没有丢失模型可以看到原始分辨率下的缺陷纹理这是提升小目标检测最有效的方法。切图时要保证相邻 patch 有 10% 的重叠避免缺陷正好落在切缝处被截断。产线固定工位场景里瓶子在画面中的位置相对固定切出来的 patch 类别分布相对稳定不像通用场景那样容易切出大量背景 patch所以这个方法在瓶装白酒检测里尤其好用。4.3 标注噪声怎么修错框、漏框、类别贴错各自的影响标注噪声对检测模型的影响不是线性的。边界框偏移 5% 以内模型基本不受影响因为 IoU 仍高于 0.7 的匹配阈值但漏框和错框的影响要大得多。一个漏标的缺陷会被当作背景参与训练模型会在该位置学到「这里没有目标」的负反馈同一位置的一个正样本往往需要多个负样本来抵消所以漏框严重的数据集会表现为召回率低且怎么调都上不去。类别贴错的框会把模型往错误方向推两个形态相近的类别之间尤其明显比如 label_wrinkle 和 label_broken特征差异本来就小标签再互串模型学到的决策边界会混乱验证集上这两类互相误检。修标注噪声的原则是先修漏框再修类别贴错最后才修边界框偏移。漏框影响的是召回率的上限类别错误影响的是精确率而边界框偏移对最终 IoU 指标的影响最轻可以留到模型稳定后再精细调整。5. 验证与迭代先看漏检再看误检按缺陷类型修数据5.1 用混淆矩阵定位最该修的数据子集训练结束后不要只看 validation 目录下打印的 mAP50 和 mAP50-95这两个数字是全局平均掩盖了类别间的差异。用 YOLOv8 自带的验证命令输出混淆矩阵yolo detect val \ model./runs/baijiu/v8s_baseline/weights/best.pt \ data/data/baijiu_data/data.yaml \ splitval \ plotsTrueplotsTrue会在 run 目录下生成 confusion_matrix.png 和各指标的曲线图。看混淆矩阵时遵循一个顺序先看对角线之外哪里最亮对角线之外最亮的方块指向的是最容易混淆的缺陷组合比如 cap_defect 被识别成 label_wrinkle说明这两类缺陷在训练集里形态接近或者标注边界不清再看背景列背景列数值大说明误检严重模型把正常瓶身纹理或反光当成了缺陷这时候修数据的方向是补充难负样本而不是继续叠加增强。5.2 按缺陷类别拆出来的 PR 曲线比整体 mAP 更说明问题整体 mAP 被多数类主导liquid_abnormal 这类易学类别会把平均值拉高掩盖 bottle_crack 的低召回。按类别查看 PR 曲线能直观看到每一类在哪个置信度阈值下召回率断崖下降。对固定工位检测来说漏检比误检致命产线里漏掉一个疵品意味着缺陷流到后端而误检只要加一道人工复检即可兜底。如果某类 PR 曲线的膝盖出现在 0.7 置信度以下说明模型对该类的特征学习不够充分优先回到 4.2 节的小目标方案去调整而不是一味调低置信度阈值。5.3 三类高频修正合并碎框、补漏标、重画模糊边界以验证结果为输入常见的修数据操作有三步。第一步是合并碎框。标签褶皱这类连续缺陷常被标成多个小框导致一个完整缺陷被拆成三四个目标训练时模型输出多个低置信度框NMS 之后乱成一团用标注工具把同一条褶皱上的小框合并成一个大框即可。第二步是补漏标。把预测结果和人工复核结合优先补那些模型置信度低但人眼确认的缺陷样本这是提升召回率最直接的手段。第三步是重画类别边界。标签破损和标签起皱如果持续互相误检重新对标标注规范明确「破损」必须是可见的撕裂或缺口「起皱」是表面不平整然后按新规范修标签。每次修完数据重新训练一轮对比混淆矩阵里的目标格是否变暗而不是看总 mAP 有没有涨——总 mAP 涨了可能是因为多数类被优化得更好而你要修的少数类毫无起色。本文还有配套的精品资源点击获取