智能零售柜商品检测数据集:三格式标签与YOLO11跨平台训练全攻略
2026/9/24 13:13:11 网站建设 项目流程

简介:面向智能零售柜商品检测项目,这份PDF指南整理了5000张真实监控场景商品图片数据集的完整接入方式。数据集覆盖罐装饮料、袋装零食等常见零售柜商品,共标注113个类别,并配套VOC、COCO、YOLO三种标签格式,可直接用于目标检测模型训练,适合新零售场景的算法工程师、科研人员及竞赛选手使用。指南还介绍了随资源附赠的YOLO11一键训练脚本,支持GPU、CPU及Mac M芯片多平台训练,并给出博主训练结果日志作为效果参考。整份资料仅1个PDF文件,体积5.77MB,内容包括数据集缩略图、标注说明、适用场景说明与百度网盘获取方式。目前已有413人学习浏览,对需要快速获取智能零售柜商品训练数据并搭建检测方案的开发者而言,能显著节省数据检索和格式转换成本。

1. 智能零售柜商品检测数据集:为什么这 5000 张图和三格式标签值得你先看

做智能零售柜的都知道,柜子里那点东西比开放货架难搞得多。饮料瓶反光、包装袋褶皱、小包零食堆叠,加上柜内补光灯角度刁钻,商品边缘经常跟背景糊在一起。很多团队拿着通用目标检测模型直接上,结果在测试集上 mAP 挺好看,一放进真实柜子就漏检。我接触过不少做新零售设备方案的朋友,大家最后都卡在同一个环节:没有一套贴合柜内场景、标注格式齐全、能直接喂给训练脚本的数据资产。所以看到这个「智能零售柜商品检测数据集」标题时,我先关注的是三件事:图数是否够用、三种标签是否对齐、以及训练脚本是否真的能在不同硬件上跑起来。

这套方案把 5000 张图配齐 VOC、COCO、YOLO 三种格式标签,同时给出支持 GPU、CPU、Mac 三平台的 YOLO11 一键训练脚本,正好命中零售柜识别项目从数据准备到模型训练的全链路缺口。适合谁用?比如你正在做智能货柜视觉方案选型,或是算法岗需要快速验证柜内商品检测可行性,又或者你手里的标注数据只有一种格式想统一成 YOLO 管线,这套组合能帮你省掉好几周的数据整理时间。接下来我按实际落地顺序,把数据场景、格式转换、平台适配和主要坑位都拆开讲一遍。

2. 零售柜场景为什么让通用检测模型翻车:先搞懂数据背后的三个难点

2.1 小目标占比高:货架纵深与相机距离之间的矛盾

零售柜内部通常只有 30 到 60 厘米深,但摄像头要覆盖 4 到 7 层货架,单件商品在画面里经常只有 30×30 像素甚至更小。YOLO 系列默认的输入尺寸是 640×640,在这个分辨率下小目标特征会在下采样过程中快速衰减。你可以自己做个试验:找一张柜内实拍图,把一件 250ml 饮料的标注框输出出来,跟整张图的宽高比一下,大概率宽度占比不到 5%。这就解释了为什么很多团队用通用预训练权重直接推理时,小瓶装商品频繁漏检。

处理这类数据的首要原则是别急着改模型结构,先把标签质量抓起来。我在处理零售柜数据时,会先统计所有标注框的宽高分布,把那些宽或高小于 20 像素的框单独拎出来检查一遍,看是标错了还是真实存在极小目标。这个环节最花时间,但效果立竿见影。

2.2 类间相似度高:同品牌不同口味只有一个标签差异

智能柜里最常见的情况是三瓶不同口味的同系列饮料摆在一起,包装主色一致,差异集中在标签上一小块图案。如果标注人员在框选时不够细致,模型很容易把特征学成「这个位置有一瓶饮料」,而不是「这是草莓味还是原味」。这也是零售柜数据集比通用目标检测数据集更讲究标注一致性的原因——你用 COCO 的 80 类逻辑去理解它是不对的,这里常常一个 SKU 就是一个类别。

拿这个 5000 张图的规模来说,如果类目数控制在 30 到 60 个 SKU 之间,平均每个类有 80 到 160 个实例,基本够训练出一个能用但不算饱满的模型。我的经验是:如果单类实例少于 50,就该考虑数据增强或者采集更多样张,否则这个类别大概率会过拟合到柜内固定位置和固定光照上。

