CenterTrack Tracking Objects as Points

Task: Multi-Object Tracking
Method: joint detection and tracking, center-based
Venue: ECCV
Year: 2020
Paper: https://arxiv.org/abs/2004.01177
Code: https://github.com/xingyizhou/CenterTrack

摘要

多目标跟踪长期由”先检测再关联”(tracking-by-detection)范式主导,依赖复杂的关联策略(Kalman Filter、ReID 特征、图匹配)将不同帧的检测框链接起来。本文提出 CenterTrack,一种同时进行检测和跟踪的算法:以 CenterNet 为基础,将当前帧、前一帧图像和前一帧跟踪结果渲染的 heatmap 作为输入,在检测中心点的同时预测帧间位移 offset。跟踪仅需基于中心距离的贪心匹配。CenterTrack 在 MOT17 上达到 67.8% MOTA(22 FPS)、KITTI 上 89.4% MOTA(15 FPS),均为同期最优;在 nuScenes 3D 跟踪上以 28.3% AMOTA@0.2 大幅超越单目基线。

核心论点:如果物体是点(CenterNet),跟踪就是点的轨迹——只需预测相邻帧间中心点的位移,贪心匹配即可关联身份,无需任何外部运动模型或外观特征。

问题与动机

主流多目标跟踪方案各有局限:

方案 代表作 核心问题
Tracking-by-detection SORT / DeepSORT 检测与跟踪分离,关联依赖 Kalman Filter + ReID,速度慢
联合检测+跟踪(框传播) Tracktor 用 bbox regression 传播身份,要求帧间 bbox 高重叠(低帧率失效)
联合检测+跟踪(区域提议) Integrated Detection 用历史 bbox 作为额外 proposal,需 bipartite matching

核心痛点:现有联合方法均基于 bounding box 传播,假设相邻帧 bbox 高度重叠。当帧率较低(如 nuScenes 2 FPS)或物体运动剧烈时,这一假设不成立,跟踪性能急剧下降。

核心洞察

洞察 1:用 heatmap 而非 bbox 传递历史跟踪信息

传统方法用前一帧的 bounding box 作为 region proposal 传递给当前帧,这要求相邻帧 bbox 重叠。CenterTrack 将前一帧的跟踪结果渲染为 class-agnostic 的高斯 heatmap $H^{(t-1)} = \mathcal{R}({\mathbf{p}_0^{(t-1)}, \mathbf{p}_1^{(t-1)}, \ldots})$,与当前帧和前一帧图像一起作为网络输入(+4 通道)。

为什么更优

  • heatmap 是空间连续的软信号,即使物体大幅移动,网络仍能在感受野内找到对应关系
  • 被遮挡物体在 heatmap 中仍有峰值,网络可从中”恢复”当前帧不可见的目标
  • class-agnostic 单通道设计极其轻量

洞察 2:稀疏位移预测比稠密光流更适合跟踪

光流估计每个像素的运动,计算量大且不直接对应物体。CenterTrack 只在检测到的中心点处预测 2D offset $\hat{\mathbf{d}}^{(t)} = \hat{\mathbf{p}}^{(t)} - \hat{\mathbf{p}}^{(t-1)}$,本质是稀疏光流

$$L_{off} = \frac{1}{N}\sum_{i=1}^{N} |\hat{D}_{\mathbf{p}_i}^{(t)} - (\mathbf{p}_i^{(t-1)} - \mathbf{p}_i^{(t)})|$$

为什么更优

  • 只需 2 个额外输出通道(vs FlowNet2 的 ~150ms 推理)
  • 输出直接对应语义物体(非像素),无需后处理
  • 训练与检测 loss 联合优化,offset 学到的不仅是运动,还包含”snap to nearest prior detection”的关联能力

洞察 3:噪声注入使静态图像可替代视频训练

训练时前一帧的 GT heatmap 完美无缺,但推理时 heatmap 包含假阳性、假阴性和定位抖动。若不模拟这种差异,网络会学到”直接复制上一帧检测”而拒绝发现新物体。CenterTrack 通过三种噪声注入解决:位置抖动($\lambda_{jt}=0.05$)、假阳性($\lambda_{fp}=0.1$)和假阴性($\lambda_{fn}=0.4$)。

为什么关键:不加噪声时 MOTA 从 66.1% 暴跌至 34.4%(FN 率从 28.4% 飙升至 57.4%)——网络在空 heatmap(第一帧)时完全无法检测到物体。有了噪声注入后,甚至可以用静态图像+随机仿射变换模拟”前一帧”来训练,在 MOT17 上性能与视频训练持平(66.1% MOTA)。

要记住的 3 个数字

  • 67.8% MOTA:MOT17 私有检测 SOTA @ 22 FPS
  • 89.4% MOTA:KITTI 跟踪 SOTA @ 15 FPS
  • 28.3% AMOTA@0.2:nuScenes 单目 3D 跟踪,比基线高 4× @ 28 FPS

方法设计

整体架构

$$\text{Tracking} = \text{CenterNet Detection} + \text{Prior Heatmap Conditioning} + \text{Offset Prediction}$$

