基于 YOLO11 的超市店铺偷窃行为智能识别系统

举报
柠檬🍋 发表于 2026/10/22 22:16:43 2026/10/22
【摘要】 基于 YOLO11 的超市店铺偷窃行为智能识别系统一套面向便利店 / 商超 / 连锁零售场景的实时偷窃行为视觉识别平台,使用 YOLO11n + Streamlit 构建,支持单图、批量、视频与摄像头多源接入,自动标记可疑行为并输出风险分析。一、背景1.1 行业痛点零售门店因品类多、客流大、监控盲区分散,人工盯屏识别"商品藏匿、未结账离场"等行为效率低、漏检率高。传统视频监控只能事后回看取证...

基于 YOLO11 的超市店铺偷窃行为智能识别系统

一套面向便利店 / 商超 / 连锁零售场景的实时偷窃行为视觉识别平台,使用 YOLO11n + Streamlit 构建,支持单图、批量、视频与摄像头多源接入,自动标记可疑行为并输出风险分析。

一、背景

1.1 行业痛点

零售门店因品类多、客流大、监控盲区分散,人工盯屏识别"商品藏匿、未结账离场"等行为效率低、漏检率高。传统视频监控只能事后回看取证,无法做到实时告警。本项目用 计算机视觉 目标检测的方式,对收银区、货架区、通道等关键区域的正常购物与可疑盗窃两类行为进行实时识别与风险分级,给店员和店长一个"看得见"的智能复核工具。

数据集 采集自真实超市场景,规模 4000 张图像,覆盖货架区、收银区、通道等核心区域,包含光线变化、人员密度差异等真实情况,二分类标注(正常 / 盗窃),可有效缓解 模型 在真实零售环境中的过拟合问题。

视频演示与源码下载

https://www.bilibili.com/video/BV1HTph6EEtR/

在这里插入图片描述

包含: 📦完整项目源码 📦 预训练 模型权重

🗂️数据集

1.2 项目运行效果

Web 界面总览(深海蓝 + 警戒红的监控风视觉,侧栏聚合关键指标):

在这里插入图片描述

批量图片识别 + 行为分析图表:

在这里插入图片描述

1.3 项目介绍

创新点 / 亮点

维度 说明
告警类别可配 configs/project.yaml 中 alert_classes 决定哪些类别算"风险",无需改代码
风险分级 UI 命中可疑行为时顶部 banner 自动变红,正常时变绿,便于一线门店人员快速识别
多源接入 同一界面切换"单图 / 批量 / 视频 / 摄像头",覆盖事后复核 + 实时巡店
中文模型类别 训练阶段直接使用 ['正常','盗窃'] 中文标签,前端零翻译展示

系统功能概览

  • 单张图片识别:上传现场画面 → 输出标注图 + 目标明细 + 风险等级
  • 批量图片识别:多张图片或 ZIP 压缩包批量推理,输出风险分布图表
  • 视频识别:逐帧推理 + 时间线分布,导出标注视频与行为明细 CSV
  • 摄像头实时检测:浏览器调用本机摄像头,单帧推理 + 风险标注

技术栈

层级 技术选型
检测模型 YOLO11n(Ultralytics)
Web 框架 Streamlit
图像处理 OpenCV、Pillow
数据 / 图表 Pandas、Plotly、Streamlit 原生图表
视频编解码 imageio-ffmpeg
部署 本地 Python 3.9 + macOS / Linux,支持容器化部署

类别定义:nc=2,names=['正常', '盗窃']。


二、设计框架

系统架构:浏览器 ↔ Streamlit 前端 ↔ 推理 服务(YOLO11) ↔ 模型权重 model/best.pt,配置由 configs/project.yaml 驱动业务话术、告警类别和 UI 主题色。

┌────────────────────────────────────────────────────────────┐
│                    用户浏览器                              │
│  单张图片 │ 批量图片 │ 视频 │ 摄像头                       │
└──────────────────────┬─────────────────────────────────────┘
                       │ HTTP / WebSocket