2.3 光照和反光:标签噪声之外的隐性干扰

柜内商品表面有塑封膜、玻璃瓶、易拉罐,补光灯一打,每张图都带着高光区域。高光会让边框附近的纹理失真,特别是瓶身弧面边缘,人眼都可能看走眼。很多数据集标注时没考虑这一点,导致训练出的模型对亮度极其敏感,同一商品换个摆放角度就检测不出来。

所以我拿到任何零售柜数据集后,第一件事不是急着配训练脚本,而是随机挑 200 张图做一次标签抽检,看框的贴合度和类别一致性。5000 张图做全量抽检不现实,但 4% 的样本量已经能发现系统性标注错误,比如某个类别整体偏移了几个像素、某个 SKU 的标签串到了另一类上。如果抽检不合格,后续训练投入再多时间也是在脏数据上过拟合。

3. 把 VOC/COCO/YOLO 三种格式盘成一份配置:脚本转换与对齐细节

3.1 先认识三种格式在零售柜场景里的角色

标注格式的本质是「用什么结构描述图片里有什么、在哪、属于哪类」。VOC 用的是 XML 文件,一个标注框是一组<bndbox>结点,坐标直接是人可读的像素值,适合人工检查;COCO 用的是单个大 JSON,所有图片和标注通过 id 关联,适合做统一数据管理和跨项目复用;YOLO 则是每个图片对应一个同名 txt,一行写一个class_id center_x center_y width height,坐标已经归一化到 0 到 1 之间,读取效率最高。

实际项目里,我一般把 VOC 当中间格式,用标注工具导出来后先转成 YOLO 直接开训,需要做统计分析时再转 COCO。但如果你手里的数据集只提供一种格式,而你的脚本依赖另一种,就必须自己完成转换。转换本身不复杂,复杂的是保持三类信息一致:类别列表的顺序、坐标系的定义、以及图片和标注文件的名字对应关系。

3.2 用 Python 完成 VOC 转 YOLO:代码与三个必须核对的点

假设你拿到的数据包含Annotations目录下的一堆 XML 文件和JPEGImages目录下的原图,现在要转成 YOLO 格式。直接按下面这个脚本操作:

import os import xml.etree.ElementTree as ET from pathlib import Path # 类别列表是整个转换的核心,顺序必须与后续训练配置完全一致 class_names = ["coke_330ml", "sprite_330ml", "water_500ml", "snack_chips"] # 按需替换 def convert_voc_to_yolo(xml_path, out_path, img_width, img_height): tree = ET.parse(xml_path) root = tree.getroot() lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in class_names: continue # 跳过不在列表内的类别,避免污染训练标签 class_id = class_names.index(name) box = obj.find("bndbox") x_min = float(box.find("xmin").text) y_min = float(box.find("ymin").text) x_max = float(box.find("xmax").text) y_max = float(box.find("ymax").text) # 坐标归一化:YOLO 要求中心点和宽高都除以图片宽高 x_center = (x_min + x_max) / 2 / img_width y_center = (y_min + y_max) / 2 / img_height width = (x_max - x_min) / img_width height = (y_max - y_min) / img_height # 边界裁剪:防止标注越界导致的归一化数值异常 x_center = min(max(x_center, 0.0), 1.0) y_center = min(max(y_center, 0.0), 1.0) width = min(max(width, 0.0), 1.0) height = min(max(height, 0.0), 1.0) lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}") with open(out_path, "w") as f: f.write("\n".join(lines)) # 遍历目录示例 annotations_dir = Path("./Annotations") images_dir = Path("./JPEGImages") labels_dir = Path("./YOLOLabels") labels_dir.mkdir(exist_ok=True) for xml_file in sorted(annotations_dir.glob("*.xml")): img_name = xml_file.stem + ".jpg" img_path = images_dir / img_name # 实际项目中从图像文件头读取尺寸,不要假设固定值 from PIL import Image with Image.open(img_path) as img: w, h = img.size convert_voc_to_yolo(xml_file, labels_dir / (xml_file.stem + ".txt"), w, h)