CenterTrack 架构图
      当前帧 I(t)        前一帧 I(t-1)      前一帧跟踪 heatmap H(t-1)
       [H,W,3]             [H,W,3]              [H,W,1]
          └───────────────────┼────────────────────┘
                              ↓ 拼接
                          [H, W, 7]
                              ↓
                   ┌──────────────────────┐
                   │  CenterNet Backbone  │
                   │  (DLA-34, stride=4)  │
                   │  (+4 input channels) │
                   └──────────────────────┘
                              ↓
                        [H/4, W/4, C]
                              ↓
        ┌──────────┬──────────┬──────────┬──────────┐
        ↓          ↓          ↓          ↓          ↓
    Heatmap     Size      Offset    Tracking    (3D heads)
    [H/4,W/4,C] [H/4,W/4,2] [H/4,W/4,2] [H/4,W/4,2]  (可选)
        ↓          ↓          ↓          ↓
        └──────────┴──────────┴──────────┘
                              ↓
                   ┌──────────────────────┐
                   │  Peak Detection      │
                   │  + Greedy Matching   │
                   │  (center distance)   │
                   └──────────────────────┘
                              ↓
                     检测框 + tracking_id

预测头

预测头 输出尺寸 功能 新增
Heatmap $H/4 \times W/4 \times C$ 检测当前帧中心点
Size $H/4 \times W/4 \times 2$ 预测宽高
Offset $H/4 \times W/4 \times 2$ 修正量化误差
Tracking $H/4 \times W/4 \times 2$ 帧间位移(关联用)

损失函数

$$L = L_{heatmap} + 0.1 L_{size} + L_{offset} + L_{tracking}$$

