
1. 先搞清楚“客流分析”到底在输出什么1.1 一个摄像头画面不能直接当报表用做过线下数据项目的人都听过一句话摄像头到处都是数据却很难拿。原始摄像头画面是一串不断变化的 RGB 像素它本身不会告诉你今天几点进店了多少人、顾客在哪个货架前停留最久、周末和平时的人流峰值差多少。真正有价值的是把这些像素转成经营指标这个转译过程就是 AI 客流分析系统存在的意义。很多客户一开始会问“你们是不是做人脸识别的”这个问题背后其实有个常见误解。传统安防人脸识别关注的是“这个人是谁”而客流分析关注的是“有多少人、从哪来、往哪去、停留多久”。两者虽然都会用到视觉算法但技术链路完全不同一个要提取人脸特征去比对数据库一个要检测整个人体并持续跟踪生成的是轨迹和事件而不是身份。所以这篇文章要聊的就是从摄像头原始画面到报表上一个个数字的完整链路人体检测、多目标跟踪、轨迹生成、事件规则触发、最后落库成指标。每一层都有坑而且每一层出错都会像接力赛一样传导到下一层。搞懂这条链路你才能判断一个客流系统的数据到底可不可信也才知道调试时应该从哪里下手。1.2 业务指标拆解进店数、停留时长、回头客与游逛路径我习惯先跟客户把指标定义敲死再谈算法。因为同一个词在不同人嘴里意思可能完全不一样。比如“客流”到底指的是门口路过的人、进门的人、还是收银台结账的人这三个人数完全不同。线下零售常用指标大概可以分成四类指标分类典型例子算法层面的对应关系流量类进店人数、过店人数、客流峰值检测跨线判定时长类平均停留时长、区域驻留时间轨迹起止时间戳深度类游逛路径、楼层/区域热点、回头率轨迹区域匹配与重识别转化类试穿率、提袋率配合POS系统轨迹事件与交易数据关联以最常见的“进店人数”为例完整定义其实是人体检测框的中心点从店门口外部区域进入内部区域并且至少停留超过几秒才计为一个有效进店。如果只是人站在门口探头看一眼立刻离开很多系统会把它算成过店而非进店。这个定义直接影响门口磁头线的画法和事件规则的触发条件。一旦指标定义清晰系统模块也就清晰了。前端摄像头负责采集视频流中间算法服务负责检测、跟踪、事件判断后端业务系统负责存储和报表展示。没有指标定义就谈技术选型很容易出现“算法做得很炫但客户要的数字出不来”的尴尬局面。1.3 从指标反推系统模块从指标反推下来你会得到一个比较固定的技术骨架视频接入层兼容 RTSP、ONVIF 等协议负责拉流、解码、抽帧。检测模块对每一帧画面做人形目标检测输出目标框和置信度。跟踪模块跨帧关联同一个人的检测框分配并维护 ID。轨迹模块把同一 ID 的目标中心点按时间排序生成轨迹序列。事件模块基于轨迹和虚拟区域做空间逻辑判断产生进出、停留、聚集等事件。数据服务层对事件做聚合计算输出业务报表或实时看板。有意思的是很多项目做到一半才发现瓶颈不在算法而在视频接入。摄像头时间戳不同步、画面掉帧、码率波动都会让跟踪模块拿到不连续的帧ID 频繁切换最终报表数字乱跳。所以我会把“视频接入质量”也当作算法链路的一部分来对待而不是交给运维去处理就完事。2. 人体检测所有链条的第一层未必是你以为的那个人脸识别2.1 检测器在网络层到底要输出什么人体检测的核心任务是回答两个问题画面里有没有人人在哪用一个矩形框把它框出来。现在主流方案基本都是基于深度学习的单阶段检测器例如 YOLO 系列及其变体。网络输出的不是一张图而是若干个张量每个候选框的坐标、宽高、置信度以及类别概率。实际项目里我会把检测环节理解成一个“上游过滤器”。它不需要做得特别完美但不能出现系统性偏差。什么叫系统性偏差比如摄像头装在 3 米高的地方俯拍检测器在训练集里见过的大部分是人正面或侧面的全身/半身图俯视角度下人的头肩比例完全不同检测器就会频繁漏检。这个问题不是调参能解决的必须换训练数据或者做专门的适配。很多人混淆“检测”和“识别”其实检测只是“有没有、在哪里”识别才是“是谁”。客流分析的第一层只需要检测不需要识别身份。这意味着我们在技术选型上可以选择更轻量的模型牺牲少量精度换取更高吞吐因为后续跟踪模块本来就会对多帧结果做融合单帧偶尔漏一次不一定致命。2.2 模型选型是在工控机上跑还是在摄像头里跑落地架构不同模型选型策略完全不同。我把项目分成两类一类是摄像头端智能方案前端摄像头直接跑检测模型只上传结构化结果目标框、置信度不上传原始视频。优势是带宽压力小、隐私成本低劣势是前端算力有限模型参数量被卡得很死而且后续算法升级要逐台设备刷固件。适合点位多、带宽小、对实时性要求未必极致的场景。另一类是中心端智能方案摄像头只负责采集视频流汇聚到服务器或者边缘盒子统一处理。优势是可以用更大模型算法升级只动服务器也方便做跨摄像头的轨迹拼接。劣势是带宽和存储成本高一个 1080p 摄像头按 4Mbps 码率算一天大约 40GB 左右几十个点位就得上 NAS 或云存储。在这两个方案之间我通常会建议折中摄像头端做轻量检测做人形框选中心端用跟踪和事件模块做语义分析。这样第一层过滤分散了压力第二层集中处理保障精度。如果项目预算有限直接在中心端放一块带 GPU 或 NPU 的边缘盒子也完全可行。2.3 检测环节的误检与漏检对后续的伤害检测错误不会只停留在检测层它会污染后面的所有层。误检把柱子、海报人影、拖把当成人的框如果被跟踪模块接受就会形成一条几十秒甚至几分钟的“幽灵轨迹”进而触发虚假的进店事件或驻留事件。漏检的伤害同样不小一个顾客在画面边缘没被检测到系统就不会有他的轨迹他会直接从统计数据里消失。所以上线前我会做一件很土但很有效的事准备一段 30 分钟到 1 小时的真实营业录像用系统跑一遍导出所有检测框人工快速扫一遍统计误检率和漏检率。正常俯拍角度下一个好的检测器误检率应该低于 1%漏检率低于 2%——注意这里说的“好”不只是模型好还包括安装角度、焦距调整和光线环境都配合得好。如果误检率偏高优先检查两件事一是置信度阈值是否调得太低二是画面里是否有大量与人体颜色纹理相近的静态背景。如果是漏检偏高则优先检查检测目标尺度——画面里人的目标框如果小于模型训练时的最小目标尺寸怎么调阈值都白搭。3. 多目标跟踪从一串框变成一条稳定轨迹才是真正的分水岭3.1 卡尔曼预测与匈牙利匹配怎样协作检测器只能告诉你“这一帧有哪些人”它不知道上一帧的张三还是这一帧的张三。多目标跟踪MOT要做的事就是给每个检测框分配一个固定的 ID并且持续维持这个 ID。目前工业界最常用的框架仍然是 DeepSORT 的改进版本核心是卡尔曼滤波加匈牙利匹配。卡尔曼滤波做的是“预测”和“更新”的循环。跟踪器根据目标上一帧的位置、速度预测这一帧它大概在哪然后再用检测器这一帧的结果去修正预测值。匈牙利匹配解决的是“分配问题”我有 5 个预测位置检测器给了 6 个框到底哪个框对应哪个预测算法通过计算 IoU 重叠度和特征相似度找出一组总代价最小的匹配方案。这里有一个很关键的点匹配分为不同优先级。第一优先是用外观特征匹配也就是把目标框裁剪出来用一个 ReID行人重识别网络提取特征向量和该 ID 的历史特征做余弦相似度比对。第二优先才是用 IoU 位置匹配。为什么这样设计因为视频帧率如果不够目标位移可能很大前后两帧的框根本不重叠单靠位置就丢了。当然这也会带来一个隐患——如果这个 ReID 特征提取器区分能力不够两个穿同样颜色衣服的人挤在一起时ID 就会互相交换。3.2 ID Switch 为什么是客流系统的隐形杀手做客流分析最怕的一个问题不是漏检而是 ID Switch也就是一个原来稳定为 A 的 ID 突然变成了 B。ID Switch 最大的危害在于它会把轨迹切碎。客户想看“一个顾客从入口到收银台再到出口”的完整路径结果系统显示的是两条不完整的轨迹顾客在中间凭空消失又出现报表里的平均游逛深度就会失真。高密度场景里 ID Switch 尤其严重。想象一下三个人并肩走进门口检测器给出整齐的三个框跟踪模块可能把左边的人和中间的人在新一帧搞混。这种情况在货架区域很常见因为货架会遮挡人体局部人从货架后走出来时检测框的中心点突然跳了很远跟踪模块匹配不上只好发一个新 ID。要压制 ID Switch有三个思路按推荐程度排序提高帧率、装高位俯拍、加轨迹后处理。帧率提到 15fps 以上能明显减少位移跳变高位俯拍能大幅降低人与人之间的互相遮挡概率轨迹后处理则在事件模块做修正比如一条轨迹中断后如果周边同时出现另一条轨迹且时间衔接极短就做合并。这里提醒各位单纯靠调大 IoU 阈值往往适得其反会把本该独立的两个人强行并成一条轨迹尤其是两个人在门口并排行走时。3.3 让追踪更稳的三个实用补强手段除了标准 DeepSORT我习惯在工程里加三个补强手段。第一个是图像坐标到地面坐标的映射。摄像头是透视成像的画面下方的人看起来大上方的人看起来小直接用像素距离判断“人有没有移动”会产生误差。提前做一次单应性变换标定把图像坐标映射到地面平面坐标再用地面坐标做跟踪的位置预测和速度统计轨迹会稳定很多。标定只需要在安装时放四个角点参照物离线算一次矩阵之后固定机位就不用再动。第二个是低速目标的逗留抑制。一个人站在货架前看商品时检测框会在小范围内抖动可能导致卡尔曼滤波误判他在“移动”。我会在轨迹平滑层对短时间内的位移量做低通滤波位移低于一个阈值就认为是驻留状态防止出现“人明明站着不动轨迹却在原地画圈”的问题否则区域停留时间会被拉长。第三个是 ROI 屏蔽。画面里有些区域根本不可能出现正常顾客比如收银台内侧、仓库门口、员工通道。我会在跟踪之前先把这些区域的检测结果过滤掉既减少误检来源也避免员工被计入客流量。这些区域往往不是静止不变的收银台的人会走来走去所以不能用简单屏蔽线最好用多边形 ROI 结合业务时段来动态启用。4. 轨迹事件化把坐标流翻译成业务语言4.1 事件规则引擎跨线、驻留、方向与热点区域检测和跟踪做完你手里其实只是一堆“带时间戳的坐标序列”。要让业务系统能用必须把它们转成事件。事件的定义就是空间与时间的组合逻辑下面是我在项目里经常用到的一组规则模板跨线事件轨迹点从虚拟线的 A 侧穿越到 B 侧用于进出店统计。区域驻留事件轨迹中心点持续落在某个多边形区域超过设定时长触发驻留事件。方向事件轨迹的起点和终点对应区域编号推出“从大门到收银台”这类路径语义。热点事件某个区域内同时存在的轨迹数量超过阈值触发拥挤预警。逆向导流事件在单向通道中轨迹方向与设定方向相反用于商场消防疏散分析等。规则引擎的写法不能写死在代码里因为客户对“入口”“出口”的定义会改货架位置会调整。我会做成一个 JSON 配置把虚拟区域坐标、事件类型、触发阈值全部抽出去让运营人员也能查看和修改。下面是一段简化的示例{ zones: [ { zone_id: store_entrance, type: polygon, points: [[120, 300], [220, 280], [230, 420], [130, 440]], events: [ { type: cross_in, from_zone: outside, to_zone: inside }, { type: cross_out, from_zone: inside, to_zone: outside } ] } ], dwell_threshold_seconds: 5, enter_mimimum_frames: 6 }4.2 轨迹后处理平滑、插值、状态机事件规则跑在原始轨迹上很容易误触发所以必须先做轨迹后处理我归纳为三步。第一步是平滑。卡尔曼滤波输出的轨迹依然会有小毛刺直接用中心点去做跨线判断可能因为一帧的抖动产生一次虚假跨线。我会用一个简单的滑动窗口均值窗口大小取 5 帧像素级摆动就会被抹平。第二步是补帧。检测偶尔会漏一两帧如果在漏帧期间轨迹正好穿越了门口线跨线事件就丢了。我常用的做法是当某个 ID 的轨迹缺失不超过 3 帧时用前后两个有效点的位置做线性插值把中间帧补上然后再送进事件判断。注意这里的插值时间不能太长超过 3 帧以后目标可能已经拐弯补出来的位置会不真实。第三步是状态机。这是最关键的一步。一个目标不应该既能触发“进入”又能触发“离开”所以每个 ID 需要维护一个业务状态比如“outside - entering - inside - leaving - outside”。状态机只允许合法的状态迁移这样既能消除重复事件也方便统计在店人数。我的经验是状态机里至少要有“进店等待确认”和“离店等待确认”两个中间态因为目标在门口犹豫时轨迹会在线上来回穿如果没有中间态延迟确认一个正常顾客会触发三四次进出事件。4.3 姿态类“异常事件”我为什么不建议一上来就做很多客户拿到客流系统之后会问能不能顺便识别跌倒、打架、偷窃、儿童攀爬这些“高级事件”我的回答通常是可以作为二期扩展但不要在第一期做。原因是姿态类事件与客流轨迹类事件的技术链路差异很大。客流追踪只需要目标框级别的信息即使检测器没有把人的四肢位置提取出来也不影响轨迹统计。而“跌倒”至少需要骨骼点检测要准确区分一个大人是蹲下、弯腰还是跌倒姿态估计器必须输出高于 90 的置信度但这个数值在真实弱光、遮挡环境下很难达到。打架和聚集更是如此“聚集”尚可以用轨迹密度近似“打架”则涉及人与人、人与物之间的交互判断误报率往往高到运营团队彻底忽略这个功能最终沦为一个没人看的告警源。我的建议是第一期的异常能力只做两件低成本高可靠的事——区域闯入和超时逗留。这两个本质上还是轨迹事件不需要姿态模型。等轨迹系统稳定运行一两个月积累了足够的场景数据再考虑用专门的小模型去识别特定动作效果和可维护性都会好得多。5. 实地调优决定系统好坏的往往不是算法而是安装与现场5.1 摄像头角度与高度对检测和跟踪的影响做算法的人最容易忽略安装但项目成败往往就挂在安装上。我见过太多算法在实验室跑得不错、一上现场就废的案例原因几乎都在摄像头。高度和角度是最先要确认的。理想安装高度我建议在 2.8 米到 3.5 米之间向下倾斜约 30 到 45 度。这个角度下人的头肩特征仍然清晰检测器不容易把两个人重叠成一个框同时人也还在画面里保留足够大的目标尺寸。如果装到 6 米以上俯拍虽然遮挡问题减少但人的目标会变得很小检测器精度下降跟踪也受影响。如果只装在 2.2 米那么高很多店铺门头只有这么高画面大量是人的头顶检测器可能把每个进店的人只识别出半个框甚至漏检。还有焦距和画幅。门口客流分析镜头视场角宁小勿大。画幅太宽人的目标太小画幅太窄门口两侧来的人还没进入画面就已经离开。我通常会先把画面调好确保人员行走的通道区域占画面的 60% 以上再锁死焦距和位置并且用胶带或螺丝固定住防止保洁阿姨不小心把摄像头推歪。安装角度一变后面整条链路的标定和事件区域全部作废这是最常见的事故。5.2 玻璃门、反光、逆光这些经典翻车现场有三个现场问题几乎无法靠调参完全解决必须在安装时一并考虑。第一个是玻璃门和玻璃幕墙。透明玻璃会让检测器同时看到室内的人和室外的倒影跟踪模块可能会把倒影和真人当成同一个目标或两个目标。我的做法是尽量让摄像头斜对玻璃面而不是正对同时在检测阶段屏蔽掉玻璃区域下半部分的倒影区域。另一个办法是用偏振镜片但会增加成本而且对低照度画面不友好。第二个是反光地面。地砖或浅色瓷砖会把人的倒影照出来倒影的检测框和真实人脸的检测框位置高度相似跟踪时会出现上下两个框互相纠缠的情况。这个问题的处理思路是通过 ROI 把地平线以下区域整体屏蔽。注意屏蔽不能把脚部轨迹也删掉否则跨线判断时会丢位置最好是只在“检测”环节屏蔽倒影保留“轨迹”环节的地面映射坐标。第三个是逆光。门店门口正对西晒时人脸和人体是严重欠曝的检测器几乎全灭。可以打开摄像头的宽动态WDR功能或者把曝光时间调短宁可画面整体偏暗也要保证人物轮廓与背景能区分开。WDR 也不是万能的强逆光到一定程度唯一的办法是在门口内侧增加补光让人的主体受光影。5.3 排查链路从报表数字异常倒推算法故障系统上线后一定会出现“报表数字看着不对劲”的时候。别急着怀疑算法先建立一个倒推排查顺序我一般按四步走。第一步看视频接入层。先确认画面帧率稳定、码率正常、关键帧没有间隔丢失。最简单的办法是拿工具直接拉流看几秒钟画面用肉眼判断实时画面是否卡顿和跳帧。如果画面本身就一卡一卡的下面所有步骤都不用做了先解决推流和拉流的问题。第二步看检测层。找到一段业务平稳的录屏视频用可视化工具把检测框画出来人工看一眼检测框是不是准确框住了人。如果大量框在墙和柱子上阈值要上调如果人移动速度稍快框就追不上需要确认是不是检测模型输入分辨率太低。第三步看跟踪层。在可视化界面打开轨迹回放看每个 ID 的轨迹是否平滑、有没有突然跳跃和 ID 互换。轨迹跳跃常见的原因是检测漏帧导致跟踪模块断链需要去查模型在特定视角下的漏检率。第四步看事件规则。用门口区域状态机日志看一个目标从 outside 到 inside 的状态转换是否符合业务预期。很多“少算了”的问题都出在状态机缺中间态或者跨线判断的帧数阈值设得太宽目标在门口停两三秒才判定进入导致那两三秒内的其他事件混乱。整个排查过程最好做成一个脚本化的工具链一键导出某时段所有 ID 的轨迹回放叠加区域框和事件标记这样出了问题能快速定位到具体环节不用靠猜。6. 技术链路之外匿名化与数据闭环6.1 为什么不能把“识别谁”带进客流分析系统客流分析系统在整个落地过程中有一个设计原则值得反复强调系统应该主动丢弃身份信息构建匿名化处理机制。我们讨论的是“客流分析”不是“身份识别”。有人脸图像的数据与没有人脸图像的数据在整个链路里的技术复杂度和安全等级完全不是一个量级。人脸检测模型本身会输出人脸框这时就要在系统架构里加一道“即用即弃”的处理检测到人脸框后不送人脸识别模型直接把人脸区域做模糊化或者丢弃原始像素只保留人体框和轨迹坐标。如果客户提出“想识别回头客”我会建议用顾客追踪编号Visit ID来做同一个人多次进入门店系统通过 ReID 特征对比计算出“疑似同一个 Visit”然后把这个匹配关系映射到一个随机编号上而不是真实身份。这样做的好处不只在安全层面。丢掉身份信息后数据结构变成纯时空序列处理逻辑更简单内存占用更低而且业务流程里不涉及任何身份关联运营人员用起来也更没有心理负担。6.2 数据处理架构人在环回放、离线与实时并行客流系统一旦铺到几十上百个点位数据的生命周期管理就成了工程质量分水岭。我推荐一个三通道架构。实时通道负责在线统计当前人数和实时热区。它读的是最新几秒的轨迹事件只做聚合不做整理服务的是大屏和现场预警。离线通道负责每天定时重算一次历史报表。它读取当天存下来的轨迹明细用更完整的逻辑后处理包括跨摄像头轨迹拼接、异常轨迹修正、补帧重新生成指标服务的是日报和周报。为什么要重算因为实时链路为了低延迟会允许一些临时性错误到离线复用完整上下文时很多 ID Switch 和丢帧问题是可以被修正的。回放通道则是给人看的。运营人员如果想知道“刚才 14:00 到 14:30 门口到底发生了啥”可以调出这段时间的轨迹回放视频叠加业务事件标记逐帧查看。这个通道最好做成独立的可视化页面不要把原始视频直接暴露在通用后台避免普通账号看到不需要看的信息。我自己的习惯是设置三套不同保存策略原始视频留存 72 小时轨迹明细留存 30 天聚合指标留存 180 天以上。这个策略不是一成不变的但大部分线下场景的运营需求都覆盖得到。痕迹越短后续纠纷越少。6.3 部署形态与算力成本最后聊聊算力。一套 30 个点位的客流系统中心端如果全部用 CPU 推流做检测每路 1080p 25fps 大概要占 4 到 6 个 CPU 核30 路下来是一个不小的压力。所以我通常推荐用边缘盒子分流每台边缘盒子接 4 到 8 路视频盒子只跑检测和跟踪的最轻量版本中心服务器只做事件汇总和报表。GPU 不是万能的客流分析场景有个被低估的瓶颈不是算力而是解码能力。视频流 H.264/H.265 解码极其消耗资源纯 GPU 检测虽然快但解码还是得靠 CPU所以预算有限时不要盲目追求大 GPU 服务器买一台解码能力强、内存带宽高的机器效果往往更好。成本还有一个隐藏项算法服务的运维。模型灰度更新、视频流故障检测、点位移位后的配置重下发这些都是日常开销。一个看起来简单的客流系统长期稳定的关键不在第一个月跑出了多漂亮的数字而在半年后还能不能按照当初的指标口径持续输出。我见过太多项目上线当天惊艳三个月后因为摄像头被风吹歪、模型没有定期验证而变成废数据的案例所以调试文档和点位台账一定要从一开始就建立起来。我在实际项目里最深的一个体会是客流分析系统本质上是“约束下的检测跟踪系统”它的技术上限取决于模型但技术下限取决于现场。决定项目成败的往往是那些写在算法论文里不会提的细节摄像头装多高、门口那根线画在哪、夏天强光直射时 WDR 开多大、员工通道的 ROI 有没有及时更新。把这些细节做扎实了链路里的每一环都能稳定输出报表上的数字才有意义。