这段代码里最关键的是class_names列表,它的顺序直接决定了 txt 文件里的class_id。如果你转换时类别顺序是 A、B、C,但训练配置里顺序变成了 C、B、A,那模型学到的所有类别都是错位的。另外要注意,代码里我加了归一化后的边界裁剪,因为实际标注中偶尔会出现框的某条边超出图片边界的情况,不处理的话训练时会报坐标越界错误。

转换完成后,我会做一次抽查:随机选 10 张训练图,用 OpenCV 把标签画回原图检查贴合度。这一步能发现 xml 和 jpg 文件名不对齐、坐标单位不统一(有的标注工具用整数,有的用浮点)这类隐蔽问题。

3.3 COCO 与 VOC 之间互转:注意 id 连续性和 area 字段

COCO 格式转 VOC 时最常见的坑是 category id 不连续。COCO 官方数据集里类别 id 从 1 开始且连续,但自定义数据集经常出现 id 跳号的情况。如果你不重映射,转换出的 XML 里类别标签就会错乱。我的做法是先构建一份id_to_name字典,按 id 升序排序后重新从 1 开始编号,再做映射。

从 VOC 转 COCO 时,area字段必须保证非零,否则 COCO 的评估脚本会直接忽略该框。你只需要计算(x_max - x_min) * (y_max - y_min)即可,但要注意如果原始标注里出现了退化框(宽或高为 0),要提前过滤掉。另外 COCO 的图片id和标注id必须全局唯一,不能用文件名替代,我会显式用自增数生成。

3.4 一个文件清单搞定数据集自检:训练前必跑的三条命令

在正式跑训练脚本之前,先对数据集做一轮机器自检,能省掉大量排查时间。我把需要检查的内容列成一张对照表:

检查项命令或方法通过标准
图片与标签一一对应对比JPEGImageslabels目录下的文件名集合两边文件名的.stem完全一致
标签内容可解析python -c "import cv2; ..."逐行读取 txt 并拆分浮点数每行恰好 5 个数值,且 class_id 在合法范围内
归一化坐标合法检查所有数值是否在[0, 1]区间内不允许出现负数或大于 1 的值
类目均匀度统计每个 class_id 的实例数量单类数量不少于 50,且没有明显断档

这三条命令对应的操作都不难:第一条用comm命令对比文件名,第二条写个 10 行的 Python 脚本逐文件读取,第三条直接grep -E正则扫一遍。做完这套自检,数据才有资格进入训练环节。

4. 让 YOLO11 一键训练脚本同时吃下 GPU/CPU/Mac:设备适配是门手艺

4.1 三平台训练的本质差异:不是改个布尔值那么简单

YOLO11 基于 Ultralytics 框架,底层支持 PyTorch。PyTorch 在不同平台上的计算后端不同:Windows 和 Linux 上用 CUDA 调 NVIDIA 显卡,Mac 上用 MPS 调 Apple Silicon 的 Metal 加速,都没有这些硬件就退回 CPU 计算。显卡硬件版本非常老旧时,代码里的 GPU 检测机制可能会有对较新架构特性的依赖,导致执行到一半报设备能力不够的错误,这类问题我一般在脚本开头就先做一次设备能力校验,不满足就直接报警提示,而不是等训练跑起来才让用户面对一堆晦涩错误。

一键训练脚本的真正难点在于:它要自动判断当前机器有什么设备,选择对应的后端,同时处理好不同后端对内存和批大小的约束。比如同样一张 640×640 的图,在 12GB 显存的显卡上可以跑 batch size 16,在 Mac 的 16GB 统一内存上可能只能跑 8,在纯 CPU 机器上 4 都勉强。脚本如果不做这些参数的自适应,用户跑起来就是各种 OOM 报错。

4.2 写一个能自动选设备的 Python 启动器

我给零售柜项目写训练脚本时,习惯于先用一个detect_device()函数做设备探测,再根据设备类型动态调整训练参数。参考下面的结构:

