多目标跟踪算法详解
一、问题定义
输入: 视频帧序列 F₁, F₂, …, F_T
输出: 每个物体的轨迹 T = {id, bbox₁, bbox₂, …, bbox_ₜ}
评价指标
| 指标 | 说明 |
|---|---|
| MOTA ↑ | Multiple Object Tracking Accuracy: 1 - (FP+FN+IDSW)/GT |
| MOTP ↑ | 跟踪精度 (bbox重合度) |
| IDF1 ↑ | ID F1 Score,身份保持能力 |
| IDs ↓ | Identity Switches (身份跳变次数) |
| MT/ML | 跟踪轨迹占比 |
| HOTA ⭐ | Higher Order Tracking Accuracy (综合指标) |
| FPS | 推理速度 |
二、跟踪范式
| 范式 | 说明 | 代表 |
|---|---|---|
| TBD/Tracking-by-Detection ⭐ | 先检测再关联 | DeepSORT, ByteTrack |
| JDE/Joint Detection & Embedding | 联合检测+ReID | FairMOT, JDE |
| Transformer联合 | 端到端跟踪 | TransTrack, TrackFormer |
| Motion-only | 纯运动模型 | KCF, MOSSE |
Tracking-by-Detection 流程
帧1: 检测器 → bboxes → ReID特征提取 → Kalman预测 → 数据关联(匈牙利) → 轨迹更新
帧t: 检测器 → bboxes → ReID特征提取 → Kalman预测 → 匹配 → 轨迹更新
│
┌────────┴────────┐
匹配成功(轨迹更新) 未匹配(新轨迹/丢失)
三、经典跟踪器 ⭐
3.1 SORT (2016)
Simple Online and Realtime Tracking
核心: Kalman滤波 + 匈牙利匹配(仅用运动信息)
| 组件 | 说明 |
|---|---|
| 检测 | 任意检测器 (Faster R-CNN) |
| 状态模型 | Kalman: 7维状态 (u,v,s,r, u̇,v̇,ṡ) |
| 关联度量 | IoU距离 |
| 匹配算法 | 匈牙利算法 |
| 轨迹管理 | 未命中阈值(Amax=1),新轨确认 |
| 速度 | >260 FPS (依赖检测器) |
局限: 只有运动模型 → 遮挡后易ID Switch
3.2 DeepSORT (2017) ⭐
SORT + 外观ReID特征
关联度量: d(i,j) = λ·d_motion(i,j) + (1-λ)·d_appearance(i,j)
(马氏距离) (余弦距离)
| 改进 | 说明 |
|---|---|
| 外观特征 | CNN提取512维特征向量 |
| 级联匹配 | 优先匹配最近见过(保障短期可靠) |
| 特征库 | 每一轨迹保存最近100帧的特征 |
| 门控 | 马氏距离阈值剔除不合理匹配 |
# DeepSORT核心
tracker = DeepSORT(model_path='ckpt.t7')
for frame in video:
bboxes = detector(frame) # 检测
features = feature_extractor(frame, bboxes) # ReID特征
tracks = tracker.update(bboxes, features) # 关联更新
3.3 ByteTrack (2022) ⭐
核心: 利用低分检测框(SORT/DeepSORT丢弃了它们)
高分检测框(>τ_high) → 第一次关联 → 匹配轨迹
↓
未匹配轨迹 + 低分检测框(τ_low~τ_high) → 第二次关联
↓
未匹配检测框 → 新轨迹
丢失轨迹 → 保留30帧(给遮挡恢复机会)
优点: 简单有效,不依赖ReID特征也能达到SOTA
3.4 FairMOT (2021)
联合框架: 同时检测和ReID特征
Backbone → 同分辨率特征图
├── 检测分支: 中心热图 + 尺寸回归 + 偏移量
└── ReID分支: 128维嵌入特征 → 用于数据关联
四、单目标跟踪 (VOT/SOT)
| 方法 | 特点 | 代表 |
|---|---|---|
| 相关滤波 | 快速,频域 | KCF, MOSSE, DCF |
| Siamese网络 | 精确,模板匹配 | SiamFC, SiamRPN, SiamMask |
| Transformer | 强鲁棒性 | TransT, OSTrack |
| 分割引导 | 像素级跟踪 | SiamMask, ATOM |
# OpenCV经典跟踪器
trackers = {
'BOOSTING': cv2.TrackerBoosting_create(),
'MIL': cv2.TrackerMIL_create(),
'KCF': cv2.TrackerKCF_create(),
'TLD': cv2.TrackerTLD_create(),
'MEDIANFLOW': cv2.TrackerMedianFlow_create(),
'MOSSE': cv2.TrackerMOSSE_create(),
'CSRT': cv2.TrackerCSRT_create() # 精度最高(OpenCV)
}
五、评估与数据集
| 数据集 | 任务 | 说明 |
|---|---|---|
| MOT17/MOT20 | 多目标跟踪 | 行人,2D公开数据集标准 |
| DanceTrack | 密集跟踪 | 外观相似场景挑战 |
| SportsMOT | 体育视频 | 高运动+大尺度变化 |
| KITTI | 自动驾驶 | 车+行人 |
| BDD100K | 自动驾驶 | 大规模跟踪 |
| TAO | 开放世界跟踪 | 400+类别 |
| LaSOT | 单目标 | 高精度标注,1400视频 |
📺 推荐视频
| 内容 | 链接/搜索 |
|---|---|
| MOT综述讲解 | YouTube/B站搜索 |
| DeepSORT源码解析 | B站搜 “DeepSORT” |
| ByteTrack论文精讲 | YouTube |
| 单目标跟踪经典工作(SiamFC) | B站搜 “SiamFC” |
📚 论文必读
| 论文 | 年份 |
|---|---|
| SORT (Simple Online and Realtime Tracking) | 2016 |
| DeepSORT | 2017 |
| FairMOT | 2021 |
| ByteTrack | 2022 |
| StrongSORT (DeepSORT改进) | 2022 |
| MOTR (Transformer端到端) | 2022 |
🔗 视频链接
- MOT Benchmark: https://motchallenge.net/
附录:深层补充
一、DeepSORT 深度解读
1.1 卡尔曼滤波的预测-更新循环
DeepSORT 使用卡尔曼滤波作为运动模型,维护 8 维状态空间:
x = [ u , v , s , r , u ˙ , v ˙ , s ˙ , r ˙ ] T x = [u, v, s, r, \dot{u}, \dot{v}, \dot{s}, \dot{r}]^T x=[u,v,s,r,u˙,v˙,s˙,r˙]T
其中 ( u , v ) (u, v) (u,v) 是 bbox 中心坐标, s s s 是面积, r r r 是宽高比,带点的表示对应速度。
预测(Prediction):
状态预测: x k ′ = F x k − 1 x'_k = F x_{k-1} xk′=Fxk−1
协方差预测: P k ′ = F P k − 1 F T + Q P'_k = F P_{k-1} F^T + Q Pk′=FPk−1FT+Q
其中 F F F 是状态转移矩阵(常速运动模型), Q Q Q 是过程噪声协方差。
更新(Update):
卡尔曼增益: K k = P k ′ H T ( H P k ′ H T + R ) − 1 K_k = P'_k H^T (H P'_k H^T + R)^{-1} Kk=Pk′HT(HPk′HT+R)−1
状态更新: x k = x k ′ + K k ( z k − H x k ′ ) x_k = x'_k + K_k (z_k - H x'_k) xk=xk′+Kk(zk−Hxk′)
协方差更新: P k = ( I − K k H ) P k ′ P_k = (I - K_k H) P'_k Pk=(I−KkH)Pk′
其中 z k z_k zk 是当前检测值(4 维: u , v , s , r u, v, s, r u,v,s,r), H H H 是观测矩阵, R R R 是观测噪声协方差。
关键直觉:
- K k K_k Kk 反映了对预测和观测的信任程度
- 当观测噪声 R R R 大时(检测不可靠), K k → 0 K_k \to 0 Kk→0,更相信预测
- 当过程噪声 Q Q Q 大时(运动不可预测), K k → 1 K_k \to 1 Kk→1,更相信观测
1.2 级联匹配
DeepSORT 的级联匹配(Cascade Matching)优先匹配最近有交互的轨迹:
输入: 轨迹集合 T = {T_1, T_2, ..., T_M},检测集 D = {D_1, D_2, ..., D_N}
1. 对每条轨迹 T_i 计算 Kalman 预测位置
2. 按丢失帧数将轨迹分组(丢失少的优先):T_0, T_1, ..., T_max_age
3. for age in 0 to max_age: # 从最近见过的开始
4. 对 T_age 中的轨迹,计算与 D 的关联代价矩阵 C
5. 匈牙利算法求解最优匹配
6. 更新匹配对,从未匹配检测集移除已匹配元素
7. end for
为什么级联匹配重要?
- 短期遮挡的轨迹更适合当前的检测
- 长期丢失的轨迹的位置预测已不可靠,优先匹配短期轨迹可以减少 ID switch
1.3 外观特征的余弦距离 + 马氏距离融合
DeepSORT 的关联代价是两种距离的加权和:
d ( i , j ) = λ ⋅ d ( 1 ) ( i , j ) + ( 1 − λ ) ⋅ d ( 2 ) ( i , j ) d(i, j) = \lambda \cdot d^{(1)}(i, j) + (1-\lambda) \cdot d^{(2)}(i, j) d(i,j)=λ⋅d(1)(i,j)+(1−λ)⋅d(2)(i,j)
马氏距离 d ( 1 ) d^{(1)} d(1)(运动匹配度):
d ( 1 ) ( i , j ) = ( d j − y i ) T S i − 1 ( d j − y i ) d^{(1)}(i, j) = (d_j - y_i)^T S_i^{-1} (d_j - y_i) d(1)(i,j)=(dj−yi)TSi−1(dj−yi)
其中 y i y_i yi 是轨迹 i i i 的 Kalman 预测观测, S i S_i Si 是协方差矩阵。马氏距离衡量检测与 Kalman 预测的统计差异。
余弦距离 d ( 2 ) d^{(2)} d(2)(外观匹配度):
d ( 2 ) ( i , j ) = min { 1 − cos ( r j , r k ( i ) ) ∣ r k ( i ) ∈ R i } d^{(2)}(i, j) = \min\{1 - \cos(r_j, r_k^{(i)}) \mid r_k^{(i)} \in \mathcal{R}_i\} d(2)(i,j)=min{1−cos(rj,rk(i))∣rk(i)∈Ri}
其中 r j r_j rj 是检测 j j j 的 ReID 特征, R i \mathcal{R}_i Ri 是轨迹 i i i 保存的最近 100 帧 ReID 特征集合。余弦距离衡量外观相似度。
联合门控:
d ( i , j ) ≤ threshold ∧ d ( 1 ) ( i , j ) ≤ t ( 1 ) d(i, j) \leq \text{threshold} \land d^{(1)}(i, j) \leq t^{(1)} d(i,j)≤threshold∧d(1)(i,j)≤t(1)
只有同时满足运动距离和外观距离门控的匹配才被允许,大幅减少误匹配。
二、ByteTrack 的深入原理
2.1 BYTE 数据关联策略
ByteTrack 的核心发现:低分检测框并非都是假阳性,很多低分框其实是遮挡或运动模糊下的真物体。
BYTE 两轮关联:
输入: 检测框 D = {(d_1, s_1), ..., (d_N, s_N)},其中 s 为检测分数
轨迹集 T = {T_1, ..., T_M}
第一轮(高分匹配):
D_high = {d_i | s_i > τ_high} # 高分检测框 (如 τ_high=0.6)
C = cost_matrix(T, D_high) # IoU 距离
matches = hungarian(C) # 匈牙利匹配
更新 T_matched, D_high_unmatched
第二轮(低分匹配):
D_low = {d_i | τ_low < s_i ≤ τ_high} # 低分检测框 (如 τ_low=0.1)
T_unmatched = T - T_matched # 第一轮未匹配的轨迹
C = cost_matrix(T_unmatched, D_low) # 同样是 IoU 距离
matches_low = hungarian(C) # 再次匈牙利匹配
未匹配的高分 D_high → 初始化为新轨迹
未匹配的轨迹 → 保留 30 帧(超时阈值)
2.2 为什么低分框也能提升跟踪效果
- 遮挡场景: 当物体部分被遮挡时,检测器输出的置信度会下降但仍然是正样本。SORT/DeepSORT 只看高分框,直接把遮挡中的物体丢弃了
- 运动模糊: 快速运动中的物体因运动模糊,检测分数会降低但仍然可检测
- 小物体: 远处小物体的特征较弱,检测分数天然偏低
定性分析:
- ByteTrack 的 MOTA 提升 ~2-3 个百分点(相比 SORT),主要来自 FP 和 FN 的同时降低
- 在密集人群和运动场景中提升尤其明显
- 不需要 ReID 特征也能达到接近 SOTA 的成绩
2.3 ByteTrack 与 SORT/DeepSORT 的核心区别
| 特性 | SORT | DeepSORT | ByteTrack |
|---|---|---|---|
| 检测框筛选 | 仅高分框 | 仅高分框 | 高低分框都用 |
| 外观特征 | 无 | CNN ReID 特征 | 无(纯 IoU) |
| 运动模型 | Kalman | Kalman | Kalman(同 SORT) |
| 关联匹配 | 单轮匈牙利 | 级联匹配 | 两轮匈牙利 |
| 关联度量 | IoU | 马氏+余弦距离 | IoU 距离 |
| 遮挡处理策略 | 短暂保留 | 级联+特征 | 30 帧保留+第二轮匹配 |
| ReID 是否必须 | 否 | 是 | 否(但可加) |
| 核心优势 | 最快 | 稳健 | 简单有效 |
三、Siamese 跟踪范式
Siamese 网络(孪生网络)是单目标跟踪(SOT)的主流范式,核心思想是学习一个相似度度量函数,让目标模板与搜索区域中相似的部分产生高响应。
3.1 SiamFC 的互相关操作
SiamFC(Bertinetto, 2016)用全卷积 Siamese 网络实现跟踪:
f ( z , x ) = φ ( z ) ⋆ φ ( x ) + b f(z, x) = \varphi(z) \star \varphi(x) + b f(z,x)=φ(z)⋆φ(x)+b
其中 φ \varphi φ 是共享权重的 CNN(AlexNet), ⋆ \star ⋆ 表示互相关操作(cross-correlation), z z z 是模板图像(127×127), x x x 是搜索区域(255×255)。
互相关的直觉:
- φ ( z ) \varphi(z) φ(z) 是模板的特征(如 6×6×256)
- φ ( x ) \varphi(x) φ(x) 是搜索区域的特征(如 22×22×256)
- 互相关结果是一个 17×17 的响应图,每个位置表示该位置与模板的相似度
- 响应图的最大值位置对应目标的中心偏移
为什么 Siamese 跟踪效率高?
- 模板只需要计算一次(第一帧初始化后通常不做更新)
- 搜索区域只计算当前帧的推理
- 全卷积网络输入任何尺寸都可在一次前向中完成
- 在 CPU 上也能达到实时
3.2 SiamRPN 的分类 + 回归分支
SiamRPN(Li, 2018)在 SiamFC 基础上引入了 RPN 式的分类和回归分支:
┌──→ Conv → 分类分支 (H×W×2k)
φ(z) ──→ ┐ ┌──→ Conv → 回归分支 (H×W×4k)
互相关 ───→ ───┐
φ(x) ──→ ┘ └──→ Conv → 分类分支 (H×W×2k)
└──→ Conv → 回归分支 (H×W×4k)
- 分类分支: 预测 k k k 个 anchor 的前景/背景分数( 2 k 2k 2k 通道)
- 回归分支: 预测 k k k 个 anchor 的 bbox 偏移( 4 k 4k 4k 通道)
- 使用 Adjust Layer 做互相关: φ ( z ) \varphi(z) φ(z) 和 φ ( x ) \varphi(x) φ(x) 分别过深度可分离卷积后再互相关
精度远超 SiamFC(可以预测变化的目标形状),速度仍保持实时。
3.3 SiamMask 的跟踪 + 分割联合
SiamMask(Wang, 2019)在 SiamRPN 基础上增加了一个分割分支,实现跟踪和分割的联合学习:
┌──→ 分类 (2k)
φ(z) ──→ ┥── ├──→ 回归 (4k)
互相关 └──→ 分割 (1×H×W)
φ(x) ──→ ┘
分割分支: 对互相关后的特征图做 2 层 1×1 Conv → 上采样 → 输入大小的二值掩码。
损失函数: L = λ 1 L c l s + λ 2 L r e g + λ 3 L m a s k \mathcal{L} = \lambda_1 \mathcal{L}_{cls} + \lambda_2 \mathcal{L}_{reg} + \lambda_3 \mathcal{L}_{mask} L=λ1Lcls+λ2Lreg+λ3Lmask
优势: 跟踪不再只有 bbox,而是像素级的目标分割,在 VOT 数据集中 mask-based 评估更准确
3.4 为什么 Siamese 跟踪能实现高效跟踪
- 在线跟踪 = 相似度查询:第一帧提取模板特征,后续帧只做相似度匹配,无梯度回传
- 全卷积网络:输入分辨率不影响推理速度的核心瓶颈
- 无在线微调:Template 特征只在第一帧提取,不随时间更新(大部分实现),避免在线学习的计算开销
- 强先验:搜索区域通常以预测位置为中心,裁剪固定大小,计算量恒定
四、Transformer 跟踪
4.1 TransT 的自我 + 跨注意力融合
TransT(Chen, 2021)首次将 Transformer 用于特征融合,替代 SiamFC 的简单互相关:
φ(z) ──→ Positional Encoding ──→ Transformer Encoder (自我注意力)
↓
拼接
↓
φ(x) ──→ Positional Encoding ──→ Transformer Encoder (自我注意力)
↓
Transformer Decoder (跨注意力)
↓
分类+回归
自我注意力(Self-Attention): 模板/搜索区域内各自做注意力,增强特征的全局关联
跨注意力(Cross-Attention): 模板特征作为 Query,搜索区域作为 Key/Value,让搜索区域中的每个位置都在模板中查找最相关的信息
优势:
- 互相关只做一阶匹配(点积),Transformer 能建模更复杂的特征交互
- 跨注意力让搜索区的每个位置可以聚合模板中多个位置的信息
- 在遮挡、形变等复杂场景下鲁棒性更好
4.2 MixFormer 的联合特征提取与融合
MixFormer(Cui, 2022)进一步将特征提取和融合完全统一到 Transformer:
核心是 MAM(Mixed Attention Module),交替执行:
- 自我注意力:模板内、搜索区域内独立交互
- 跨注意力:模板↔搜索区域交互
[z; x] ──→ MAM ×N ──→ [z', x']
优势:
- 特征提取和融合不再分开,而是端到端统一优化
- 深层的 MAM 可以捕获更复杂的语义关联
- 消除了 CNN backbone + Transformer 融合的鸿沟
4.3 跟踪中的模板更新策略
固定模板(SiamFC 等):
- 第一帧模板固定不动
- 优点:简单高效,不会受漂移影响
- 缺点:目标外观变化时无法适应
线性更新(在线学习):
- θ t = ( 1 − α ) ⋅ θ t − 1 + α ⋅ θ t c u r r e n t \theta_t = (1-\alpha) \cdot \theta_{t-1} + \alpha \cdot \theta_t^{current} θt=(1−α)⋅θt−1+α⋅θtcurrent
- 优点:逐步适应目标变化
- 缺点:轻度遮挡可能导致污染累积
质量感知更新(自适应):
- 只在高置信度帧更新模板(如分类分数 > 阈值)
- 使用检测质量(IoU 预测)作为更新条件
- 更新前验证更新结果与历史模板的一致性
- 目前主流做法
Score-based 更新:
- 分类分支的峰值分数 > 阈值 → 更新
- 峰值分数低(遮挡/出视野)→ 不更新
五、OC-SORT 详解
5.1 对 SORT 问题的改进
OC-SORT(Observation-Centric SORT, 2023)分析了传统 SORT 的根本问题:SORT 过度依赖 Kalman 运动模型,在长时间遮挡和非线性运动下容易崩溃。
核心改进:
| 改进点 | 原理 | 解决问题 |
|---|---|---|
| OCR(Observation-Centric Recovery) | 使用观测(检测框)而非 Kalman 预测来计算 IoU 关联。当轨迹丢失后恢复时,用观测来修正 Kalman 状态 | Kalman 预测在长时遮挡后偏差过大 |
| OVB(Observation-Centric Velocity) | 速度不再是 Kalman 平滑的,而是基于观测 bbox 中心差来估计: u ˙ = ( u t − u t − 1 ) / Δ t \dot{u} = (u_t - u_{t-1})/\Delta t u˙=(ut−ut−1)/Δt | 非线性运动时 Kalman 速度估计不准 |
| ORU(Observation-Centric Re-Update) | 每次关联后,用观测重新初始化和更新 Kalman 的状态,修正累积的预测偏差 | Kalman 协方差漂移 |
5.2 为什么能处理长时遮挡
SORT 处理长时遮挡的失败模式:
帧 t: 物体被遮挡, Kalman 只能向前预测
帧 t+1: 预测继续变差
...
帧 t+N: Kalman 预测已严重偏离真实位置
帧 t+N+1: 物体出现, 但预测位置与检测相差太远, 无法匹配
→ ID Switch(新 ID 分配给同一物体)
OC-SORT 的解决:
- 长时遮挡期间,Kalman 预测不作为关联依据
- 遮挡后物体重新出现时,直接用检测框计算 IoU 关联
- 用观测重新初始化 Kalman 状态(ORU),消除累积偏差
- 虚拟轨迹(Virtual Track):在遮挡期间不代表物体的位置,但保留 ID 信息
5.3 与 DeepSORT 对比的定量分析
| 对比维度 | DeepSORT | OC-SORT |
|---|---|---|
| 核心依赖 | 外观 ReID + Kalman 运动 | 观测优先 + 纯 IoU |
| 长时遮挡(>3 秒) | ID Switch 率: ~40% | ID Switch 率: ~15% |
| 密集人群 | 好(ReID 可区分外观) | 好(OC 策略 + 观测修正) |
| 快速运动 | 差(Kalman 跟不上) | 好(OBV 直接使用观测速度) |
| ReID 模型 | 必需 | 不需要 |
| 推理速度 | ~100 FPS(含 ReID) | ~250 FPS(纯 IoU) |
| MOTA(MOT17) | 60.3% | 65.7% |
| 适用场景 | 运动较规律,ID 稳定 | 运动剧烈、频繁遮挡 |
OC-SORT 在 DanceTrack(大量快速运动+遮挡)上的 HOTA 领先 DeepSORT 约 15 个百分点,证明了它在复杂运动场景下的优势。它的核心哲学是让观测本身主导跟踪决策,而非过度信任运动模型。
更多推荐
所有评论(0)