关键代码(来源:src/lib/model/decode.py

解码函数 generic_decode 中处理 tracking offset 的核心逻辑:

# 解码所有回归头,tracking offset 与 dep/rot/dim 等统一处理
regression_heads = ['tracking', 'dep', 'rot', 'dim', 'amodel_offset',
'nuscenes_att', 'velocity']

for head in regression_heads:
if head in output:
ret[head] = _tranpose_and_gather_feat(
output[head], inds).view(batch, K, -1)
📄 点击展开 CenterTrack 贪心关联代码

(来源:src/lib/utils/tracker.py

def step(self, results, public_det=None):
N = len(results)
M = len(self.tracks)

# 当前检测中心 + offset 投影回前一帧
dets = np.array(
[det['ct'] + det['tracking'] for det in results], np.float32) # N x 2
tracks = np.array(
[pre_det['ct'] for pre_det in self.tracks], np.float32) # M x 2

# 计算投影位置与前一帧跟踪位置的距离矩阵
dist = (((tracks.reshape(1, -1, 2) -
dets.reshape(-1, 1, 2)) ** 2).sum(axis=2)) # N x M

# 无效匹配:距离过大、尺度不匹配、类别不同
track_size = np.array([((t['bbox'][2] - t['bbox'][0]) *
(t['bbox'][3] - t['bbox'][1])) for t in self.tracks], np.float32)
item_size = np.array([((item['bbox'][2] - item['bbox'][0]) *
(item['bbox'][3] - item['bbox'][1])) for item in results], np.float32)
item_cat = np.array([item['class'] for item in results], np.int32)
track_cat = np.array([track['class'] for track in self.tracks], np.int32)
invalid = ((dist > track_size.reshape(1, M)) +
(dist > item_size.reshape(N, 1)) +
(item_cat.reshape(N, 1) != track_cat.reshape(1, M))) > 0
dist = dist + invalid * 1e18

# 贪心匹配(按置信度降序,逐个选最近的未匹配轨迹)
matched_indices = greedy_assignment(copy.deepcopy(dist))

# 匹配成功:继承 tracking_id
ret = []
for m in matched_indices:
track = results[m[0]]
track['tracking_id'] = self.tracks[m[1]]['tracking_id']
ret.append(track)

# 未匹配检测:分配新 ID
unmatched_dets = [d for d in range(N) if not (d in matched_indices[:, 0])]
for i in unmatched_dets:
track = results[i]
if track['score'] > self.opt.new_thresh:
self.id_count += 1
track['tracking_id'] = self.id_count
ret.append(track)

self.tracks = ret
return ret


def greedy_assignment(dist):
"""按行(当前检测)顺序,贪心选择距离最小的列(前一帧轨迹)"""
matched_indices = []
if dist.shape[1] == 0:
return np.array(matched_indices, np.int32).reshape(-1, 2)
for i in range(dist.shape[0]):
j = dist[i].argmin()
if dist[i][j] < 1e16:
dist[:, j] = 1e18 # 已匹配的轨迹不再参与后续匹配
matched_indices.append([i, j])
return np.array(matched_indices, np.int32).reshape(-1, 2)

实验与分析

主要结果

数据集 指标 CenterTrack SOTA 对比 速度
MOT17(公共检测) MOTA 61.5% Tracktor v2: 56.5% 57ms
MOT17(私有检测) MOTA 67.8% 57ms
KITTI MOTA 89.4% mmMOT: 84.8% 82ms
nuScenes(单目 3D) AMOTA@0.2 28.3% Baseline: 6.9% 45ms

关键发现

  • MOT17 公共检测比 Tracktor v2 高 5 个点(+8.6%),证明增益来自跟踪框架本身而非检测质量
  • KITTI 刷新全部已发表结果(89.4% MOTA),跟踪 overhead 仅为检测之上的网络 forward pass
  • nuScenes 单目 3D 跟踪超基线 4×,证明 offset 预测在低帧率大运动场景尤为有效

消融实验

配置 MOT17 MOTA KITTI MOTA nuScenes AMOTA 验证洞察
仅检测(无 heatmap/offset) 63.6 84.3 18.1
+ heatmap,无 offset 65.8 87.1 17.8 洞察 #1
+ offset,无 heatmap 63.9 85.4 26.5 洞察 #2
完整 CenterTrack 66.1 88.7 28.3 #1 + #2
完整,无噪声注入 34.4 洞察 #3
完整,静态图像训练 66.1 洞察 #3

核心结论

  1. heatmap 主要减少 FN(+2% MOTA on MOT/KITTI),因为网络”记住”上一帧的检测位置
  2. offset 主要减少 IDSW:高帧率时 offset 贡献小(MOT 从 2.5%→1.0% IDSW),低帧率时贡献巨大(nuScenes AMOTA +10.5%)
  3. 噪声注入是训练关键:不加噪声 MOTA 暴跌至 34.4%——网络学会”复制上一帧”而拒绝新检测

运动模型对比

运动模型 MOT17 MOTA KITTI MOTA nuScenes AMOTA
无运动(零 offset) 65.8 87.1 17.8
Kalman Filter 66.1 87.9 18.3
光流(FlowNet2, ~150ms) 66.1 88.4 26.6
CenterTrack offset 66.1 88.7 28.3

高帧率下所有运动模型效果接近;低帧率(nuScenes 2 FPS)下 CenterTrack 优于光流和 Kalman Filter——因为 offset 不仅预测运动,还学会”snap to prior detection”的关联能力。

工程实践

训练配置

Backbone: DLA-34 (从 CenterNet 预训练初始化)
Input: 960×544 (MOT) / 1280×384 (KITTI) / 800×448 (nuScenes)
Batch: 32
Optimizer: Adam (lr=1.25e-4)
Epochs: 70 (learning rate ×0.1 at epoch 60)
Augmentation: 随机翻转、随机缩放裁剪、色彩抖动
Training Time: ~24h (DLA-34, 4×V100)

复现要点

  1. 从 CenterNet 初始化:复用所有检测相关权重,仅随机初始化 4 个额外输入通道和 tracking 输出头。从零训练精度下降 5.4% MOTA(MOT17)。

  2. heatmap 噪声参数:$\lambda_{jt}=0.05$(位置抖动幅度 = 5% bbox 尺寸)、$\lambda_{fp}=0.1$(10% 概率添加假阳性)、$\lambda_{fn}=0.4$(40% 概率删除检测)。这些参数应根据基线检测器的实际误差率调整。

  3. 输出阈值设置:MOT 用 $\theta=0.4, \tau=0.5$;nuScenes 用 $\theta=0.1, \tau=0.1$(低帧率需保留更多低置信检测)。track rebirth 仅在 MOT 测试集使用($K=32$ 帧重生窗口)。

  4. 3D 跟踪扩展:nuScenes 上先训练 140 epochs 纯 3D 检测,再 fine-tune 70 epochs 加入 tracking。6个相机输出简单拼接,不处理视图重叠区域。

研究启示

7.1 可迁移的思想

  • 条件输入(heatmap conditioning):将前序任务的输出渲染为空间 heatmap 作为后续网络输入,是一种通用的序列推理技巧,可应用于姿态跟踪、视频分割等
  • 稀疏位移优于稠密光流:只在关键点处预测运动向量,既快又准。类似思想被 StreamPETR 的 query 传播和 Sparse4D 的实例传播所继承
  • 噪声注入模拟推理误差:训练时有意注入推理阶段可能出现的错误,使模型更鲁棒,是 domain adaptation 思想的简化版

7.2 方法局限

  • 纯局部跟踪:仅关联相邻两帧,物体消失后重现会获得新 ID(长程重识别需外部模块)
  • 贪心匹配非最优:置信度顺序的贪心匹配在密集场景可能产生次优分配(实验中匈牙利也没更好)
  • 3D 能力有限:单目 3D 检测精度受限,28.3% AMOTA 仍远低于 LiDAR 方法

7.3 技术影响

  • 简化多目标跟踪:证明联合检测+跟踪只需一个检测网络 + 额外 2 通道 offset,无需 Kalman Filter、ReID、图匹配
  • **催生 CenterPoint**:CenterTrack 的 offset-based 贪心匹配被 CenterPoint 简化为 velocity-based 匹配,推广到 3D LiDAR 跟踪
  • 影响 ByteTrack 等后续工作:贪心匹配 + 简单运动模型的范式影响了后续一系列高效跟踪器