☰
智能零售柜商品识别数据集:5000张VOC与YOLO双格式实战指南
2026/10/4 6:24:04 网站建设 项目流程

简介:面向智能零售结算场景的商品识别检测数据集,适合从事计算机视觉目标检测的开发者、学生及算法工程师,用于训练与评估自动结算系统中的商品识别模型。数据集共5422张已标注图片,覆盖113类商品,并已划分训练集3796张、验证集1084张、测试集542张,可直接用于PaddleDetection、PaddleX及YOLO系列、SSD、PPYOLO等主流检测框架。压缩包内共8057个文件,以jpg图像、xml标注和txt标签为主,分别对应原始图片、VOC格式标注与YOLO格式标签,整体约881.5MB,兼顾两种常用标注格式,省去格式转换环节。已有597人学习下载,参考项目中最高mAP可达96.41,可作为智能零售柜商品检测的基线数据,帮助读者快速复现训练流程、验证算法效果并对比不同检测模型的表现。

1. 智能零售柜商品识别数据集:5000 张 VOC 与 YOLO 双格式到底怎么用

做智能零售柜这行,绕不开一个现实:柜子里塞满饮料、零食、日用品,SKU 动辄几百上千,靠人工盘点不现实,靠 RFID 成本高还容易串读,最后大家都会走到视觉识别这条路。而视觉识别的第一道坎,从来不是模型选哪个,而是数据从哪来。你手上如果有一个 5000 张规模、同时带 VOC 格式和 YOLO 格式标签的商品识别检测数据集,那基本等于把冷启动阶段最痛苦的一步给省了。这个标题讲的正是这样一份资源:5000 张零售柜场景的商品图像,标注同时提供 Pascal VOC 的 XML 和 YOLO 的 txt 两套,覆盖检测任务里最常见的两种训练框架入口。它适合三类人:刚接手零售柜算法、需要快速跑通 baseline 的工程师;想验证自己检测模型在密集小目标上表现的算法同学;以及做商品识别产品、需要评估数据成本的项目负责人。下面我不谈虚的,直接讲这份数据怎么落地、参数怎么设、坑在哪。

2. 先搞清楚 VOC 和 YOLO 两套标签的差异与转换逻辑

2.1 两种格式的本质区别不在文件后缀,而在坐标表达

很多人第一次拿到双格式数据集,会以为只是同一份标注换了扩展名,其实不是。VOC 的 XML 存的是绝对像素坐标,xmin/ymin/xmax/ymax直接对应原图上的框位置,宽高由框自身决定;YOLO 的 txt 存的是归一化后的中心点加宽高,class cx cy w h,四个值都在 0 到 1 之间,且 cx、cy 是框中心相对整图宽高的比例。这个差异决定了:VOC 标签换一张分辨率不同的图就失效,YOLO 标签天然跟分辨率解耦。零售柜场景里,同一款商品在不同柜机、不同摄像头下分辨率可能不一样,所以 YOLO 格式在跨设备迁移时更省事。但 VOC 格式可读性强,用 LabelImg 打开能直接看到框,排查标注错误时更直观。两套都留着,本质是给你两条路:想快速可视化核对用 VOC,想直接喂训练用 YOLO。

2.2 目录结构要先对齐,否则训练脚本第一步就报错

拿到压缩包解压后,常见做法是整理成下面这种结构,VOC 和 YOLO 各占一个根目录,图片共用一份,避免重复占空间:

retail_dataset/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── voc_annotations/ │ ├── 000001.xml │ ├── 000002.xml │ └── ... ├── yolo_labels/ │ ├── 000001.txt │ ├── 000002.txt │ └── ... └── classes.txt

classes.txt里一行一个类别名,顺序必须和 YOLO 标签里的 class id 严格对应,第 0 行对应 id 0,第 1 行对应 id 1。这个文件看着不起眼,但它是后面所有类别映射的唯一依据,写错一行,整个训练集的标签全乱。我一般会先wc -l classes.txt确认类别数,再抽查几张图的 txt,看 class id 有没有超出范围。

2.3 从 VOC 转 YOLO 的脚本与四个边界坑

如果手上只有 VOC,或者想自己重新生成一遍 YOLO 标签做校验,用下面这段脚本转换。它读 XML 里的尺寸和框,算出归一化值写进 txt:

import os import xml.etree.ElementTree as ET # 类别名到 id 的映射,顺序必须和 classes.txt 一致 classes = ["drink", "snack", "daily", "other"] class_to_id = {c: i for i, c in enumerate(classes)} def voc_to_yolo(xml_path, out_txt_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") img_w = int(size.find("width").text) img_h = int(size.find("height").text) lines = [] for obj in root.iter("object"): cls_name = obj.find("name").text.strip() if cls_name not in class_to_id: continue # 类别不在表里就跳过,避免脏标签污染训练 bbox = obj.find("bndbox") xmin = float(bbox.find("xmin").text) ymin = float(bbox.find("ymin").text) xmax = float(bbox.find("xmax").text) ymax = float(bbox.find("ymax").text) # 边界裁剪,防止标注越界导致归一化后出现负值或大于1 xmin = max(0, min(xmin, img_w)) xmax = max(0, min(xmax, img_w)) ymin = max(0, min(ymin, img_h)) ymax = max(0, min(ymax, img_h)) cx = (xmin + xmax) / 2.0 / img_w cy = (ymin + ymax) / 2.0 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h # 过滤掉宽高为0的无效框 if w <= 0 or h <= 0: continue lines.append(f"{class_to_id[cls_name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") with open(out_txt_path, "w") as f: f.write("\n".join(lines)) if __name__ == "__main__": xml_dir = "retail_dataset/voc_annotations" out_dir = "retail_dataset/yolo_labels" os.makedirs(out_dir, exist_ok=True) for name in os.listdir(xml_dir): if name.endswith(".xml"): voc_to_yolo( os.path.join(xml_dir, name), os.path.join(out_dir, name.replace(".xml", ".txt")) )

逻辑上,这段脚本做了三件关键事:一是用size里的真实宽高做归一化,不能拿固定值;二是对框做边界裁剪,零售柜标注里经常出现框超出图像边缘的情况,不裁就会算出负数或大于 1 的值,训练时直接报错;三是过滤宽高为 0 的退化框。参数上,classes列表必须和你的classes.txt完全一致,:.6f保留六位小数是 YOLO 生态里比较通用的精度,够用且不会让文件过大。跑完记得抽查:随便挑一张图,用cat看 txt,再用 LabelImg 打开对应 XML,肉眼比对框位置是否一致。

3. 用这份数据集跑通 YOLO 训练的最小闭环

3.1 数据划分与 data.yaml 的写法

5000 张不能全拿去训练,常规做法是训练集 70%、验证集 20%、测试集 10%,也就是 3500 / 1000 / 500。划分时要注意同一款商品、同一个柜机角度尽量别跨集,否则验证集指标会虚高。划分完写一个data.yaml:

path: /data/retail_dataset train: images/train val: images/val test: images/test nc: 4 names: ["drink", "snack", "daily", "other"]

nc是类别数,必须和names长度一致,也和classes.txt行数一致。path用绝对路径最稳,相对路径在不同工作目录下跑容易找不到图。YOLO 找标签的默认逻辑是把images替换成labels,所以你的目录里最好保持images/train对应labels/train这种镜像结构,省得改代码。

3.2 训练命令与关键参数怎么设

以常见的 YOLOv8 训练入口为例,最小命令是这样:

yolo detect train \ data=/data/retail_dataset/data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs/retail \ name=exp1

参数逐个说:model选 s 而不是 n,是因为零售柜商品密集、小目标多,n 的容量容易欠拟合;imgsz=640是通用起点,如果你的柜机图像里商品特别小,可以提到 960 甚至 1280,但显存和速度要权衡;batch=16在 8G 显存上跑 640 基本稳,爆显存就降到 8;lr0=0.01是 SGD 的常规初始学习率,用 Adam 的话要降到 0.001 量级;patience=20表示 20 轮验证指标不涨就早停,避免过拟合。训练过程中重点看mAP50和mAP50-95两条曲线,如果训练 loss 一直降但验证 mAP 早早平掉,多半是过拟合,回去加数据增强或者减模型容量。

3.3 零售柜场景必须开的增强项

通用增强不够用,零售柜有几个特点:商品排列密集、遮挡严重、光照受柜门玻璃影响大。所以增强配置里我一般会显式打开这几项:mosaic=1.0提升小目标召回,mixup=0.1缓解过拟合,hsv_h=0.015、hsv_s=0.7、hsv_v=0.4模拟不同柜内灯光,degrees=5做小角度旋转,因为摄像头安装角度通常有轻微偏差。flipud建议关掉,商品上下翻转不符合真实摆放逻辑,开了反而引入噪声。这些值不是拍脑袋,是多次在零售柜数据上试出来的经验区间,你可以在此基础上微调。