import torch from ultralytics import YOLO def detect_device(): """ 按优先级返回可用设备:CUDA > MPS > CPU 同时返回设备名称,供后续参数调整使用 """ if torch.cuda.is_available(): device = "cuda" gpu_name = torch.cuda.get_device_name(0) total_mem = torch.cuda.get_device_properties(0).total_memory / 1024**3 print(f"[设备] CUDA 可用:{gpu_name},显存 {total_mem:.1f} GB") return device, gpu_name elif torch.backends.mps.is_available(): device = "mps" print("[设备] Apple MPS 后端可用,使用 GPU 加速") return device, "MPS" else: device = "cpu" print("[设备] 未检测到 GPU,回退 CPU 训练(速度会慢很多)") return device, "CPU" def adjust_batch_by_device(device, gpu_name="", default_batch=16): """根据设备类型动态调整 batch size,避免 OOM""" if device == "cuda": # 显存小于 8GB 时降低 batch,防止显存溢出 if "8GB" in gpu_name or any(k in gpu_name for k in ["1660", "2060", "3050"]): return 8 return default_batch elif device == "mps": return 8 # MPS 后端显存与内存共享,保守一点 else: return 4 # CPU 训练 batch 太大没有意义,反而拖慢 if __name__ == "__main__": device, name = detect_device() batch = adjust_batch_by_device(device, name) # 加载自己数据集的 yaml 配置,注意 class 顺序必须与转换脚本一致 model = YOLO("yolo11n.pt") model.train( data="retail_cabinet.yaml", epochs=100, imgsz=640, batch=batch, device=device, workers=4 if device != "cpu" else 2, amp=False if device == "mps" else True, # MPS 的混合精度支持还不完善 project="runs/retail_cabinet", name="exp", patience=20, )

这段代码把最容易出问题的几个点都兜住了。detect_device函数按优先级返回设备,避免用户手动改参数;adjust_batch_by_device根据设备类型和显存大小动态调整批大小,防止 OOM;amp=False if device == "mps" else True是因为 PyTorch 的 MPS 后端在做自动混合精度时偶发数值异常,我在 Mac 上训练时遇到过 loss 变成 nan,关了之后一切正常。

4.3 零售柜数据集的 YAML 配置:类别表是唯一真理

训练脚本依赖一个数据配置文件,指向图片目录、标签目录和类别名称。这个文件写错一处,前面所有格式转换的努力就白费了。零售柜场景下我的retail_cabinet.yaml长这样:

path: ./datasets/retail_cabinet train: images/train val: images/val nc: 4 names: 0: coke_330ml 1: sprite_330ml 2: water_500ml 3: snack_chips

names的顺序必须与 VOC 转 YOLO 脚本里的class_names列表逐一对应,差一个位置都不行。这其实是整个数据链路里最容易翻车的地方——标注格式转换脚本里的类别顺序是自己定义的,训练配置里的类别顺序又是在 YAML 里写的,两边一旦没有同步,模型训练出来的预测结果就全乱了。我一般会在detect_device()之后加一段调试代码,把 YAML 里的 names 和数据集标签中实际出现的类别 id 做一个交集检查,不匹配就立刻停止训练,算是给代码上最后一道保险。

4.4 CPU 和 Mac 上的训练预期管理

说实话,CPU 训练 YOLO11 在 5000 张图上跑 100 个 epoch,按照常见配置大概要 20 到 30 个小时,基本只能用来验证代码能不能跑通。如果你只有 CPU,我的建议是把epochs降到 10,imgsz降到 416,先走通流程,再找一台 GPU 机器做正式训练。Mac 的情况好一些,M1 及以上芯片的 MPS 加速差不多是入门级 NVIDIA 显卡的 60% 到 70% 性能,但要注意 PyTorch 版本不能太旧,MPS 支持在 1.12 之后才逐渐稳定。另外 Mac 训练时不要插着电看温度,MPS 跑满 30 分钟后风扇会开始啸叫,机身材质传递热量明显,属于正常现象,不用太担心。

5. 智能零售柜训练避坑:五条血泪经验让你少走一个月弯路

5.1 数据划分不当导致类别分布失衡

现象:训练集 mAP 接近 0.95,验证集 mAP 只有 0.6,差距悬殊。

原因:零售柜数据通常来自同一个柜子的不同时段拍摄,如果按文件名顺序直接划分 train/val,可能出现某个 SKU 只在训练集出现、验证集完全没有的情况,或者某类商品在训练集只有 20 张,验证集却有 80 张。这种随机划分在类别数量多、单类样本量少的数据集上特别容易翻车。

解决:按类别做分层采样,保证每个类别在训练集和验证集里的比例接近整体比例。具体来说,先统计每个类的实例数量,然后按比例把图片分配到两个集合,同类图片尽量均匀分布。如果某类实例太少,就把它全部放进训练集,验证集不包含该类,避免模型评估时被极小样本量干扰。

