1. 问题抽象

客流统计不是“人数识别”,而是一个时序事件检测问题


输入:视频帧 / 深度数据流
输出:穿越边界的计数事件

核心拆成三步:


Detection(检测) → Tracking(跟踪) → Event(计数)


2. 最小可运行系统(Minimal Pipeline)


for frame in video_stream:
detections = detect(frame) # 目标检测
tracks = tracker.update(detections) # 多目标跟踪

for t in tracks:
if cross_line(t):
if not recently_counted(t.id):
count += 1


3. Detection(目标检测)

3.1 常见实现

  • YOLOv5 / YOLOv8
  • MobileNet-SSD(低算力设备)

3.2 关键指标

指标含义
Precision误检率
Recall漏检率

3.3 实际问题

  • 漏检(FN) → 少计
  • 误检(FP) → 多计
  • 遮挡 → 检测失败

3.4 推理性能

设备延迟
CPU80–150 ms
Jetson GPU10–30 ms

建议:


FPS ≥ 15 才能保证轨迹连续性


4. Tracking(多目标跟踪)

如果没有Tracking:


同一个人每一帧都会被当成新目标 → 计数失效


4.1 简化实现(中心点匹配)


def match(prev, curr):
for p in prev:
for c in curr:
if distance(p, c) < threshold:
assign_same_id(p, c)

复杂度:


O(n²)


4.2 工程方案

SORT
  • Kalman Filter(预测)
  • Hungarian Algorithm(匹配)

状态:


[x, y, vx, vy]


DeepSORT

增加:

  • 外观特征(embedding)
  • 余弦距离匹配

4.3 关键指标

指标目标
ID Switch< 3%
MOTA> 0.9

5. Event(计数逻辑)

5.1 线穿越法(最常用)


def cross_line(track):
return track.prev_y < line_y and track.curr_y >= line_y


5.2 状态机(避免抖动)


IDLE → APPROACH → CROSS → DONE


5.3 抖动问题

问题:


人在边界附近来回移动 → 多次触发

解决:

  • 设置缓冲区(buffer zone)
  • 单次触发锁定

6. 去重机制(关键)

6.1 时间窗口限制


if now - last_count_time[id] > 2s:
allow_count()


6.2 空间约束

  • 限制轨迹必须完整穿越区域

7. ToF方案(与RGB差异)

7.1 数据结构


(x, y, z) 深度点


7.2 检测方式

  • 深度阈值分割
  • 连通域分析

复杂度:


O(n)


7.3 优势

  • 不依赖光照
  • 可区分前后目标(Z轴)

8. 精度来源拆解

误差模型:


Total Error = FN + FP + ID Switch


8.1 实测范围

场景精度
单入口95%–98%
中密度90%–95%
高密度85%–92%

9. 性能瓶颈

9.1 跟踪匹配


Hungarian:O(n³)

目标数增加 → 延迟上升


9.2 遮挡

  • 多人重叠 → ID丢失 → 重复计数

9.3 帧率不足


FPS < 10 → 轨迹断裂


10. 常见优化手段

10.1 ROI限制

减少无关区域计算


10.2 多帧融合

降低单帧误检


10.3 Track过滤

删除短生命周期轨迹:


if track.age < 3:
ignore()


10.4 动态阈值

根据密度调整:

  • 匹配距离
  • 检测阈值

11. 一句话总结


客流统计 = 稳定ID跟踪 + 正确事件触发


12. 可扩展方向

  • 多摄像头融合(跨视角Re-ID)
  • 热力图(Heatmap生成)
  • 停留时间统计(轨迹分析)
  • ToF + RGB融合

13. 参考实现结构(工程化)


project/
├── detector/
├── tracker/
├── event/
├── config/
└── main.py

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