基于 YOLO11 的超市货架空位智能巡检系统关键词YOLO11 · 智能零售 · 货架巡检 · 缺货预警 · Streamlit模型最佳 mAP0.5 93.8%单图推理 50 ms自动锁定画面里所有空货位。一、背景1.1 行业痛点线下零售门店的运营效率很大程度上取决于补货是否及时。一个常见但容易被低估的场景货架上爆款被一抢而空 →空货位停留时间越长营业额损失越大价签还在、商品没了 → 顾客以为售完不卖了扭头走人大店动辄几千个 SKU人工巡店一圈半小时起步信息回传到补货已经是 20 分钟以后。传统方案靠巡店员 钉钉拍照 微信群报修问题很明显依赖人力、响应滞后、夜班漏检高。本项目用 YOLO11n 把这件事变成一次上传图片 → 自动框出空位 → 推送补货工单的工程化流程。视频演示与源码下载https://www.bilibili.com/video/BV1Fgph67EQy/包含完整项目源码预训练模型权重️数据集1.2 项目运行效果Web 界面总览巡检台单张巡店图检测——画面里所有空货位一次性框出1.3 项目介绍项目定位面向超市/便利店/仓储零售的智能货架巡检 Demo识别画面中所有货架空位区域输出可追溯的检测明细辅助补货与陈列复核。核心功能模块说明单图检测上传一张巡店图自动框出全部空货位批量图片多张/ZIP 一次性上传自动统计每张图空位数 全店总缺位数视频流检测适配巡检机器人/监控录像逐帧分析输出时间轴趋势摄像头实时直接调用门店摄像头做实时缺货预警类别定义本数据集是单类别检测任务nc1目标只有一个——“空”empty_shelf / 货架空位。在 UI 中通过class_display_names把英文标签映射成中文货架空位更贴近门店运营人员的用语。技术栈层选型检测模型Ultralytics YOLO11n轻量化骨干推理引擎PyTorch Ultralytics前端/交互Streamlit响应式 UI CSS 主题化视频处理OpenCV ImageIO-FFmpeg图表分析Streamlitbar_chart/line_chart pandas配置驱动PyYAMLconfigs/project.yaml项目创新点单类高召回是核心 KPI——空货位检测最怕漏漏一个就少一次补货机会项目主调 IoU0.7 conf0.25 的组合先保召回再用 NMS 收敛配置驱动的行业话术——同一份代码骨架在火灾/PCB/口罩等场景都能复用只换project.yaml和数据集即可批量页 巡店报告——批量上传后自动出每图目标数和类别分布双图等价于门店补货排序表店长可以直接对照补货。二、设计框架2.1 系统总体架构┌──────────────────────────────────────────────────────────────┐ │ 浏览器Streamlit 巡检台 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ 单图上传 │ │ 批量上传 │ │ 视频/摄像头 │ │ │ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │ └──────────┼─────────────────┼─────────────────────┼────────────┘ │ │ │ ┌──────────▼─────────────────▼─────────────────────▼────────────┐ │ Streamlit 服务端streamlit_app.py │ │ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │ │ │ load_yaml/UI │ │ infer_image_path │ │ batch 聚合分析 │ │ │ └─────────────────┘ └──────────────────┘ └───────┬───────┘ │ └──────────────────────────────────────────────────────┼─────────┘ │ ┌──────────────────────────────────────────────────────▼─────────┐ │ YOLO11 推理引擎ultralytics PyTorch │ │ YOLO(model/best.pt).predict(img, conf0.25, iou0.7) │ │ → boxes(xyxy/cls/conf) result.plot()(标注 BGR ndarray) │ └────────────────────────────────────────────────────────────────┘2.2 YOLO11 网络结构Input (640×640×3 巡店图) │ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Backbone │ → │ Neck │ → │ Head │ │ C3k2 SPPF │ │ FPN PAN │ │ Decoupled │ │ C2PSA 注意力│ │ (多尺度融合) │ │ DFL │ └──────────────┘ └──────────────┘ └──────┬───────┘ │ ▼ [类别概率 边框坐标 置信度]YOLO11n 相比 v8n 的关键变化C3k2 模块替换 C2f参数更少、感受野更灵活C2PSA 注意力提升对货架形状不规则空白区的特征显著性解耦头 DFL让边框回归走分布化预测对货架空位这种边界模糊目标更稳。2.3 检测流程原始巡店图手机拍/巡检机器人 ↓ Letterbox 缩放 640×640保持长宽比 ↓ Backbone 抽取 P3/P4/P5 三层特征 ↓ Neck FPNPAN 多尺度融合 ↓ Head 输出 [bbox cls_prob] ↓ conf ≥ 0.25 过滤 NMS(iou0.7) ↓ result.plot() 渲染标注图 ↓ Streamlit 双列展示 表格 bar_chart 聚合三、代码结构核心 50 行 解析项目目录约定超市货架空位检测/ ├── app/streamlit_app.py # Web 入口 ├── configs/project.yaml # 行业话术 UI 推理参数 ├── model/best.pt # 训练好的 YOLO11n 权重 ├── scripts/ # 训练/评测/导出脚本 ├── 超市空货架检测train_CH_yolo11n/ # 训练产物 └── 超市空货架检测数据集/ # 1500 张标注图 data.yaml核心 50 行模型加载 单图推理 Streamlit 单图分支frompathlibimportPathimportstreamlitasst,pandasaspd,yamlfromultralyticsimportYOLO PROJECT_ROOTPath(__file__).resolve().parent.parent CFGyaml.safe_load((PROJECT_ROOT/configs/project.yaml).open(encodingutf-8))APP_METACFG.get(app,{})CLASS_DISPLAYAPP_META.get(class_display_names)or{}# empty_shelf → 货架空位MODEL_PATHPROJECT_ROOT/model/best.ptDEFAULT_CONFfloat(CFG.get(inference,{}).get(conf,0.25))st.cache_resource(show_spinnerFalse)defload_model(model_path:str)-YOLO:returnYOLO(model_path)# 仅首次加载6 MB 量级命中缓存后零延迟definfer_image_path(model:YOLO,image_path:Path,conf:float):单图推理返回 (RGB 标注图, 检测明细 DataFrame)resultmodel.predict(str(image_path),confconf,verboseFalse)[0]annotatedresult.plot()# BGR ndarray已画好框 类别 置信度rows[]ifresult.boxesisnotNone:forboxinresult.boxes:cls_idint(box.cls.item())raw_nameresult.names[cls_id]# 训练原标签displayCLASS_DISPLAY.get(raw_name,raw_name)# → 中文货架空位x1,y1,x2,y2[float(v)forvinbox.xyxy[0].tolist()]rows.append({class_id:cls_id,class_name:raw_name,display:display,confidence:round(float(box.conf.item()),4),x1:round(x1,1),y1:round(y1,1),x2:round(x2,1),y2:round(y2,1),})returnannotated[:,:,::-1],pd.DataFrame(rows)# BGR → RGB# ───────── Streamlit 单图分支 ─────────confst.slider(置信度阈值,0.01,0.99,DEFAULT_CONF,0.01)modelload_model(str(MODEL_PATH))uploadedst.file_uploader(上传巡店图片,type[jpg,png,bmp,webp])ifuploadedisnotNone:importtempfilewithtempfile.NamedTemporaryFile(deleteFalse,suffix.jpg)asf:f.write(uploaded.getvalue());tmpPath(f.name)annotated_img,dfinfer_image_path(model,tmp,conf)col1,col2st.columns(2)col1.image(uploaded.getvalue(),caption原图,widthstretch)col2.image(annotated_img,caption检测结果,widthstretch)st.metric(画面空货位数,len(df))st.dataframe(df,widthstretch)逐段解析class_display_names把英文映射成中文—— 巡检台直接给店长看所以训练标签是empty_shelfUI 上是货架空位运营无感切换。st.cache_resource缓存模型—— Streamlit 每次交互都会重跑脚本没缓存会反复加载 6 MB 权重体验掉到 5s 以上。model.predict(...)一次返回结构化结果——boxes.xyxy/boxes.cls/boxes.conf全部 tensor遍历转 DataFrame下游图表/CSV/批量分析复用同一份 schema。result.plot()自带 BGR 标注图—— 不需要手动cv2.rectangle颜色和置信度文字 Ultralytics 已经画好。单类项目的关键指标是画面空货位数—— 用st.metric(len(df))突出展示店长一眼就能看出这张图缺几个位。四、训练效果4.1 训练总览数据集1500 张真实超市场景图按 train/val/test 划分约 1400 / 97 / 50单类目标。训练参数yolo11n.pt→ 200 epoch、imgsz640、batch16。训练 loss / P / R / mAP 曲线最终指标results.csv最后一行指标数值含义Precision §0.928检出框 92.8% 是真的空货位误报低Recall ®0.887真实空货位 88.7% 被找回漏检低mAP0.50.938IoU0.5 下综合表现工业可用mAP0.5:0.950.719严格 IoU 区间仍稳健4.2 PR 曲线单类任务的 PR 曲线整体压在右上角且非常平滑说明模型在大部分置信度阈值下都能保持高精度和高召回。4.3 归一化混淆矩阵单类项目的混淆矩阵主要看目标 ↔ 背景两个方向。本项目对角线非常显著说明模型在区分空货位和背景纹理包括相似的浅色板材上表现稳定。4.4 数据分布与验证集预测数据集类别中心 / 框尺寸 / 中心点分布验证集随机一批的预测可视化可以观察到验证集图中一旦出现价签下方裸露的层板或端架边缘空位模型都能用紧凑的 bbox 框住且置信度普遍 0.7。五、项目总结做对了什么场景聚焦—— 不贪多只解决画面里所有空货位在哪这一件事单类 高召回做到 mAP0.5 93.8%真实数据—— 1500 张图来自真实超市场景覆盖标准层板/端架、店内灯光/自然光/阴影、多种拍摄视角模型泛化能力扎实轻量好部署—— 6 MB 的 YOLO11n 权重单图推理 50 ms巡检机器人/边缘盒/笔电都能跑工程化闭环—— 单图 → 批量 → 视频 → 摄像头四种入口齐备批量页直接产出巡店报告形态。还能怎么做接入巡检机器人—— 把当前 Demo 包成 HTTP 接口让巡检机器人定时上传 触发推理再把结果回写到补货工单系统多店多 SKU 关联—— 配合 OCR 识别价签 SKU做哪个 SKU 在哪个店哪个货架空了的联动小目标增强—— 端架最上层和最下层的小空位远距离拍摄召回还有提升空间可以加 Mosaic Mixup 强化训练导出 ONNX/TensorRT—— 进一步压到 10 ms 单图支持 1 路视频实时25 fps跑下来不卡。一句话总结用 200 行 Streamlit 一个 6 MB 的 YOLO11n 权重把超市人工巡店、电话补货的旧流程改造成上传即看图、看图即补货的工程化巡检台mAP0.5 93.8% 已经能直接挂到零售运营 SOP 上跑。