Ultralytics SKU-110K 零售货架密集场景检测数据集:从 YAML 配置到 YOLO 训练全流程解析
SKU-110K 是 Ultralytics 官方支持的一个单类、高目标密度的零售货架目标检测数据集,常用于训练和评测 YOLO 系列模型在拥挤场景下的检测能力。本文基于仓库中的 SKU-110K 数据集文档 与 SKU-110K.yaml 配置文件 展开,讲清该数据集的划分、YAML 配置、自动下载与标注转换机制,以及训练 YOLO26 的完整命令与代码写法,帮助你把这套"13.6 GB 一键下载 + 自动转 YOLO 格式"的数据集真正用起来。
一、SKU-110K 数据集概览
SKU-110K 是一个由 Eran Goldman 等人(CVPR 2019 论文《Precise Detection in Densely Packed Scenes》)创建的单类目标检测数据集,包含 11,743 张密集排列的零售货架图像,划分为 8,219 张训练、588 张验证、2,936 张测试图像。
理解这个数据集有三个关键数字:
- 1 个检测类别:所有商品都标注为一个
object框(names: {0: object}),标注中不包含任何逐 SKU 的品类信息; - 11 万个 SKU:"SKU-110K" 的 "110K" 指的是横跨全部图像的不重复 store-keeping unit(商品单元)数量超过 11 万,而不是 11 万个检测类别——这是该数据集最常见的误解;
- 170 万个标注框:全部图像累计超过 170 万个商品标注框,平均每张图像约 147 个紧密排列的商品目标。
这种"同类目标高度相似、彼此紧邻"的密集排列,使 SKU-110K 成为检验检测器在拥挤零售环境中定位精确性的典型基准。数据集许可为 Research-Only(仅研究用途),实际工程使用前应自行确认授权范围。
二、关键特性与适用场景
文档归纳了 SKU-110K 的三大关键特性:
- 单类检测(Single-class detection):每个商品一个边界框,全部归入唯一类别
object,模型只需学习"哪里有商品",而不需要区分具体商品种类; - 极致的目标密度(Extreme object density):图像来自世界各地的商店货架,平均每张约 147 个目标,且外观相近甚至相同的商品常常紧贴在一起,对 NMS、小目标定位和重叠框区分都是强考验;
- 大规模(Large scale):11 万+ 唯一 SKU、170 万+ 标注框、11,743 张图像,足以训练并压测最先进的检测器。
文档列出的典型应用方向包括:
- 零售库存管理与自动化(retail inventory management);
- 电商平台中的商品识别(product recognition);
- 陈列图合规校验(planogram compliance verification);
- 门店自助结账系统(self-checkout);
- 仓库中的机器人抓取与分拣(robotic picking and sorting)。
如果你的目标恰好是"数货架上的商品"、"检测漏摆/错摆位置"这类任务,SKU-110K 提供的高密度单类标注形态与实际业务高度吻合。
三、数据集划分
SKU-110K 的三个子集共享同一个 object 类别:
| 划分 | 图像数 | 用途 |
|---|---|---|
| Train | 8,219 | 模型训练的图像与标注 |
| Validation | 588 | 训练期间用于 验证 的留出图像 |
| Test | 2,936 | 训练完成后的最终评测图像 |
三个子集各自以图像清单文件(train.txt / val.txt / test.txt)形式引用,这也是理解其 YAML 配置的关键。
四、数据集 YAML 配置详解
数据集配置由 ultralytics/cfg/datasets/SKU-110K.yaml 定义,包含数据集路径、类别名和一段内嵌的下载/转换脚本。完整内容如下:
# Ultralytics AGPL-3.0 License - https://ultralytics.com/license
# SKU-110K retail items dataset by Trax Retail
# Example usage: yolo train data=SKU-110K.yaml
# parent
# ├── ultralytics
# └── datasets
# └── SKU-110K ← downloads here (13.6 GB)
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, ...]
path: SKU-110K # dataset root dir
train: train.txt # train images (relative to 'path') 8219 images
val: val.txt # val images (relative to 'path') 588 images
test: test.txt # test images (optional) 2936 images
# Classes
names:
0: object
# Download script/URL (optional)
download: |
import shutil
from pathlib import Path
import numpy as np
import polars as pl
from ultralytics.utils import TQDM
from ultralytics.utils.downloads import download
from ultralytics.utils.ops import xyxy2xywh
# Download
dir = Path(yaml["path"]) # dataset root dir
parent = Path(dir.parent) # download dir
urls = ["http://trax-geometry.s3.amazonaws.com/cvpr_challenge/SKU110K_fixed.tar.gz"]
download(urls, dir=parent)
# Rename directories
if dir.exists():
shutil.rmtree(dir)
(parent / "SKU110K_fixed").rename(dir) # rename dir
(dir / "labels").mkdir(parents=True, exist_ok=True) # create labels dir
# Convert labels
names = "image", "x1", "y1", "x2", "y2", "class", "image_width", "image_height" # column names
for d in "annotations_train.csv", "annotations_val.csv", "annotations_test.csv":
x = pl.read_csv(dir / "annotations" / d, has_header=False, new_columns=names, infer_schema_length=None).to_numpy()
images, unique_images = x[:, 0], np.unique(x[:, 0])
with open((dir / d).with_suffix(".txt").__str__().replace("annotations_", ""), "w", encoding="utf-8") as f:
f.writelines(f"./images/{s}\n" for s in unique_images)
for im in TQDM(unique_images, desc=f"Converting {dir / d}"):
cls = 0 # single-class dataset
with open((dir / "labels" / im).with_suffix(".txt"), "a", encoding="utf-8") as f:
for r in x[images == im]:
w, h = r[6], r[7] # image width, height
xywh = xyxy2xywh(np.array([[r[1] / w, r[2] / h, r[3] / w, r[4] / h]]))[0]
f.write(f"{cls} {xywh[0]:.5f} {xywh[1]:.5f} {xywh[2]:.5f} {xywh[3]:.5f}\n") # write label
逐项解读配置语义:
path: SKU-110K:数据集根目录,相对于数据集下载目录(默认datasets/,即解压后位于datasets/SKU-110K)。注释中的目录树提示了最终落盘位置,总大小约 13.6 GB;train/val/test: *.txt:这里采用的是 Ultralytics 数据集 YAML 三种引用形式中的"图像清单文件"形式(另一种是直接指向图像目录,或目录列表)。train.txt、val.txt、test.txt每行一条./images/xxx相对路径,由下方下载脚本自动生成;names: {0: object}:唯一的检测类别。check_det_dataset会据此推导nc = 1;download: |内嵌 Python 脚本:这是理解"第一次训练自动下载"行为的核心。脚本分三步:- 从 Trax Retail 官方 S3 地址下载
SKU110K_fixed.tar.gz并解压,将SKU110K_fixed重命名为SKU-110K; - 读取原始的
annotations/annotations_{train,val,test}.csv(无表头,列为image, x1, y1, x2, y2, class, image_width, image_height,坐标为像素级 xyxy),用polars高效解析; - 为每张图像生成 YOLO 格式标签文件:类号固定写
0,像素坐标除以图像宽高归一化后再经xyxy2xywh转为归一化 xywh,每行以 5 位小数写入labels/<image名>.txt;同时把每个子集的去重图像列表写成对应的.txt清单。
- 从 Trax Retail 官方 S3 地址下载
xyxy2xywh 工具函数定义在 ultralytics/utils/ops.py,是 YOLO 标签格式的通用坐标转换入口。
五、自动下载机制:源码层面的调用链
文档提示"SKU-110K 在第一次训练时自动下载,需要约 13.6 GB 磁盘空间,且标注转换可能需要几分钟"。这个行为的实现入口在 check_det_dataset(ultralytics/data/utils.py),调用链可以概括为:
- 解析 YAML:
check_det_dataset(dataset, autodownload=True)被训练流程调用后,先加载 YAML,校验train/val键存在、names或nc存在、类型合法,并把train/val/test路径解析为绝对路径; - 判定是否需要下载:解析后的
val(或指定 split)路径若不存在,且 YAML 中含有download字段、autodownload为真,则触发下载; - 执行内嵌脚本:
download字段以http开头且以.zip结尾时按 URL 直接下载;以bash开头时执行 shell 脚本;否则——SKU-110K 正属于这种情况——以exec(s, {"yaml": data})执行内嵌 Python 脚本,脚本内可以直接引用yaml字典(这就是上面脚本能使用yaml["path"]的原因)。
# ultralytics/data/utils.py 中的核心分支(节选)
if s.startswith("http") and s.endswith(".zip"): # URL
safe_download(url=s, dir=DATASETS_DIR, delete=True)
elif s.startswith("bash "): # bash script
subprocess.run(s.split(), check=True)
else: # python script
exec(s, {"yaml": data})
也就是说,你在训练命令中只需写 data="SKU-110K.yaml",框架会自动完成"下载 13.6 GB 压缩包 → 解压改名 → 逐张图像把 CSV 像素标注转换为 YOLO 标签"的全过程,无需任何手工步骤。下载目录默认是 DATASETS_DIR(datasets/),若空间不足可通过设置文件调整该路径。
六、训练 YOLO26 的完整用法
在 训练文档 的参数体系下,SKU-110K 的训练示例如下(图像尺寸 640、100 个 epoch,从预训练权重开始):
Python API:
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n.pt") # load a pretrained model (recommended for training)
# Train the model
results = model.train(data="SKU-110K.yaml", epochs=100, imgsz=640)
CLI:
# Start training from a pretrained *.pt model
yolo detect train data=SKU-110K.yaml model=yolo26n.pt epochs=100 imgsz=640
几个实用要点:
- 首次运行耗时构成:约 13.6 GB 下载 + 170 万级标注的 CSV→YOLO 转换,文档明确提示"可能需要几分钟",属于预期行为而非卡死;
- 磁盘与网络:训练前请确认
datasets/所在分区有 ≥ 13.6 GB 空闲空间以及到 Trax S3 源点的稳定网络; - 参数查阅:
epochs、imgsz之外的完整训练参数(批大小、增强开关、早停等)参见 Training 文档 与 训练技巧指南; - 评测:训练完成后可用
data="SKU-110K.yaml", split="test"在 2,936 张测试图上做最终评测,验证流程见 Validation 文档。
对于更小的入门需求,检测数据集总览 还列有 coco8、coco128 等体量更小的数据集可用于快速验证管线。
七、样本数据与标注形态
SKU-110K 的图像真实还原了商店货架:数十个外观几乎相同的产品并排陈列,同一张图中既有大目标也有大量小目标。文档给出的示例说明:图像以密集货架为背景,所有商品均用边界框标注在唯一的 object 类下。
从标注转换脚本可以进一步推断其标注形态的细节:原始标注 CSV 中每行含像素坐标 (x1, y1, x2, y2) 及图像宽高,转换后每张图像对应一个 labels/<image名>.txt,每行格式为 cls cx cy w h(归一化、5 位小数)。高物体密度意味着单张图像平均写出约 147 行标注,这也是转换阶段耗时较长的直接原因。这种标注形态对检测器的要求集中在两点:密集小目标不遗漏、相邻相似目标不合并。
八、引用与致谢
在研究或使用该数据集时,建议引用原始论文:
@inproceedings{goldman2019dense,
author = {Eran Goldman and Roei Herzig and Aviv Eisenschtat and Jacob Goldberger and Tal Hassner},
title = {Precise Detection in Densely Packed Scenes},
booktitle = {Proc. Conf. Comput. Vision Pattern Recognition (CVPR)},
year = {2019}
}
文档同时致谢了 Eran Goldman 等人为计算机视觉研究社区创建并维护 SKU-110K 数据集。
九、常见问题(FAQ)
SKU-110K 有 11 万个类别吗?
没有。它是单类数据集:所有商品都标注为 object 类(names: {0: object})。"110K" 指的是图像中出现的唯一 SKU 数量超过 11 万,而非检测类别数。
数据集具体有多少图像和类别?
11,743 张图像(8,219 训练 / 588 验证 / 2,936 测试),1 个检测类别 object。详见上文"数据集划分"一节及 SKU-110K.yaml。
下载体积多大?需要手动下载吗?
约 13.6 GB,无需手动下载——首次以 data="SKU-110K.yaml" 训练时,check_det_dataset 会自动触发 YAML 中内嵌的下载与标注转换脚本。
如何用它训练 YOLO 模型?
直接按第六节的 Python 或 CLI 示例执行即可:加载 yolo26n.pt 预训练权重,data="SKU-110K.yaml"、epochs=100、imgsz=640,首次运行会自动完成数据准备。
小结
SKU-110K 在 Ultralytics 中的定位非常清晰:一个开箱即用的单类、高密度、大规模零售检测基准。它的 YAML 配置展示了 Ultralytics 数据集描述文件"声明路径 + 内嵌下载/转换脚本"的完整形态——path/train/val/test 声明数据布局,names 声明类别,download 脚本负责从 CSV 像素标注一键生成 YOLO 格式标签。理解 check_det_dataset 中的自动下载分支后,你就能把同样的机制迁移到自己的工作数据集 YAML 中,实现"一条训练命令完成数据准备 + 模型训练"。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00