YOLOv8实战:可口可乐产品识别数据集训练与避坑指南

发布时间:2026/10/10 18:10:51
YOLOv8实战:可口可乐产品识别数据集训练与避坑指南 简介这是一份面向YOLO系列算法学习者的产品识别目标检测数据集内含5166张带标签图像覆盖可口可乐等产品的识别场景。数据集已按训练/验证需求划分并配备data.yaml配置文件可直接用于yolov5、yolov8、yolov9、yolov10、yolo11等主流版本的模型训练与测试。标签同时提供YOLO格式txt与VOC格式xml分别保存便于不同工具链调用YOLO格式采用class、归一化中心坐标与宽高的标准写法上手简单。压缩包文件总数2000个以xml标签文件为主要类型整体大小约143.6MB标签类别可在资源详情页查看。目前已有95人学习下载适合需要产品识别数据集进行算法实战、模型评估与对比实验的开发者。1. 先别急着解压这份可口可乐产品识别数据集是什么、能解决什么拿到YOLO算法-产品识别数据集-5166张图像带标签-可口可乐.zip这类压缩包第一反应通常是解压、丢进训练脚本、等着看 mAP。我建议先花半小时把这 5166 张图的标签格式、类别编号和图像来源看清楚。这是一份面向目标检测任务的产品识别数据集标注对象是可口可乐的瓶、罐、箱等商品实例典型用在零售货架盘点、无人货柜和生产线质检。标签统一、场景相对集中适合新手练手也适合做迁移学习的底料。但直接拿来训练大概率会在验证集上自嗨部署到真实门店就翻车。这篇笔记从数据集本身拆起讲清 YOLO 标签格式跑通 YOLOv8 训练再交代产品识别里几个容易踩的坑。2. 拆开 YOLO 格式5166 张图像的目录结构、标签文件与类别定义2.1 典型的 YOLO 检测数据集目录长什么样解压后先别急着看图把顶层目录结构打一遍。绝大多数 YOLO 检测数据集体例是images/和labels/平级图像和标签同名不同后缀000001.jpg对应000001.txt。需要先分清这是检测框标签不是 yolo 实例分割那种掩码多边形——后者标签里是一串多边形顶点坐标格式完全是另一套东西。实际拿到的数据集可能有几种摆法我的处理经验如下已经分好train/、val/子目录直接进 3.2 写 yaml图像全部平铺在images/里需要自己划分文件名带着采集批次或相机编号例如checkout_01_000123.jpg。第三种最容易被忽略。文件名里的批次信息往往是划分训练集和验证集的重要依据按文件名随机洗牌同一批次的连拍帧会同时落到训练集和验证集训练时看着正常验证集 mAP 虚高。后面第 4 章专门讲数据划分泄漏这件事。另外如果打开 txt 发现一行不止 5 个数字比如出现一串浮点数坐标说明这份标签可能是分割标注或者多边形框不是 YOLO 检测格式。不要硬套训练脚本否则解析时直接报错。2.2 读懂 label txt归一化坐标是 YOLO 格式的灵魂YOLO 的一行标注是 5 个值class_id x_center y_center width height。坐标全部除以图像宽高做归一化换句话说不管是 640×640 小图还是 3024×4032 手机原图框的坐标都在 0 到 1 之间。这个设计和 COCO json 的左上角 x、y 加宽高不一样混用会让框整体偏移训练出来的模型自己骗自己。打开一个标签文件用下面这段脚本把归一化坐标反算回像素坐标叠在原图上检查from pathlib import Path from PIL import Image label_path Path(labels/000001.txt) image_path Path(images/000001.jpg) w, h Image.open(image_path).size for line in label_path.read_text(encodingutf-8).splitlines(): line line.strip() if not line: continue cls_id int(line.split()[0]) x_c, y_c, bw, bh map(float, line.split()[1:]) # 反算左上角和右下角的像素坐标 x1 (x_c - bw / 2) * w y1 (y_c - bh / 2) * h x2 (x_c bw / 2) * w y2 (y_c bh / 2) * h print(cls_id, round(x1), round(y1), round(x2), round(y2))逻辑是先拿 PIL 读出图像的宽和高再逐行取类别编号、中心点坐标和宽高最后反算成左上右下两个角点。这里map(float, ...)是把字符串批量转浮点数line.split()[0]是类别编号必须是整数。跑出来的像素坐标如果明显超出图像边界比如x2比w大很多说明标签越界了。打印的四个值可以直接用 OpenCV 画框和图像叠在一起看比盯数字直观。字段含义整理成一张表核对标签时心里有底字段含义取值范围class_id类别编号从 0 开始0 ~ 类别数-1x_center框中心点的 x 除以图像宽0~1y_center框中心点的 y 除以图像高0~1width框宽除以图像宽0~1height框高除以图像高0~1大多数翻车现场出在 class_id 上。标签写的是 2data.yaml 的 names 列表第二位却不是可乐模型就永远学不对。这是整个 YOLO 数据集环节最容易黑匣子化的地方3.2 再强调一次。2.3 没有 classes.txt 时怎么确认类别到底有几个训练必须要有 names 类别列表但很多压缩包里只有 txt。这时先跑一个统计脚本把 class_id 分布打出来from collections import Counter from pathlib import Path counter Counter() empty_files 0 for txt in Path(labels).glob(*.txt): ids [] for line in txt.read_text(encodingutf-8).splitlines(): line line.strip() if line: ids.append(int(line.split()[0])) if not ids: empty_files 1 else: counter.update(ids) print(class_id 分布:, sorted(counter.items())) print(空标签文件数:, empty_files)这个脚本同时确认两件事类别编号有没有断档以及有多少空标签文件。如果分布是{0: 2000, 1: 1800, 2: 1300}说明 3 个连续类别names 照0、1、2写如果分布是{0: 2000, 2: 3000}没有 1那要么采集时漏了类要么标注工具跳过了某类直接按最大编号加一猜类别数会出问题。类别拆多细也直接影响训练难度。以可口可乐这类产品识别数据集为例常见标注方案是按包装形态分瓶、罐、箱也有按配方分经典、零度、健怡。两种都合理关键是 names 顺序和 txt 里的 class_id 一一对应。很多人问「xml 格式文件没有标签怎么办」大多不是 xml 真没标签而是 VOC 格式的 object 转 YOLO txt 时classes 列表顺序没和转换工具对齐导致生成的标签全错位。2.4 标注质量体检越界框、空标签与框面积分布class_id 看完了再看框本身。除了 2.2 说的越界检查我一般还会统计框面积占整张图的比例。产品识别数据集里一瓶可乐和一箱可乐的框面积能差几十倍如果训练时只在某一个尺度上见过目标换个视角就漏检。from pathlib import Path samples [] for txt in Path(labels).glob(*.txt): for line in txt.read_text(encodingutf-8).splitlines(): line line.strip() if not line: continue parts line.split() if len(parts) ! 5: continue # 格式不对的直接跳过 w float(parts[3]) h float(parts[4]) samples.append(w * h) # 归一化面积占比 samples.sort() p5 samples[len(samples) // 20] p50 samples[len(samples) // 2] p95 samples[int(len(samples) * 0.95)] print(框面积占比 p5 / p50 / p95:, p5, p50, p95)w和h是归一化宽高乘起来就是框面积占比。p5 和 p95 的差距能一眼看出尺度跨度。跨度超过 20 倍训练时就要把 imgsz 加大或者走切片推理的路线而不是默认 640 一路到底。这一步做完数据集才算真正打开看过了可以进训练环节。3. 用这份数据集跑通 YOLOv8 训练划分脚本、data.yaml 与训练命令3.1 数据划分脚本按类别分层别把同一场景漏到验证集压缩包里如果没分 train/val就得自己动手。最省事但最不该做的是random.shuffle一把梭。同一场景的连续帧高度相似随机切会让同一瓶可乐同时出现在训练集和验证集最后验证 mAP 虚高一到现场就现原形。常见做法是按「主类别」分层每个类别抽 10% 做验证集空标签文件提前踢掉。我用的划分脚本长这样from pathlib import Path import random import shutil from collections import Counter, defaultdict random.seed(42) root Path(coke_dataset) images_src root / images labels_src root / labels out_dirs [ root / train / images, root / train / labels, root / val / images, root / val / labels, ] for d in out_dirs: d.mkdir(parentsTrue, exist_okTrue) def main_class(label_path: Path) - str: counts Counter() for line in label_path.read_text(encodingutf-8).splitlines(): line line.strip() if line: counts[int(line.split()[0])] 1 return str(counts.most_common(1)[0][0]) if counts else empty groups defaultdict(list) for label_path in labels_src.glob(*.txt): cls main_class(label_path) if cls empty: continue # 空标签不参与划分 groups[cls].append(label_path) for paths in groups.values(): paths.sort() # 排序后再 shuffle保证随机种子稳定生效 random.shuffle(paths) val_n max(1, round(len(paths) * 0.1)) for label_path in paths[:val_n]: img images_src / (label_path.stem .jpg) if not img.exists(): img images_src / (label_path.stem .png) shutil.copy2(label_path, root / val / labels / label_path.name) shutil.copy2(img, root / val / images / img.name) for label_path in paths[val_n:]: img images_src / (label_path.stem .jpg) if not img.exists(): img images_src / (label_path.stem .png) shutil.copy2(label_path, root / train / labels / label_path.name) shutil.copy2(img, root / train / images / img.name) print(train/val 划分完成请检查目录数量)逻辑是每个样本先统计自己包含的所有类别取数量最多的那个作为主类别再按主类别分组组内打乱后前 10% 进验证集。这样能保证每个类别在验证集里都留有一定比例不会出现「验证集全是可乐瓶、训练集全是可乐罐」的极端情况。参数说明random.seed(42)让划分过程可复现round(len(paths) * 0.1)对每个类至少留 1 个验证样本用copy2而不是move是给自己留后悔药训练集确认没问题再删源目录不迟。如果图像后缀混着.jpg、.jpeg、.png建议把后缀列表写成一个循环逐个尝试不要只写死.jpg。要真正做到同场景不跨集合还得按拍摄批次目录分组这个脚本是类别分层的近似方案更严格的泄漏控制在第 4 章讲。3.2 写 data.yaml路径、类别编号和名称必须对齐YOLOv8 靠一个 data.yaml 找到数据和类别。注意train和val指向的是 images 目录YOLOv8 会按同名规则自动去 labels 目录找标注不需要在 yaml 里写 labels 路径。path: /home/you/coke_dataset # 改成你解压后的绝对路径 train: train/images val: val/images names: 0: coca-cola 1: coke-zero 2: diet-cokenames必须和 txt 里的 class_id 完全一致一个萝卜一个坑。假设标签文件里第二类写的是1而 names 里1对应经典款模型就会把零度学成经典款这类错误在验证集上要看到混淆矩阵才能发现。常见做法是先跑一遍 2.3 的统计脚本把类别编号和 names 摆在一起校准完再开训。path建议写绝对路径规避不同机器上相对路径解析差异names的条目数必须等于标签最大编号加一。训练中出现类别数量对不上优先改 yaml不要去批量改 txt。注意批量改 txt 里的 class_id 很容易把同类别编号改乱而且通常不可逆。先备份再用脚本统一改改完重新跑一遍类别统计确认分布。3.3 训练命令与参数baseline 先用 nano别一上来就上大模型装 ultralytics 很简单pip install ultralytics不管用 PyCharm 还是纯命令行先确认解释器是同一个虚拟环境否则装完却 import 不到是新手最容易卡住的一步。第一次跑 baseline 用 nano 权重不做高级调参。下面这组参数适合 5166 张中等规模的产品识别数据集yolo detect train \ data/home/you/coke_dataset/data.yaml \ modelyolov8n.pt \ epochs100 imgsz640 batch16 \ patience20 device0 \ project./runs namecoke_product参数说明modelyolov8n.pt是在 COCO 上预训练过的权重拿产品识别数据集做 fine-tune图量不大也有底子imgsz640是显存和精度之间的平衡点batch16大约需要 8~10 GB 显存显卡紧张就降到 8patience20表示验证指标 20 轮不涨就早停对中等规模数据集很实用能省掉后半段无效训练时间。project./runs namecoke_product把日志和权重单独放一个目录方便后续对比实验。有人问损失曲线为什么不降我的排查顺序是data.yaml 路径、图像是否正常读取、空标签是否混入最后才是学习率。YOLOv8 默认学习率对 fine-tune 够用真正让损失不动的原因十有八九是数据路径错了或者标签文件空了。3.4 训练完先看三张图损失曲线、混淆矩阵和验证集预测图训练结束先别只盯 mAP 数字打开 runs 目录里的图。第一张是results.png里面是 yolo 损失函数在训练过程中的实际表现包括box_loss和cls_loss的训练与验证两条曲线。验证损失尾段明显回升是过拟合信号验证损失横盘不降大概率是标注不一致或者类别太难。第二张看confusion_matrix_normalized.png重点看哪些类别互相混淆。产品识别场景里最常见的是零度可乐和经典可乐互认或者透明瓶被漏检导致背景占比偏高。第三张是val_batchN_pred.jpg直接看验证集上的预测框位置框偏了半个瓶身、漏了后排的小瓶都比 mAP 数字更早暴露问题。看完这三张图再决定要不要调参。数据本身有毛病时调 anchor 和损失权重都是隔靴搔痒先把标签体检和划分修好再回来跑第二轮。4. 产品识别数据集避坑反光、小目标、场景单一与标签噪声产品识别数据集看起来比行人检测、车辆检测简单——目标就是货架上的商品类别少、背景固定。但 5166 张图对工业落地来说并不算多真正持续让人翻车的是几个看起来不严重的细节。下面按我踩过的顺序写。4.1 透明瓶反光可乐瓶被认成矿泉水瓶透明瓶反光在验证集上最容易暴露红色可乐瓶要么直接漏检要么框缩到瓶盖以下还有一种情况是被认成矿泉水瓶。透明 PET 瓶在高光下轮廓断裂深色液体隔着瓶身反光看又和背景搅在一起。根子在于训练图大多是白底棚拍瓶身反光区域在颜色空间里和白色背景几乎没有边界模型学到的是「红色瓶标」而不是完整瓶型。同一瓶可乐换两个拍摄角度反光形态完全不同模型就认不出来了。解决优先级是补图、调增强、改推理。往训练集补一两百张自然光照的门店图最有效增强里加大hsv_v抖动让瓶身亮度在训练中学会变化推理端对高光区域做 CLAHE 局部均衡有一点改善但治标不治本。4.2 小目标与密集陈列一整面货架怎么数都数不对小目标问题在远景货架图上非常明显一瓶可乐只有二三十像素宽漏检一片中景密集陈列时几个紧贴的瓶框被 NMS 合并成一个最后数量永远对不上。原因不在参数而在分辨率。imgsz640 时小目标占像素太少特征图下采样几轮之后几乎消失anchor 匹配不到正样本损失函数在这一类上学不到东西。这是 yolo 系列在小目标上的老问题。预算够就imgsz1280训练和验证分辨率翻倍对 20 像素的小瓶是质变代价是显存翻倍显存不够就保持 640推理时用 SAHI 把大图切成小图分别检测再拼回坐标。接了深度相机想做测距的话先等检测框稳定再谈距离框歪了测出来的距离没有任何意义。4.3 场景单一导致过拟合棚拍训练集门店部署直接翻车场景过拟合的典型表现是训练集 mAP 做到 0.95拿到真实门店摄像头一测只有 0.7还伴随大量误检。5166 张图里很多是同一批棚拍或同一货架的重复角度有效场景可能只有几百个。模型把背景纹理、灯光色温当成了特征。白底棚拍训出来的模型一旦遇到木纹货架、日光灯色温、手指遮挡置信度立刻崩。最有效的办法是带上一版模型去目标门店采 200~500 张图人工框几十张做 fine-tune这是产品识别落地的常规路径。不想采图就做背景替换增强把目标 ROI 抠出来随机贴到真实货架背景上再合成训练样本。只做翻转、加高斯噪声这类通用增强对场景过拟合帮助很小。4.4 标签噪声与类别不平衡5166 张里的分布可能和你想的不一样标签噪声的表现是训练曲线正常但某个类别 recall 明显低于其他类打开验证集预测图该框的没框框了的类别不对。根源是标注标准不统一。「可口可乐」到底指经典款还是包含零度瓶、罐、箱要不要分开多人协作标注时这两类标准混在一起模型就学出一个四不像类别。另一个常见问题是类别不平衡经典款可能占了一半的框小瓶装只有几百个模型自然会牺牲少数类。训练前跑一遍类别频次和框面积统计。频次差 5 倍以上要么合并成一个大类要么在训练时提高少数类的损失权重。框面积两极分化严重时按面积过滤掉极端大框或小框比硬调 anchor 更直接。4.5 数据划分泄漏验证集指标看着漂亮现场一测就崩划分泄漏最气人val mAP50 有 0.95换一个随机种子重新划分再训结果差了 5 个点部署到现场效果远不如验证集。原因就是划分的最小单位错了。同一瓶可乐、同一个货架的连续帧在随机划分时被拆进了训练集和验证集验证集变成了「半梦见过」的图。5166 张里连拍帧占比越高泄漏越严重。解决方式是按拍摄批次或场景目录分组整个组只进训练集或只进验证集。也可以先用感知哈希对全部图像算相似度高度重复的帧去掉一部分再做划分。判断泄漏的土办法是看训练 mAP 和验证 mAP 的差距小得异常比如两个都到 0.99基本就是泄漏了。5. 从训练到部署算 mAP、导出 ONNX 与实时识别的三个检查点模型训练完还要在验证集上正式评估一次再导出成部署格式。这一步能让你从「训练脚本跑完了」过渡到「模型真的能用了」。5.1 在验证集上算 mAP50 和 mAP50-95yolo detect val \ data/home/you/coke_dataset/data.yaml \ model./runs/coke_product/weights/best.pt \ imgsz640 batch32结果里重点看 mAP50 和 mAP50-95 两个数。产品识别更看重 mAP50货架计数和质检对「框大概在不在」敏感mAP50-95 更严苛框位置偏差一点就掉分。验证集指标这时候有点玄学别只看数字配合 3.4 的预测图一起判断。5.2 导出 ONNX让模型脱离 PyTorch 环境跑起来yolo export model./runs/coke_product/weights/best.pt formatonnx导出后可以用 ONNX Runtime 在 CPU 上推理也可以在 Jetson AGX Orin 这类设备上继续转 TensorRT engine这是边缘盒子上搭 YOLO 环境的常见做法。默认导出参数够用真要多 batch 推理再开dynamicTrue。5.3 一瓶可乐都认不准时先回来查这三件事第一部署代码里的 names 顺序和训练 data.yaml 是否一致顺序不一致可乐会变零度第二预处理是否和训练一致letterbox 保持宽高比后再归一化BGR/RGB 通道顺序反了颜色全偏第三置信度阈值别设太低产品识别现场调到 0.35 到 0.5比在训练端加正则更省事。我第一次拿这种带标签的现成数据集跳过体检直接开训结果在客户现场被摄像头底下的透明瓶身教做人。后来凡是从网上下数据集我都先做标签统计、分层划分、跑 baseline折腾半小时省的是后面调参的一整天。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询