4. 商品识别数据集落地时的避坑与排查

4.1 类别不均衡导致小类几乎检不出

现象:训练完看混淆矩阵,饮料类 mAP 0.8,日用品类只有 0.2。原因:5000 张里日用品样本可能只占 5%,模型被大类主导。解决:先统计每个类别的框数量,对少于 500 框的类别做过采样,或者在损失里给稀有类加权。YOLO 本身没有直接的类权重参数,常见做法是复制含稀有类的图像进训练集,或者用copy-paste增强把稀有商品贴到其他图上。

4.2 标签越界和宽高为 0 让训练直接崩

现象:训练启动几轮后报nan或者断言失败。原因:VOC 转 YOLO 时没做边界裁剪,出现负坐标或大于 1 的值;或者标注时手滑画了零面积框。解决:转换脚本里必须加裁剪和过滤,转换完再跑一遍校验脚本,遍历所有 txt,检查每个值是否在 0 到 1 之间、w 和 h 是否大于 0。这一步花十分钟,能省掉后面几小时的排查。

4.3 图像和标签文件名对不上

现象:训练日志里 warning 一堆「image not found」或者「label missing」。原因:图片是.jpg,标签是.txt,但有的图没有对应标签,或者扩展名大小写不一致。解决:写个脚本比对images和labels两个目录的文件名集合,找出差集,缺标签的图要么补标要么移出训练集。零售柜数据里经常有纯背景图,这种图没有目标,YOLO 允许空标签文件,但文件名必须存在。

4.4 验证集指标虚高,上线就翻车

现象:验证集 mAP 0.9,实际柜机测试掉到 0.5。原因:划分数据时同一柜机、同一批次的图被分到了训练和验证两边,模型其实见过类似场景。解决:按柜机 ID 或拍摄批次做分组划分,确保验证集的柜机和训练集不重叠。这个坑最隐蔽,因为指标好看的时候没人会怀疑划分方式,等上线才发现问题,后悔药没得吃。

4.5 玻璃反光和遮挡造成的漏检

现象:柜门有反光或者商品被前排挡住时,漏检明显。原因:训练集里这类困难样本太少,模型没学到。解决:专门收集一批反光、遮挡的图,哪怕只有两三百张,加进训练集做微调,效果比调参明显。另外推理时可以适当降低置信度阈值,从 0.25 降到 0.15,召回会回来一些,代价是误检略增,零售柜场景里漏检比误检更不可接受。

5. 把 5000 张用出 5 万张的效果:进阶技巧与验证习惯

数据量固定的时候,提升空间在用法上。第一个技巧是「难例回流」:模型上线后,把置信度在 0.3 到 0.5 之间的预测框对应的图挑出来,人工复核后加进训练集,迭代两三轮,mAP 通常能涨 5 到 10 个点。第二个技巧是「多尺度训练」,在data.yaml同级配置里把imgsz设成范围,比如 640 到 960 随机,让模型适应不同柜机分辨率,比固定尺寸泛化好。第三个是「类别合并再拆分」,如果某些 SKU 外观极像,先合并成一个大类训一版,再把 backbone 冻结、换分类头做细分类,比直接训几百类稳得多。

验证习惯上,我坚持两件事:一是每次训练完必须用测试集跑一遍yolo detect val,看混淆矩阵和 PR 曲线,不能只看训练日志的 mAP;二是抽 20 张测试图做可视化,把预测框画出来肉眼过一遍,很多标注错误和逻辑问题只有看图才能发现。表格里是我常用的验证检查项:

检查项合格标准不达标时先查
类别框数量分布稀有类不少于 300 框是否需过采样
标签值范围全部在 0~1 之间转换脚本边界裁剪
训练/验证 mAP 差距小于 0.15是否过拟合或划分泄漏
单图推理耗时满足柜机实时要求模型尺寸和 imgsz
困难样本召回反光遮挡场景可接受是否需补难例

最后说个我自己的习惯:拿到任何一份商品识别数据集,先别急着训模型,花半小时把类别分布、框大小分布、图像分辨率分布画出来。这三个分布图能告诉你这份数据适合什么模型、该设什么 imgsz、哪些类需要特殊照顾。我早期跳过这一步,直接开训,结果跑了三天才发现某类样本只有几十个,白白浪费算力。数据这行,前期多看一眼,后期少熬一夜。希望帮到你。

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

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

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

立即咨询