线下零售做精细化运营,绕不开一个基础问题:顾客什么时候来、往哪儿走、在哪个货架前停留最久。这些行为数据过去要么靠店员手工登记,要么依赖云端视频分析,前者成本高且不准,后者要把店内视频实时上传,带宽压力大,顾客隐私也难以保障。边缘盒子方案把计算能力直接放到门店里,摄像头画面在本地完成检测、追踪和统计,只把结构化数据回传后台,是目前比较均衡的技术路线。

整体架构与硬件选型
一套典型的边缘客流方案由三部分组成:前端摄像头、边缘计算盒子和云端管理平台。摄像头通过RTSP把视频流推给盒子,盒子上的分析服务完成行人检测和追踪,输出客流计数、动线轨迹和区域驻留数据,最后通过HTTPS或MQTT把结果上报云端。整个过程原始视频不出门店,只上传几十字节级别的结构化消息。
硬件选型上需要综合考虑算力、功耗和成本。以常见三类方案做对比:入门级可以用树莓派加神经加速棒的组合,适合单路摄像头的小型便利店;中等规模推荐RK3588或Jetson Orin Nano这类自带NPU的盒子,单台可稳定跑四到八路视频流;大型商超如果路数超过十六路,就要考虑工控机加独立加速卡的方案。下表是一个大致的参考。
| 方案 | 算力 | 支持路数 | 功耗 | 适用场景 |
|---|---|---|---|---|
| 树莓派4B+加速棒 | 约4 TOPS | 1-2路 | 10W左右 | 便利店 |
| RK3588盒子 | 6 TOPS NPU | 4-8路 | 15W左右 | 标准门店 |
| Jetson Orin Nano | 40 TOPS | 8-16路 | 25W左右 | 旗舰店 |
| 工控机+加速卡 | 80 TOPS以上 | 16路以上 | 100W以上 | 商超 |
需要注意的是,摄像头安装角度对统计精度影响很大。建议俯视安装,镜头与地面夹角保持在60度以上,这样行人互相遮挡的情况会明显减少,检测准确率能提升五到十个百分点。红外双目摄像头还可以通过深度信息排除货架、推车等非人形目标的干扰,适合出入口计数场景。
检测模型与追踪算法的实现
行人检测主流选择是YOLO系列。在NPU设备上,YOLOv5s或YOLOv8n经过量化后推理速度都能满足实时要求。以RK3588为例,模型转成RKNN格式后单帧推理耗时在15毫秒以内,四路视频按每路抽帧到10fps计算,整体负载还有富余。检测输出的目标是边界框,要变成有意义的客流数据,还必须做跨帧关联,这就是多目标追踪。
追踪算法推荐ByteTrack,它的思路是先用高置信度检测结果匹配已有轨迹,再用低置信度结果做二次匹配,对遮挡后的目标恢复效果不错。每条轨迹会分配一个唯一ID,系统据此计算每个顾客的移动路径和在各个区域的停留时长。下面是一段核心处理逻辑的伪代码示意。
import cv2
import numpy as np
from bytetrack import BYTETracker
tracker = BYTETracker(track_thresh=0.5, match_thresh=0.8)
# 区域定义:货架区、收银区、促销区等,用多边形坐标表示
zones = {
"shelf_a": np.array([[100,100],[400,100],[400,500],[100,500]]),
"cashier": np.array([[500,100],[780,100],[780,500],[500,500]]),
}
def process_frame(frame):
boxes, scores = detector.infer(frame) # 行人检测
online_targets = tracker.update(boxes, scores)
for t in online_targets:
cx, cy = int(t.xyxy[0] + t.xyxy[2]) // 2, int(t.xyxy[1] + t.xyxy[3]) // 2
for name, poly in zones.items():
if cv2.pointPolygonTest(poly, (cx, cy), False) >= 0:
dwell_recorder.add(name, t.track_id) # 记录驻留
trajectory.add_point(t.track_id, cx, cy) # 记录轨迹点
出入口计数要处理穿越判定问题。常用做法是在画面中画一条虚拟线,维护每条轨迹上一帧和当前帧的位置,判断线段是否与虚拟线相交,同时用轨迹运动方向区分进店和出店。为了避免徘徊顾客被反复计数,建议设置冷却时间,同一条轨迹在短时间内的多次穿越只计一次。实际部署中这套逻辑的计数准确率能做到95%以上,误差主要来自高峰期的密集遮挡。
热力图生成与数据上报
热力图的本质是把所有轨迹点按空间位置累积叠加,再用颜色映射渲染。具体做法是维护一张与监控区域俯视图同尺寸的二维累积矩阵,每收到一个轨迹点就在对应格子加一,可以按停留时间加权,驻留久的格子权重更高。渲染时对矩阵做高斯模糊让色块过渡自然,再映射为蓝到红的色带。叠加到门店平面图上,运营人员一眼就能看出哪些区域是冷区。
import cv2
def render_heatmap(accumulate_matrix, shop_layout_img):
# 高斯模糊平滑处理,让热区过渡自然
blurred = cv2.GaussianBlur(accumulate_matrix, (0, 0), sigmaX=15)
# 归一化后映射到0-255
norm = cv2.normalize(blurred, None, 0, 255, cv2.NORM_MINMAX)
# 应用伪彩色映射
heatmap = cv2.applyColorMap(norm.astype(np.uint8), cv2.COLORMAP_JET)
# 与门店平面图按权重融合
overlay = cv2.addWeighted(shop_layout_img, 0.6, heatmap, 0.4, 0)
return overlay
数据上报策略要考虑弱网环境。门店网络抖动是常态,推荐本地SQLite做缓存队列,上报失败的消息写入本地,网络恢复后按时间戳顺序补传。热力图属于大块数据,建议在盒子上聚合生成,按小时或按营业日为粒度生成PNG和统计数据一起上传,而不是把原始轨迹点全部回传,这样单店每日上报数据量可以控制在几兆以内。设备管理方面,盒子要支持远程升级和心跳监控,云端长时间收不到心跳要能自动告警,避免某家店的数据悄悄断了好几天才发现。
常见问题与优化建议
部署中最常遇到的问题有三个。第一是多路并发下的性能瓶颈,解决方案是抽帧而非逐帧处理,客流分析对实时性要求不高,每路5到10帧足够,配合模型INT8量化可以成倍提升吞吐。第二是ID切换导致轨迹断裂,强光变化和镜面反射是主因,可以通过调整摄像头位置避开反光面,同时在追踪层开启轨迹平滑滤波。第三是隐私合规,虽然原始视频不出店,但轨迹数据本身也涉及个人信息,建议在本地对ID做匿名化映射,且只上报聚合统计结果而非个体轨迹明细。
从投入产出看,单台标准门店的边缘盒子加两到四个摄像头的改造成本并不高,却能持续产出进店率、动线分布、区域停留、员工排班参考等一系列运营指标。对于想做陈列优化和促销效果评估的零售企业来说,这套方案的数据颗粒度远超传统POS数据,值得作为数字化改造的第一步来落地。