YOLOv11货架商品识别实战:从训练调参到库存自动化管理 简介这份PDF文档面向零售行业技术人员、计算机视觉学习者与门店数字化方案设计者围绕YOLOv11在货架商品识别与库存自动化管理中的落地展开帮助读者理解如何用单阶段目标检测替代低效的人工盘点与手工记录。资源包共1个PDF文件大小约2.13MB支持目录章节跳转、阅读器左侧大纲显示与章节快速定位查阅体验完整流畅。文档共38页内容涵盖零售业智能升级背景与需求、YOLO系列算法演进与YOLOv11网络结构原理、货架商品识别系统搭建数据采集标注、模型训练评估、系统集成测试、库存自动化管理系统实现实时监控、补货提醒、盘点与销售分析、数据与模型及架构层面的性能优化以及大型超市、便利店、精品零售店三类案例的应用效果评估。已有95人学习适合希望系统掌握YOLOv11零售落地路径、对照目录快速定位关键模块的读者参考。1. 货架商品识别为什么总在最后一米翻车做过零售数字化的人大多有过类似经历摄像头装好了模型也训了离线测试 mAP 看着还行一上真实货架就原形毕露——密集排列的饮料罐互相遮挡、价签反光、商品被顾客拿起来又放回去导致位置错乱库存数字和实际对不上。零售业智能升级落到货架商品识别与库存自动化管理这件事上核心矛盾从来不是能不能检测出商品而是能不能在真实货架的拥挤、遮挡、光照变化下稳定地检测出每一个 SKU并把结果变成可用的库存数据。YOLOv11 作为 Ultralytics 在 2024 年推出的新一代检测框架在骨干网络和特征融合上做了调整对小目标和密集场景相对友好这也是它被大量用在货架场景的原因。这篇笔记面向的是想用 YOLOv11 把货架商品识别真正跑起来、并接到库存管理流程里的工程师从数据准备、模型训练、小目标优化到推理结果落库把每一步的参数和坑讲清楚。2. 从货架图片到可训练数据集标注策略与格式转换2.1 货架场景的数据集该长什么样货架商品识别和通用目标检测最大的区别在于类别体系的设计。通用检测数据集里人车狗是互斥的但货架上同一层可能摆着几十个外观高度相似的 SKU比如不同口味的同一品牌饮料、不同容量的同款洗发水。如果直接把每个 SKU 当成一个类别类别数轻松上百而且长尾分布极其严重——畅销品样本几千张滞销品可能只有十几张。我一般的做法是分两层第一层做商品/非商品和货架层的粗检测用于定位货架结构和判断缺货第二层在粗检测裁剪出的区域内做细粒度 SKU 分类或检测。这样第一层的数据量需求小、泛化好第二层可以针对重点品类单独优化。如果业务要求端到端出 SKU 位置那就必须保证每个类别的实例数不低于 200低于这个数的类别要么合并、要么用数据增强补。采集时要注意几个硬性条件摄像头视角固定货架场景通常用固定枪机而非手持、覆盖早中晚三种光照、包含满架/半空/缺货三种状态。缺货样本尤其重要因为库存自动化管理的核心价值就是发现缺货如果训练集里全是满架图模型会把空位误判成背景。2.2 标注规范与常见错误标注用 LabelImg 或 CVAT 都行关键是框的边界要统一。货架商品密集标注员很容易出现两种偏差一是框贴太紧把商品边缘裁掉几个像素二是框太松把相邻商品的边缘框进来。这两种偏差在训练时都会让模型学到错误的边界特征。统一规范建议框的边界贴着商品可见轮廓的外沿遮挡情况下只标可见部分不要脑补被遮挡的区域。对于被遮挡超过 70% 的商品直接标为忽略区域在 YOLO 格式里可以用一个特殊类别或者干脆不标否则模型会学到大量噪声。2.3 把标注转成 YOLOv11 能吃的格式YOLOv11 沿用 YOLO 系列的标注格式每张图对应一个同名 txt每行是类别索引 中心x 中心y 宽 高坐标全部归一化到 0-1。如果你用的是 COCO 格式或者 VOC 格式需要转换。下面是一个 VOC XML 转 YOLO txt 的脚本import xml.etree.ElementTree as ET import os # 类别名到索引的映射必须和 data.yaml 里的 names 顺序一致 CLASS_MAP {bottle: 0, can: 1, box: 2, bag: 3} def voc_to_yolo(xml_path, img_w, img_h, out_txt_path): 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_MAP: 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) # 归一化并转成中心点宽高 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 边界裁剪防止标注越界导致训练报错 cx min(max(cx, 0.0), 1.0) cy min(max(cy, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{CLASS_MAP[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))这段脚本的关键点有三个CLASS_MAP的顺序必须和训练时data.yaml里的names完全一致否则类别会错乱归一化后的坐标要做 0-1 裁剪因为标注员偶尔会把框拖出图片边界越界坐标会让 YOLOv11 在计算损失时产生 NaN保留 6 位小数是为了避免密集小目标在量化时丢失精度。转换完成后目录结构按 Ultralytics 的约定组织dataset/ images/ train/ val/ labels/ train/ val/ data.yamldata.yaml内容path: /abs/path/to/dataset train: images/train val: images/val names: 0: bottle 1: can 2: box 3: bag提示path建议写绝对路径相对路径在不同工作目录下启动训练时容易找不到数据这是新手最常踩的坑之一。3. YOLOv11 训练货架检测模型参数怎么设、什么时候停3.1 模型选型n/s/m/l/x 在货架场景怎么选YOLOv11 提供 n、s、m、l、x 五个尺度。货架场景的特点是目标密集、单类实例多、但类别语义相对简单都是商品所以不需要特别大的模型容量。我的经验是如果部署在边缘设备如门店的 Jetson 或 RK3588选 yolov11n 或 yolov11s如果部署在服务器端做批量盘点选 yolov11m 性价比最高。l 和 x 在货架场景的收益递减明显因为货架目标的类间差异主要靠纹理和颜色而不是复杂语义大模型容易过拟合到训练集的光照条件。一个反直觉的结论在货架商品识别里yolov11s 加上充分的数据增强往往比 yolov11l 在真实门店的泛化更好。原因是小模型对纹理噪声的鲁棒性反而更强大模型会把训练集里某个货架的特定反光模式记下来。3.2 训练命令与关键参数Ultralytics 的训练入口很简洁但参数含义要清楚yolo detect train \ modelyolov11s.pt \ data/abs/path/to/data.yaml \ epochs200 \ imgsz1280 \ batch16 \ lr00.01 \ lrf0.01 \ warmup_epochs3 \ mosaic1.0 \ close_mosaic20 \ scale0.5 \ degrees0.0 \ fliplr0.5 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ device0 \ projectruns/shelf \ namev11s_1280逐个说关键参数。imgsz1280是货架场景的核心参数因为货架图片里单个商品可能只占 30×30 像素用默认的 640 会让小目标在特征图上只剩几个像素直接消失。1280 的代价是显存和推理时间翻倍但货架检测的精度提升非常明显。如果显存不够可以用imgsz1024折中。mosaic1.0是 YOLO 系列的招牌增强把四张图拼成一张能显著提升小目标和密集场景的表现。但close_mosaic20必须在最后 20 个 epoch 关掉否则拼接边界会让模型学到不存在的图片边缘特征推理时出现莫名其妙的误检。degrees0.0是因为货架摄像头是固定的商品不会旋转开启旋转增强反而会让模型对倒着的商品产生错误认知。fliplr0.5可以保留因为左右翻转不改变商品的语义。hsv_s0.7和hsv_v0.4调得比默认值高是为了应对门店不同时段的光照变化和不同门店的色温差异。这是货架场景和通用检测的重要区别——光照鲁棒性直接决定模型能不能跨店部署。3.3 训练过程怎么判断好坏训练日志里要盯的不是loss而是metrics/mAP50-95和val/box_loss的走势。货架场景常见的一种情况是训练 loss 一直降但验证 mAP 在某个 epoch 后停滞甚至下降这说明模型开始记忆训练集的特定货架布局。这时候应该看验证集里跨货架的那部分样本如果做了划分而不是整体 mAP。另一个要看的指标是每个类别的 AP。货架场景的长尾问题会让某些 SKU 的 AP 极低但整体 mAP 被头部类别拉高掩盖了问题。训练完一定要导出confusion_matrix.png和results.csv逐个类别看。如果验证 mAP 在 150 epoch 左右还在缓慢上升可以继续训到 300如果 100 epoch 就平了加 epoch 没用应该回去检查数据标注质量或者增加数据多样性。4. 小目标与遮挡货架检测绕不开的两个硬骨头4.1 小目标优化的三个实操手段货架商品识别里小目标是最常见的翻车点。一个标准货架层高 40cm摄像头距离 3 米一个 5cm 宽的饮料罐在 1080p 画面里大概只有 40 像素宽缩放到 640 输入后只剩 20 像素。YOLOv11 的 P3 特征图 stride 是 820 像素的目标在 P3 上只有 2-3 个格子特征极其稀疏。第一个手段是提高输入分辨率前面说的imgsz1280就是最直接的办法。第二个手段是调整 anchor 或者用 YOLOv11 自带的anchors自适应机制让先验框更匹配小目标尺寸。第三个手段是切片推理SAHI 思路把大图切成小块分别检测再合并这对超高分辨率货架图特别有效。切片推理的核心逻辑from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction # 加载 YOLOv11 权重注意 model_path 指向训练好的 best.pt detection_model AutoDetectionModel.from_pretrained( model_typeyolov11, model_pathruns/shelf/v11s_1280/weights/best.pt, confidence_threshold0.25, devicecuda:0 ) result get_sliced_prediction( shelf_01.jpg, detection_model, slice_height640, # 切片高度建议和训练 imgsz 接近 slice_width640, overlap_height_ratio0.2, # 切片重叠比例防止目标被切断 overlap_width_ratio0.2 ) result.export_visuals(export_dirvis/)slice_height和slice_width设成和训练分辨率接近能让每个切片里的目标尺度和训练时一致。overlap设 0.2 是为了处理跨切片边界的商品重叠太小会漏检太大则推理时间线性增长。SAHI 的代价是推理时间变成原来的 4-9 倍所以只适合服务器端批量盘点不适合实时视频流。4.2 遮挡处理的思路货架遮挡分两种商品之间的相互遮挡以及货架结构层板、立柱对商品的遮挡。前者靠数据增强里的mosaic和随机遮挡cutout来模拟后者需要在标注时把货架结构也标出来让模型学会区分被挡住的商品和货架本身。一个实用技巧是在训练时加入copy-paste增强把标注好的商品实例随机粘贴到其他货架图上人为制造遮挡组合。Ultralytics 原生不支持这个需要自己写 dataloader 或者在标注阶段就生成合成图。这个手段对提升遮挡场景的召回率效果明显但要注意粘贴的商品光照要和背景一致否则模型会学到粘贴痕迹这个伪特征。4.3 密集场景的 NMS 调参货架商品挨得近默认的 NMS IoU 阈值 0.7 会导致相邻商品被误抑制。把iou调到 0.5-0.6 能保留更多相邻框但代价是同一商品可能出多个框。实际调的时候要看具体货架的密集程度饮料罐排列紧密的用 0.5大件商品用 0.65。推理时的命令yolo detect predict \ modelruns/shelf/v11s_1280/weights/best.pt \ sourceshelf_test/ \ imgsz1280 \ conf0.25 \ iou0.55 \ saveTrue \ save_txtTrue \ save_confTruesave_txtTrue和save_confTrue是接库存管理的关键前者输出每个框的坐标和类别后者带上置信度后续做库存统计时可以用置信度过滤低质量检测。conf0.25是货架场景的经验值低于这个值的框大多是反光或价签引起的误检。5. 从检测结果到库存数字避坑与排查清单5.1 检测框数量不等于库存数量这是最容易翻车的地方。模型在一张货架图上检测出 47 个框不代表库存就是 47。原因有三同一商品可能被检测出多个框NMS 没抑制干净、被遮挡的商品可能漏检、货架深处的商品可能因为透视变形被误判。正确的做法是建立货架-层-位的空间映射。先用货架结构检测确定每一层的位置再把商品框分配到对应的层和位最后按位统计。这样即使某个商品漏检也能通过位空缺判断缺货而不是简单地数框。5.2 常见问题排查现象模型在训练集上 mAP 很高换一个门店就崩。原因训练集的光照、货架材质、摄像头角度太单一模型过拟合到了特定环境。 解决采集至少 3 个不同门店、不同时段的数据训练时加大hsv增强验证集必须包含未见过的门店。现象小目标召回率低大目标正常。原因输入分辨率不够或者 P3 特征层的感受野和小目标尺度不匹配。 解决提高imgsz到 1280 或 1536检查data.yaml里小目标类别的实例数是否足够必要时用 SAHI 切片推理。现象推理结果里同一商品出现多个重叠框。原因NMS 的iou阈值太高或者模型对某个类别的置信度普遍偏低导致抑制不彻底。 解决把iou降到 0.5-0.55检查训练时是否close_mosaic没生效导致模型学到了拼接边界特征。现象训练到一半 loss 变成 NaN。原因标注里有越界坐标或者学习率太高导致梯度爆炸。 解决用前面的转换脚本做坐标裁剪把lr0从 0.01 降到 0.005加warmup_epochs5。现象推理速度远低于预期。原因imgsz太大、模型尺度选太大、或者没开半精度。 解决推理时加halfTrue开启 FP16边缘设备考虑导出 TensorRT 或 ONNXyolo export modelbest.pt formatengine halfTrue。6. 把检测接到库存系统一个可验证的落地技巧模型跑通只是第一步真正决定这套方案值不值得投入的是检测结果能不能稳定地变成库存数字并且这个数字能被业务验证。我一般会做一个双通道校验模型检测出的库存数和 POS 系统的销售数据做对账。如果某个 SKU 模型显示缺货但 POS 显示还有库存或者反过来就说明检测在这一天出了问题需要人工复核。具体做法是在推理结果落库时除了商品类别和数量还记录三个字段检测时间戳、货架 ID、每个检测框的置信度均值。然后用一个简单的 SQL 做日对账-- 找出模型库存和 POS 库存差异超过阈值的 SKU SELECT d.sku_id, d.shelf_id, d.detect_count, p.pos_count, ABS(d.detect_count - p.pos_count) AS diff FROM daily_detect_summary d JOIN daily_pos_summary p ON d.sku_id p.sku_id AND d.shelf_id p.shelf_id WHERE ABS(d.detect_count - p.pos_count) 3 ORDER BY diff DESC;diff 3这个阈值要根据货架容量调小货架用 2大货架用 5。对账差异大的 SKU 自动进入人工复核队列复核结果反过来标注成训练数据形成闭环。这个闭环是整套系统能不能长期跑下去的关键——没有它模型会随着门店陈列变化慢慢退化而你不知道。还有一个技巧是给每个检测框加一个稳定性分数连续 N 帧如果是视频流或者连续 N 次盘点如果是定时抓拍都检测到同一位置有商品才认为这个位置确实有货。单次检测的偶然误检会被这个机制过滤掉。实现上就是在数据库里对同一shelf_id position做计数超过阈值才更新库存状态。# 简化的稳定性判断逻辑 STABLE_THRESHOLD 3 # 连续 3 次检测到才算稳定 def update_inventory(shelf_id, position, detected, history): key f{shelf_id}_{position} if key not in history: history[key] [] history[key].append(1 if detected else 0) # 只保留最近 N 次记录 history[key] history[key][-STABLE_THRESHOLD:] if len(history[key]) STABLE_THRESHOLD and sum(history[key]) STABLE_THRESHOLD - 1: return in_stock elif len(history[key]) STABLE_THRESHOLD and sum(history[key]) 0: return out_of_stock return unknown # 状态未稳定不更新库存这个逻辑看起来简单但它把单次检测的玄学变成了多次观测的统计是让库存自动化管理真正可用的关键一步。我踩过的最大坑就是早期直接用单帧检测结果更新库存结果顾客走过货架时手部遮挡导致大量误报缺货门店店长直接不信任这套系统了。后来加了稳定性判断误报率降了一个数量级。做这套方案我的习惯是先把检测精度做到能接受的下限比如 mAP50 到 0.85再花同样甚至更多的时间在结果后处理和业务对账上。模型本身只是整个库存自动化管理链条里的一环后面那套检测-映射-对账-反馈的闭环才是真正决定项目成败的地方。希望帮到你。本文还有配套的精品资源点击获取