如果从软件工程的角度看,一个智能客流系统其实可以拆成几个相互独立的模块:
vbnet
Sensor
Capture
3D Processing
AI Inference
Tracking
Event Engine
Storage
Analytics
最大的变化是:过去这些能力经常集中在一个"计数设备"里,现在越来越适合按照Pipeline拆开。
1. 先定义数据对象
不要一开始就写Counting函数。
先定义系统中的对象。
Detection
markdown
Detection {
bbox
confidence
depth
class_id
}
Track
arduino
Track {
track_id
position
velocity
confidence
age
state
}
Event
css
Event {
event_id
device_id
timestamp
event_type
direction
zone_id
}
Statistic
bash
Statistic {
timestamp
entry
exit
occupancy
dwell_time
}
这样做的好处是:
vbnet
Detection ≠ Track
Track ≠ Event
Event ≠ Statistic
后续替换AI模型时,不需要修改整个系统。
2. Capture层
Capture模块只负责获取传感器数据:
sql
Frame
Depth
Timestamp
如果使用双目:
css
Left Frame
Right Frame
如果使用ToF:
Depth Frame
再统一进入:
FramePacket
例如:
markdown
FramePacket {
timestamp
rgb
depth
sequence
}
注意Sequence。
设备长时间运行时,单纯依赖系统时间不够。
可以通过:
diff
timestamp
+
sequence
共同判断是否存在丢帧。
3. 3D Processing层
双目视觉需要:
Calibration
→ Rectification
→ Stereo Matching
→ Disparity
→ Depth
基本公式:
ini
Z = fB/d
其中:
ini
Z = depth
f = focal length
B = baseline
d = disparity
最终得到:
javascript
Depth Map
如果采用ToF,则直接得到距离信息。
不同3D传感器在光照、安装高度、遮挡和测量范围方面存在不同特性,因此不能简单认为某一种技术适用于所有场景。
4. AI Inference层
AI模块最好不要直接修改业务数据。
输入:
FramePacket
输出:
css
Detection[]
例如:
yaml
[
{
class: person,
confidence: 0.96,
bbox: [...],
depth: 2.31
}
]
业务层不需要知道模型到底是:
objectivec
YOLO
RT-DETR
Custom CNN
Transformer
这样模型可以独立升级。
5. Tracking层
Tracking接受:
css
Detection[]
输出:
css
Track[]
常见实现可以使用:
css
Kalman Filter
+
Hungarian Algorithm
Kalman Filter负责预测:
scss
x(k|k-1)
Hungarian Algorithm负责:
Track ↔ Detection
如果加入Appearance Feature,则可以形成:
diff
Motion
+
IoU
+
Appearance
+
Depth
综合匹配。
3D客流研究中也存在使用深度信息和Kalman Tracking进行人员计数的技术路线。
6. Event Engine才是真正的Counting层
不要把:
scss
len(Detection)
当作客流。
Counting应该监听Track。
例如:
ini
Track ID = 101
Position:
P1 → P2 → P3 → P4
系统设置虚拟线:
scss
──────────────
Detection Line
──────────────
当轨迹发生:
css
Side A
↓
Line
↓
Side B
触发:
ENTRY
反向则:
vbnet
EXIT
最终:
vbnet
Track
↓
Crossing Event
↓
Count
这就是检测和统计之间最关键的一层。
7. U-turn必须单独处理
现实中会出现:
进入
↓
停留
↓
返回
如果算法只判断:
ini
cross line = IN
可能把一次短暂穿越错误地算作完整客流。
因此可以增加状态机:
scss
OUTSIDE
↓
APPROACH
↓
INSIDE
↓
CONFIRMED
如果:
scss
OUTSIDE → APPROACH → OUTSIDE
则不产生完整Entry。
只有满足一定空间位移、速度和停留条件后:
scss
OUTSIDE → INSIDE
才生成:
vbnet
ENTRY EVENT
8. Dwell Time来自Track生命周期
停留时间其实不需要额外的传感器。
只需要保存:
track_start
track_end
计算:
ini
dwell_time = track_end - track_start
如果进一步定义区域:
css
Zone A
Zone B
Zone C
则可以计算:
css
Zone A Dwell
Zone B Dwell
Zone C Dwell
最终形成:
Trajectory
9. Re-ID应该作为Tracking的辅助,而不是替代
一个常见误区是:
有了Re-ID就不用Tracking。
实际上两者作用不同。
Tracking解决短时间连续关联。
Re-ID解决目标重新出现后的关联。
所以更合理的Pipeline:
r
Detection
↓
Motion Tracking
↓
Lost
↓
Re-ID Matching
↓
Recover Track
这样可以降低ID Switch。
公开研究已经出现将3D空间特征与Re-ID特征结合进行人员关联的方案。
10. Edge设备需要性能监控
AI系统部署到边缘设备以后,需要实时监控:
Inference FPS
Inference Latency
CPU
NPU/GPU
Memory
Temperature
Dropped Frames
Network
Storage
例如:
ini
FPS = 15
Latency = 62ms
CPU = 38%
NPU = 71%
RAM = 54%
这些数据比单纯看"设备在线"更有意义。
因为:
Online ≠ Healthy
设备虽然在线,如果AI Pipeline持续丢帧,最终客流数据一样会受到影响。
11. 本地数据缓存
客流系统不能假设网络永远在线。
可以设计:
sql
Event
↓
Local Queue
↓
Upload
网络正常:
vbnet
Event → Cloud
网络异常:
sql
Event → SQLite / KV / Local DB
网络恢复:
sql
Local DB
↓
Batch Upload
↓
ACK
↓
Delete
这样可以避免网络波动导致数据缺失。
12. 云端接收的最好是结构化事件
例如:
json
{
"device": "store001",
"timestamp": 1788508200,
"event": "ENTRY",
"zone": "door01",
"confidence": 0.97
}
平台再通过Stream Processing进行:
vbnet
Event
↓
Validation
↓
Aggregation
↓
Storage
↓
Analytics
最终得到:
css
5min Traffic
Hourly Traffic
Daily Traffic
Occupancy
Dwell Time
Zone Flow
这比直接把所有视频交给云端处理更容易扩展。
边缘AI方案目前已经广泛采用"本地推理、上传结构化结果"的思路,用于降低延迟、带宽需求以及原始视频处理压力。
13. 一个完整Pipeline可以写成
css
Sensor
↓
FramePacket
↓
3D Processing
↓
Detection[]
↓
Tracking
↓
Track[]
↓
Event Engine
↓
Event[]
↓
Local Queue
↓
MQTT / HTTP
↓
Cloud
↓
Aggregation
↓
Analytics
其中:
vbnet
Sensor负责感知
3D负责空间
AI负责识别
Tracking负责连续性
Event Engine负责计数
Cloud负责汇总
Analytics负责计算
这套结构最大的价值不是把系统做得更复杂,而是让每一个模块拥有清晰边界。
以后更换传感器,不需要重写数据平台。
更换AI模型,不需要修改统计逻辑。
增加新的区域分析,也不需要修改底层Detection。
这才是3D视觉+AI客流系统真正值得关注的技术方向。
未来的核心问题也会从:
"摄像头能数多少人?"
逐渐转变为:
"系统能否稳定地把物理空间中的人员运动,
转换成连续、可靠、可计算的数据事件?"
而这个问题,本质上已经从一个视觉算法问题,变成了一个完整的感知计算系统问题。