┌──────────────────────▼─────────────────────────────────────┐
│              Streamlit App (app/streamlit_app.py)          │
│  · 模式路由(st.radio)                                    │
│  · 上传 / 预览 / 分析图表                                  │
│  · 风险等级 banner + 类别分布                              │
└──────────────────────┬─────────────────────────────────────┘
                       │ model.predict()
┌──────────────────────▼─────────────────────────────────────┐
│                 YOLO11n 推理引擎                           │
│  Backbone (C2f + SPPF) → Neck (FPN + PAN) → Decoupled Head │
│  + DFL(分布式回归) → NMS                                 │
└──────────────────────┬─────────────────────────────────────┘
                       │ result.boxes (cls, conf, xyxy)
┌──────────────────────▼─────────────────────────────────────┐
│  后处理:apply_class_display + is_alert_class              │
│  → 渲染标注图 + DataFrame 明细 + 风险分级                  │
└────────────────────────────────────────────────────────────┘

YOLO11 网络结构(与 v8 同源,更深更轻):

  • Backbone:连续 Conv + C2f 块下采样 5 次,末端 SPPF 聚合多尺度特征
  • Neck:FPN(自顶向下)+ PAN(自底向上)双向融合
  • Head:解耦头(分类 / 回归分离),回归侧使用 DFL 输出分布而非单值,小目标定位更稳
  • 损失:BCE(分类)+ CIoU + DFL(回归)

检测流程:图像/帧 → 缩放至 imgsz=640 → 推理 → 置信度过滤(conf=0.35)→ NMS(iou=0.7)→ 类别映射 → 风险打标 → 前端渲染。


三、代码结构(核心 50 行 + 解析)

项目结构(精简版):

超市偷窃行为检测/
├── app/streamlit_app.py        # Streamlit Web 入口(含 4 种接入模式)
├── configs/project.yaml        # 业务配置(标题、告警类别、UI 主题)
├── model/best.pt               # 训练好的 YOLO11n 权重
├── scripts/                    # 训练 / 评测 / 导出脚本
├── data/dataset/               # 数据集(train / valid / test)
└── 超市店铺偷窃行为检测train_CH_yolo11n/train/   # 训练产物(指标、曲线)

核心 50 行(app/streamlit_app.py 关键片段,已删减无关 UI):

from pathlib import Path
import pandas as pd
import streamlit as st
from ultralytics import YOLO

PROJECT_ROOT = Path(__file__).resolve().parent.parent
MODEL_PATH = PROJECT_ROOT / "model" / "best.pt"
ALERT_CLASSES = {"盗窃"}            # 来源:project.yaml -> app.alert_classes
DEFAULT_CONF = 0.35                # 来源:project.yaml -> inference.conf

@st.cache_resource(show_spinner=False)
def load_model(model_path: str) -> YOLO:
    return YOLO(model_path)        # 一次加载、全局复用,避免每次推理重载权重

def infer_image_path(model: YOLO, image_path: Path, conf: float):
    result = model.predict(str(image_path), conf=conf, verbose=False)[0]
    annotated = result.plot()      # 自带画框 + 类别 + 置信度
    rows = []
    if result.boxes is not None:
        for box in result.boxes:
            cls_id = int(box.cls.item())
            rows.append({
                "class_id": cls_id,
                "class_name": result.names[cls_id],
                "confidence": round(float(box.conf.item()), 4),
                "x1": float(box.xyxy[0][0]), "y1": float(box.xyxy[0][1]),
                "x2": float(box.xyxy[0][2]), "y2": float(box.xyxy[0][3]),
            })
    return annotated[:, :, ::-1], pd.DataFrame(rows)   # BGR -> RGB

def is_alert_class(name: str) -> bool:
    return name in ALERT_CLASSES

# ---------------- Streamlit 主流程 ----------------
st.set_page_config(page_title="超市店铺偷窃行为智能识别系统", layout="wide")
model = load_model(str(MODEL_PATH))
conf = st.sidebar.slider("置信度阈值", 0.05, 0.95, DEFAULT_CONF, 0.05)
mode = st.radio("接入源", ["单张图片", "批量图片", "视频", "摄像头"], horizontal=True)

