1. 先聊聊超市偷窃检测这件事为什么这么难
先从我自己的经历说起。早几年我做过一段零售场景的视频分析项目,甲方提的需求特别朴素:能不能用摄像头自动发现有人在偷东西。听起来就是个目标检测加分类的事,但真做起来才发现,这活儿跟"检测一个人"完全不是一回事。
偷窃行为检测难在哪?举个例子,一个人伸手从货架上拿一瓶水放回购物车,这是正常购买;同样一个动作,把水塞进自己的背包或者裤兜,这是偷窃。两个动作在视觉特征上高度相似,区别往往只在于后续动作的走向、手势的细节、目光的状态。单帧画面上,高速摄像头下你甚至看不出差别。
更要命的是,超市场景本身就极度复杂。不同品类货架的密集程度不一样,货架本身会产生大量遮挡,购物车、促销堆头、其他顾客会把目标挡得严严实实。光照也不是恒定的,靠窗区域白天和傍晚的色温差异很大,冷柜区还会有反光。人流高峰时段,三五个人同时挤在一排货架前,模型要把异常行为从正常的挑选、比较、犹豫中剥离出来,这是典型的低信噪比场景。
所以当时我们跟做数据集的朋友聊下来,得出的结论很一致:通用目标检测数据集解决不了这个问题。不是模型不行,是训练数据里没有"行为"层面的信息。COCO数据集能教模型认出货架、认出人、认出商品,但没法告诉模型"这些行为组合起来意味着偷窃风险"。
后来我们自己做过一批实验,用公开数据集训出来的YOLO模型,放在真实门店监控里,平均每天每路摄像头产生几十次误报,夜深人静保洁阿姨拖地都能触发报警。但真正的小偷动作,因为包裹在正常购物行为里,反而经常漏掉。
这就是为什么"超市店铺偷窃行为检测数据集"这种垂直数据集有价值。4000张高质量标注图,看着规模不大,但它的价值在于构建思路——每一个样本都在试图告诉模型:偷窃行为在像素层面的特征边界到底在哪里。拿这个数据集训练YOLO模型,做安防检测场景的落地验证,是当前性价比很高的一条技术路线。
下面我把这套数据集的构建思路、标注规范、模型训练和落地经验完整拆开来讲,想着重解决三个问题:数据集的类别和场景是怎么设计的;围绕YOLO训练时超参数和数据增强怎么配;真正部署后哪些坑会让你前功尽弃。
2. 4000张数据集的核心设计:从行为定义到标注规范
数据集的质量不是靠"数量大"堆出来的。4000张听起来不多,但如果每张图里的人都身处真实的超市环境、具备明确的行为语义,那它对模型的指导意义远超几万张随手抓拍的碎片数据。
2.1 类别体系:偷窃行为的粒度划分
做行为检测数据集,第一个绕不开的问题就是:怎么定义类别?
我在第一次做类似项目时犯过错——把"偷窃"当成一个单独的类别去标。结果模型学得一团糟,因为"偷窃"本身是过程性的,不是某个固定的视觉状态。一个人伸手、藏匿、张望,三个阶段画出来完全不一样。
后来和团队反复讨论,把行为拆成了更细的类别,这套思路在这类数据集里也被证明是更可行的:
- 拿取商品(grabbing):手伸向货架、抓取商品的动作,这是所有后续行为的前提;
- 环顾四周(looking around):头部大幅转动、视线频繁扫视周围,尤其在无同伴交流时,这是很强的风险信号;
- 藏匿行为(concealing):商品被塞入口袋、背包、衣物内,或者从包装中取出后放回空盒,这类动作在画面里表现为手部大幅度的、不自然的位移;
- 快速离开(leaving quickly):短时间内向出口方向移动,伴随频繁回头的特征。
每个类别还可以区分行为是否"确认"——比如手已经伸入包内、或者商品已经脱离货架区域,算法在后续决策时对已确认行为要给更高权重。
这套类别的粒度设计有一个非常重要的隐含逻辑:不能让模型学习"抽象概念",要让它学习"像素特征"。你告诉它一个样本是"偷窃",它不知道学什么;你告诉它"手部进入背包区域且商品消失",它就能从边缘、纹理、遮挡关系里提取到规律。
2.2 场景多样性:让模型见过足够多的"世界"
4000张图如果全是同一个机位、同一个时间段拍的,训练出来的模型换个门店就废。所以我特别看重数据集在场景维度上的覆盖设计,一般会考虑这几层:
- 区域类型:日用品区、零食区、生鲜区、酒水区、结账区。不同区域的货架高度、通道宽度、人流密度完全不同;
- 机位角度:俯视(顶装半球摄像头,最常见的便利店机位)、平视(货架端头)、侧视(通道长焦)。偷窃行为在不同角度下呈现的几何形态截然不同;
- 光线条件:日间、傍晚、夜间灯光、冷柜区冷白光、促销区暖光。模型如果只见过一种光照,部署后碰到冷暖切换极易丢帧;
- 人员特征:不同体型、着装、背包/手袋类型、同行人数,这些会影响手部动作被遮挡的概率。
拿我实际测试过的案例来说:同一套YOLO模型,在只含"正对货架"角度的数据集上训练,部署到"侧视通道"机位时,mAP直接掉了十几个点。后来补充了侧视角度的样本,误检率才明显下降。
所以"高质量标注"不能只解释为"框得准",更包含了"场景覆盖全"。你在看一个数据集的时候,我建议先看它的场景分布说明,再看标注精度。
2.3 标注规范:高质量从哪里来
标注质量是这类数据集最容易被低估的问题。4000张数据,如果边界框偏移超过5%,类别混淆率超过2%,训练出来的模型精度天花板就会很明显。
我见过不少刚开始做标注的团队,对边界框的定义习惯各异。有些人习惯紧贴目标轮廓,有些人习惯带一点边距。这在训练时看似无伤大雅,但模型学到的是"边框和目标的偏移规律",而不是"目标本身"。
可复现的标注规范一般包含以下约定:
- 有遮挡时,边界框必须覆盖目标的可见部分,并依据上下文补全不可见部分(比如人转身后身体被货架挡住一半,仍按完整人体标注);
- 低分辨率下难以判断类别的,宁可标为"ignore"区域,不要硬分类;
- 模糊帧、运动模糊超过阈值的图像,直接淘汰,不做"凑数"标注;
- 多目标重叠时,每个目标独立标注,不允许合并框;
- 行为类别争议较大的样本(比如"环顾四周"和"正常张望"),由审核人员投票决定。
标注工具的选型上,LabelImg、LabelStudio、CVAT我都用过。单机小批量LabelImg够用;要做团队协同和质量追溯,CVAT更方便,它能导出YOLO格式,还支持在线任务分配和冲突标记。
2.4 质量管控:两层审核加抽检机制
数据集的标注质量,不能靠"标注员认真一点"来保证,要靠流程。我们当时的做法是:
- 做首轮标注,标注员独立完成所有类别和边界框;
- 做交叉审核,另一名标注员逐张检查,发现问题退回修改;
- 做专家抽检,每组抽样10%到20%的图片,由熟悉业务场景的人最终判定类别边界。
这套流程走下来,4000张数据的周期大约三到四周。如果你是自己攒数据,可以简化成"标注加自检",但至少每个类别要抽查一遍,重点看容易混淆的"环顾四周"和"正常观察"边界。
还有一个细节容易被忽略:难样本的占比。全部标注的都是"明显偷窃",模型学不到"临界状态"。所以高质量数据集里应该有20%到30%的难样本——动作模糊、遮挡严重、行为介于正常和异常之间。这类样本才是模型泛化能力提升的关键。
3. 基于YOLO的行为检测实现:模型选型与训练配置
数据集有了,下一个问题是怎么训。这里我只讲YOLO这条路,因为这是目前安防场景落地最成熟、生态最完整的方案。
3.1 为什么选YOLO系列
YOLO系列在目标检测领域的优势不需要我多讲,单阶段、速度快、工程化成熟、社区资料丰富。但具体选哪个版本,我需要提醒一下。
YOLOv5和YOLOv8是目前生产环境使用最广泛的两个版本。v5胜在稳定、部署资料多,很多边缘设备上的优化方案都基于它;v8的anchor-free设计在重叠目标、小目标场景下有一定优势,且内置了更灵活的模型缩放策略。我自己在两套模型上做过对比,同一份数据集、同样的训练条件,v8在mAP@0.5:0.95上大概能高2到4个点,但推理速度会略慢。
如果你的目标是部署到Jetson或嵌入式设备,v5的成熟度更高;如果是纯服务器推理或者用GPU集群,v8表现更好。当然也可以试试更新的变体,比如v11、v12之类,但要注意配套工具链是否成熟。
3.2 数据准备与增强策略
拿到数据集后,第一步是把标注转成YOLO格式。YOLO格式要求每个目标的标注为:类别ID + 归一化的中心点x、y + 归一化的宽、宽。这里有个常见的坑:不同标注工具导出的坐标体系不一样,有的给的是左上角和右下角的像素坐标,需要做一次换算,千万别直接塞给模型。
换算公式很简单:
x_center = (x_min + x_max) / 2 / img_width y_center = (y_min + y_max) / 2 / img_height width = (x_max - x_min) / img_width height = (y_max - y_min) / img_height数据增强这块,我用的是YOLOv8自带的增强策略,但根据行为检测场景做了调整:
- Mosaic增强:默认开启,但训练后期我会降低mosaic的概率。原因是mosaic会把四个不同场景拼接在一起,目标尺寸被压缩,而偷窃行为数据集里有大量中近距离的手部动作细节,过度mosaic反而会干扰小目标学习;
- 旋转和透视增强:轻微开启,模拟不同摄像头安装角度。角度太大容易让"人"变成"躺倒的人",反而不真实;
- 亮度、对比度扰动:这个必须开,而且要开得狠一点。门店不同区域的光照差异大,亮度和对比度扰动可以缓解这一差异;
- 翻转增强:水平翻转对行为检测是友好的,偷窃动作左右手只是镜像关系,语义不变。
训练集的划分上,我建议按"场景"划分,而不是纯随机划分。保证同一个摄像头视角的多张图只出现在训练集或验证集里,避免验证集泄漏真实泛化性能。
3.3 训练参数配置
训练参数直接决定模型收敛质量和速度。基于4000张数据,我可以给一套跑起来比较稳的配置作为参考(图像尺寸、批次这类参数可以根据显存灵活调整):
# 以YOLOv8为例的推荐训练配置 model: yolov8s.pt data: supermarket.yaml epochs: 200 imgsz: 640 batch: 16 optimizer: SGD lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 warmup_momentum: 0.8 close_mosaic: 10几个关键点:
- 预训练权重确实有用。行为检测虽然和通用目标检测任务不同,但backbone学到了基础特征,迁移学习能明显缩短收敛周期,尤其是4000张这种中小规模数据集;
- SGD和AdamW的选择上,如果数据量小,SGD配线性学习率衰减更稳,AdamW收敛快但容易过拟合;
- epochs不要死守300,我建议用早停机制,patience设20,验证集mAP不再提升就停止。4000张数据200个epoch通常已经能稳定收敛;
- imgsz的选择,640是一个默认的较好平衡点。如果采集到的图像是1080p,缩到640会损失细节,但显存和速度都更可控。手部动作小目标占比高的时候,可以尝试864甚至960的输入尺寸,但训练时间会显著增加。
3.4 模型评估指标
这类数据集很少用单指标衡量好坏。我关注的指标有三个层次:
- mAP@0.5:主要衡量"有没有检测到目标",阈值较宽松,反映模型的基础检测能力;
- mAP@0.5:0.95:对边界框精度要求更高,能反映定位质量。偷窃行为检测对边界框的位置准确性要求比较高,因为后续往往还要接行为识别逻辑,框偏了会导致时序上的误判;
- 每个类别的Precision / Recall:这比整体mAP更重要。环顾四周这类行为的Recall往往偏低,因为它和正常行为的视觉差异太小;藏匿行为的Precision可能偏低,因为手部进入包内和正常掏钱包的动作容易混淆。
我强烈建议训练完先看各类别的混淆矩阵,而不是只盯着一个mAP数值。mAP高不代表行为检测做得好,如果只是"拿取商品"这一类精度高,另外三类都很差,那这个模型在真实场景里基本不能用。
4. 训练结果分析与问题排查:踩过的坑都在这
这一节是我最想写的,因为模型训练完,真正的挑战才刚刚开始。
4.1 常见的误报和漏报类型
第一轮训练完,我习惯把验证集里所有的错误预测抽出来,按类型归类。行为检测数据集最常见的错误有这几类:
- 把"整理货架"识别成"拿取商品":店员补货、理货的动作和偷窃行为在视觉上高度相似。解决思路是训练集中补充店员制服样本,并给模型提供更多"整理货架"的负样本;
- 把"正常放入购物车"识别成"藏匿":这本质上是因为手部移动轨迹和商品消失方向高度重合。这类误报很难彻底消除,只能通过提高置信度阈值来压;
- 漏检"环顾四周":头部小幅转动在画面里变化不显著。这类目标准确说更依赖于时序信息,单帧模型能力有限,我一贯的建议是检测模型只负责输出目标框和类别,行为判定交给后端的时序分析模块。
顺便岔开一句:仅靠YOLO单帧检测做行为判断,鲁棒性是有上限的。现在很多落地系统用"空间检测加时序分类"的两级架构,但无论如何,底层的检测质量决定了整个系统的上限。一个连"手部是否接触商品"都判断不准的检测模型,后面的时序模型再强也白搭。
4.2 小目标漏检问题
超市监控里,人的全身框很容易检测,但"手部+商品"这个组合是小目标,在1080p画面里可能只有几十个像素。YOLO对小目标检测天然不占优势,因为深层特征图分辨率低,小目标在特征提取过程中信息基本丢失。
解决思路有几个方向:
- 增加输入图像尺寸(imgsz从640调到960),小目标像素占比提升,检测率明显改善;
- 使用P2层特征,比如YOLOv8的P2模型变体,对小目标更友好,但代价是推理速度变慢;
- 对原始图像做切片推理,把大图切块后分别检测,效果显著但工程复杂度高。
我自己实测,在4000张数据集上,把imgsz从640调到960,手部相关类别的Recall大概提升了6到8个点,代价是训练时间接近翻倍。这个取舍在项目初期值得做,后续部署时再根据性能要求压回640。
4.3 阈值选择:不要拍脑袋定0.5
做安防检测,置信度阈值是一个需要认真调的超参数。默认0.25或者0.5往往不是最优解。
阈值越低,Recall越高,误报也越多;阈值越高,Precision越高,漏报也越多。在超市偷窃场景里,误报和漏报的代价不一样:误报多了,门店人员会对系统失去信任;漏报多了,系统形同虚设。所以阈值的设定,本质是业务决策在模型层面的体现。
我的做法是画出Precision-Recall曲线,然后跟业务方确认:你们能接受多少次误报,来换取一次偷窃行为的确认?如果接受度低,阈值就往高调;如果能接受偶尔的误报,捕获得越全越好。这个讨论必须在部署前完成,技术上没有"绝对正确"的阈值。
4.4 实测环节:换一个没见过的门店
训练时指标好看不算数,我每次都会拿一个完全没参与训练的真实门店视频做盲测。盲测的时候尤其关注:
- 不同摄像头品牌带来的色彩风格差异;
- 不同货架布局对遮挡关系的影响;
- 人群密度上升时,漏检率的变化。
这批4000张的数据集在盲测中的表现,比我预期好一点。训练集只覆盖了门店部分区域,但盲测门店的日用品区、零食区基本都能检出,唯一的明显短板是收银台附近的"快速离开"检测,因为收银区域的动线和数据集中常见的通道场景差异较大,误报偏高。
这类问题没有捷径,只能通过补充目标场景的数据来迭代。这也解释了为什么数据集不是一次性消耗品——它在持续迭代中体现最大价值。
5. 部署落地与持续推进:经验与实用建议
如果只是训练一个模型,这篇文章到这里可以结束了。但要真正落地到门店安防场景,下面这些经验可能更值钱。
5.1 摄像头视角与画质问题
门店摄像头的实际安装角度和数据集里的标注图像往往有差距。网络摄像头画面普遍有压缩伪影和噪声,尤其是暗光环境下,画面偏绿偏灰,检测效果会有明显下降。
我通常在推理前加一步图像预处理:先做去噪(用快速非局部均值或者简单的双边滤波),再做对比度增强(CLAHE),对暗部细节的提升非常明显。这一步在CPU上也不算贵,但对检测精度的提升立竿见影。
5.2 推理速度的优化建议
安防场景对实时性有明确要求,单路摄像头基本要跑到25帧每秒以上。为了在低算力设备上跑YOLO,我常用的手段有:
- 用TensorRT做模型加速,FP16精度通常能满足要求,检测精度损失几乎可以忽略;
- 把输入图像从1080p压缩到640分辨率,配合上面说的切片推理,只对关键区域做高清检测;
- 设置检测帧率策略,比如每3帧检测一次,中间两帧用跟踪算法关联,可以在保持行为连续性的前提下大幅降低算力消耗。
需要注意的是,跟踪算法(比如ByteTrack)在人群密集的超市场景会出现跟丢和ID切换,这个需要结合具体场景做调参,没有一劳永逸的配置。
5.3 数据集版本管理与持续迭代
我认为这类数据集的真正价值在于"生长"。第一次拿到4000张,训练出及格线以上的模型,只是起点。后续每次部署的真实场景数据,筛选出模型表现差的案例,回灌到训练集里,形成数据闭环,模型会越用越准。
这里有一个实操建议:每次模型迭代后,把新模型在历史负样本集上的表现记录下来。如果新版模型在修复某个场景问题的同时,导致另一个场景的指标下降,就要回退或者做针对性训练。这种回归测试的习惯,比单纯追求mAP增长更重要。
版本管理也很简单,给每个数据集版本打上标签,记录场景来源、标注规范版本、标注人员信息、训练效果评估。我见过太多团队上架了"最终版数据集",结果三个月后发现一个类别定义错了,整个返工。版本记录做好了,返工成本会低很多。
5.4 隐私合规与伦理边界
最后想多说一句技术之外的东西。做安防行为检测,不可避免涉及对公共场所人员行为的观察和记录。合规不是"提醒"一下就能带过的事。
从实践角度,有几个具体的操作建议:
- 推理服务输出的检测结果只保留行为事件片段,不长期存储完整监控录像;
- 最终面向门店管理人员的告警信息,做脱敏处理,不展示无关人员的清晰面部特征;
- 这个系统的定位应该是"辅助防损工具",而不是"自动指控工具"。高置信度的检测结果,也要由门店工作人员人工核实后处理。
窃行为检测这个方向,技术难度在于行为和场景的复杂性,而不在于模型结构本身。数据集的构建方法论、标注规范、训练调参和部署维护,每一环都会直接影响系统的实际效果。如果你正准备做类似的事情,别急着追求更大的数据量,先把手里的几千张图的质量做成闭环,用起来之后再滚动迭代,这才是最稳的路径。