5.2 Mac 上训练 loss 变成 nan

现象:训练第 2 个 epoch 开始 loss 输出显示 nan,模型权重失效。

原因:MPS 后端的自动混合精度实现存在一些算子兼容问题,PyTorch 的torch.backends.mps在 float16 计算时偶发异常值。很多 Mac 用户第一次跑训练脚本时中招,还以为是代码问题。

解决:直接在训练参数里关闭 AMP,amp=False。代价是训练时间增加约 20%,但换来的是稳定收敛。如果你的 PyTorch 版本大于 2.0,还可以试试torch.set_float32_matmul_precision("medium"),有些场景能缓解数值波动。

5.3 边框全偏移导致漏检:标签坐标系被默认参数带偏

现象:新模型在部分货道位置检测框整体向右下偏移,尤其在图像边缘区域严重。

原因:标注工具导出 VOC 时,有些会带posetruncated这类附加信息,但坐标本身是正常的。问题出在读取 XML 的脚本里用了硬编码的img_width=1920img_height=1080,而实际图片尺寸是 1280×960。归一化时除错了分母,所有框的坐标都被压缩或拉伸。

解决:转换代码里严格从图片头部读取尺寸,不要相信任何预设值。我在convert_voc_to_yolo函数里用 PIL 读图取了真实的img.size,这就是最可靠的做法。另外,归一化之后不要立刻覆盖原标签,先输出一份 heatmap 可视化图,确认框的位置和物体对齐后再替换旧文件。

5.4 小目标漏检率居高不下

现象:瓶装饮料检测正常,但类似口香糖、小包巧克力这类小于 30×30 像素的商品频繁漏检。

原因:YOLO11 默认解耦头对小目标的特征融合做了一些优化,但在输入分辨率 640 的情况下,小目标的特征图尺寸非常有限。如果数据集中小目标占比不高,模型会倾向于忽略小的候选框。

解决:先把输入分辨率调整到 832 或 1024,但要注意这会显著增加训练和推理耗时。更有效的做法是检查数据集里小目标的比例,如果超过 30%,可以考虑用 SAHI 这类切片推理方案在推理阶段把小图放大。零售柜场景比较取巧的办法是直接按货道切图,把单层货架区域裁出来再检测,小目标比例瞬间下降。

5.5 训练中途显存溢出 OOM

现象:GPU 训练第 38 个 epoch 时突然报CUDA out of memory,前面全部白跑。

原因:除 batch size 过大外,workers数量过高也会让数据加载器占满共享内存,尤其当你的机器同时跑着可视化界面时。另外 Ultralytics 默认开启 cache 功能,如果评估缓存也占用显存,叠加起来就溢出了。

解决:在model.train()参数里显式设置cache=False,同时降低workers到 2。如果显存小于 8GB,把batch设成 4 到 8 之间,开启梯度累积accumulate=4来补偿小 batch 带来的 BN 统计波动。

6. 验证零售柜模型能不能用:自定义评估逻辑比 mAP 数字更要紧

模型训练完,输出 mAP@0.5 到 0.95 的数字只能说明模型在这个数据集上的表现,但不等于在实际柜子里能用。零售柜场景里我最看重三个额外指标:单次推理耗时、边缘货道漏检率、以及补光灯亮度切换后的稳定性。具体怎么验证呢?我会写一个评估脚本,模拟柜机运行时的推理逻辑——相机拍到一张图,检测模型输出所有商品框,然后按货道区域做归类和数量统计,最后与真实库存做差。这一步跑通了,模型才真正达到交付状态。

实际调优中,我习惯做一个轻量的在线增强验证:把同一张测试图随机调整亮度、对比度和饱和度,各生成 5 个版本,然后看模型输出的检测框是否稳定。零售柜内补光灯有时会从暖光切成冷光,商品颜色偏移比较大,如果模型在这个测试下掉点超过 10%,就需要补充更多光照变化的样本,而不是继续调网络结构。

最后想提一个我自己的习惯:每次训练都会把 yaml 配置文件、类别列表、转换脚本的版本一起归档,训练完把数据集划分的随机种子固定住。这样模型效果下滑时能准确定位是数据变了还是代码变了,而不是靠玄学调参。零售柜项目迭代快,这种可复现的训练环境能帮你省下大量返工时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询