if mode == "单张图片":
    uploaded = st.file_uploader("上传现场图片", type=["jpg", "png", "jpeg"])
    if uploaded is not None:
        img_bytes = uploaded.getvalue()
        annotated, df = infer_image_path(model, Path(uploaded.name), conf)
        col1, col2 = st.columns(2)
        col1.image(img_bytes, caption="现场画面", width="stretch")
        col2.image(annotated, caption="识别结果", width="stretch")
        alert_n = int(df["class_name"].map(is_alert_class).sum()) if not df.empty else 0
        st.metric("可疑行为数量", alert_n, delta="需复核" if alert_n else None)
        st.dataframe(df, width="stretch")

逐段解析

  1. @st.cache_resource 装饰 load_model:Streamlit 每次交互都会重跑脚本,缓存可避免反复 YOLO(...) 加载,单图响应从秒级降到毫秒级。
  2. model.predict(conf=conf, verbose=False) 一行完成"预处理 + 推理 + NMS",返回 Results 对象,.plot() 直接得带框图,省去手画 OpenCV 矩形的工作量。
  3. result.boxes 遍历每个目标,把 cls / conf / xyxy 抽成 DataFrame,前端用 st.dataframe 展示明细,也便于后续导出 CSV / 入库。
  4. is_alert_class 把"业务告警"与"模型类别"解耦:告警清单在 configs/project.yaml 里维护,新增风险类型时不用改代码。
  5. st.radio + if/elif 路由四种接入模式,复用同一个 model 实例,单图 / 批量 / 视频 / 摄像头共享同一份推理逻辑。

四、训练效果

训练采用 YOLO11n 预训练权重 微调 ,epochs=200, imgsz=640, batch=16, patience=50。最终关键指标:

指标 数值
Precision (B) 0.731
Recall (B) 0.852
mAP@0.5 0.824
mAP@0.5:0.95 0.630

训练结果总览

说明:当前 mAP@0.5 ≈ 0.82,整体可用但仍在迭代中。下一阶段会通过以下方式继续提升:

  • 扩充"盗窃"难样本:藏入袖口、推车遮挡、低光环境等长尾场景
  • 引入跟踪(ByteTrack)抑制单帧抖动,把"可疑帧"聚合成"可疑事件"
  • 升级到 YOLO11s/m 提升小目标识别精度,再用 INT8 量化平衡推理速度

由于本阶段 mAP 尚未达到放出 PR / 混淆矩阵的内部阈值(≥ 0.85),暂仅展示训练 loss / 指标随 epoch 变化的总览图。从曲线看,box / cls / dfl loss 平稳下降,P/R/mAP 在中后段趋于平台期,未出现过拟合震荡。


五、项目总结

做对了什么

  • 业务配置全部抽到 project.yaml,告警类别、置信度、UI 主题、品牌话术可一键替换,一套代码切换不同零售场景。
  • 类别名直接用中文训练,前端零翻译、风险 banner 与告警颜色(深海蓝 + 警戒红)符合监控审美。
  • 推理函数返回 (annotated_image, DataFrame),单图 / 批量 / 视频 / 摄像头四个入口复用同一份核心,新增模式只改 UI。

还能怎么做

  • 加入轻量目标跟踪(ByteTrack / BoT-SORT),把帧级检测升级为事件级告警,减少单帧误报对店员的打扰。
  • 接入门店摄像头 RTSP 流,结合时间窗口聚合,对"长时间停留 + 商品消失"做组合规则。
  • 模型蒸馏 / 量化:在边缘盒子(如 Jetson Orin Nano)上跑 INT8 YOLO11n,把响应时延压到 50ms 以内。

一句话总结

YOLO11n + Streamlit 给了零售业一套"开箱即用、配置驱动"的偷窃行为复核工具:训练数据替换 + project.yaml 改两行,就能复用到便利店、商超、连锁店等多形态门店场景。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。