0%

Features for Multi-Target Multi-Camera Tracking and Re-Identification

梳理MTMC问题经典论文Features for Multi-Target Multi-Camera Tracking and Re-Identification中的方法。

Features for Multi-Target Multi-Camera Tracking and Re-Identification

作者:Ergys Ristani, Carlo Tomasi (Duke University)

Abstract

Multi-Target Multi-Camera Tracking (MTMCT) tracks many people through video taken from several cameras. Person Re-Identification (Re-ID) retrieves from a gallery images of people similar to a person query image. We learn good features for both MTMCT and Re-ID with a convolutional neural network. Our contributions include an adaptive weighted triplet loss for training and a new technique for hard-identity mining. Our method outperforms the state of the art both on the DukeMTMC benchmarks for tracking, and on the Market-1501 and DukeMTMC-ReID benchmarks for Re-ID. We examine the correlation between good Re-ID and good MTMCT scores, and perform ablation studies to elucidate the contributions of the main components of our system.

1. 任务定义与整体思路

MTMCT 的目标是,给定 nn 路无重叠视域的视频流 V=V1,,VnV={V1,…,Vn},输出每个人在全局时空中的完整轨迹 T=T1,,TlT={T1,…,Tl}
Re-ID 的目标是:给定查询图 qq,在跨相机图库 GG 中按相似度降序返回同身份图像。

作者提出只学习特征,不学习关联:

  • 训练阶段:用改进的加权三元组损失(AWTL)+ 困难身份挖掘(HNM)在纯 Re-ID 协议下训练 128-D 外观特征;
  • 测试阶段:用相关聚类(Correlation Clustering)一次性把全部检测关联成跨相机轨迹;
  • 检测器与特征解耦,整体 pipeline 通过三阶段递进,即检测 → 单相机轨迹 → 跨相机轨迹。

2. 训练:外观特征学习

2.1 三元组损失的通用形式

在行人 Re-ID 任务里,我们把一张含有某个人全身(或可见大部分身体)的 bounding-box 图像叫做一个 样本(或 patch、embedding)。

训练时,输入网络的图像三元组如下:
· 先随机选 一个身份 ID-a(比如张三)。
· 从 ID-a 当天被不同相机拍到的所有框图里,随机抽 KK 张(论文 K=4K=4)。这 KK 张里的任意一张就叫 锚点图像 xaxa(anchor)。
· 同属 ID-a 的其余框图都叫 正样本图像 xp(positive)——它们和 xa 同身份,只是视角、光照、姿态或遮挡不同。
再从 其它任何身份(李雷、韩梅…)的框图里随机抽若干张,叫 负样本图像 xnnegativexn(negative),它们和 xaxa 身份不同。

对锚点 xaxa,设 P(a)P(a) 为正样本集,N(a)N(a) 为负样本集,定义

L3=[m+xpP(a)wpd(xa,xp)xnN(a)wnd(xa,xn)]+L_3=\left[m+\sum_{x_p\in P(a)}w_pd(x_a,x_p)-\sum_{x_n\in N(a)}w_nd(x_a,x_n)\right]_+

其中 d(,)d(·,·) 为欧氏距离,m=1m=1。关键在权重 w,w{wₚ, wₙ} 的设计。

2.2 自适应权重(AWTL)

与 Batch-Hard 仅给最难样本赋 1、其余 0 不同,作者提出 softmax 式连续权重:

wp=ed(xa,xp)xP(a)ed(xa,x),wn=ed(xa,xn)xN(a)ed(xa,x)w_p=\frac{e^{d(x_a,x_p)}}{\sum_{x\in P(a)}e^{d(x_a,x)}},\quad w_n=\frac{e^{-d(x_a,x_n)}}{\sum_{x\in N(a)}e^{-d(x_a,x)}}

Batch-Hard的缺点:

  • 梯度只来自两张图,其余样本被浪费;
  • 如果“最难”样本是离群帧(遮挡、误检),网络会被强行拉向错误方向;
  • 权重是 0/1 硬分配,无法兼顾多个难样本。

自适应权重的优势:

  • hardest 样本若是离群,权重不会独大;
  • 多个难分样本同时获得梯度,训练更稳定。

2.3 困难身份挖掘(HNM)

训练集身份数大时,随机 PK 采样很难碰到真正困难的身份。作者维护两个池:

  • Hard-Identity-Pool H:对当前锚点,全局特征距离最大的 H=50 个身份;
  • Random-Pool:其余身份。

每个 mini-batch 中,除锚身份外的 P–1 个身份以 0.5/0.5 概率从上述两池抽取,再各随机选 K=4 张图。
实践:网络先 warm-up 5 k 次迭代,用此刻特征离线计算一次 H,之后固定到训练结束。

2.4 网络结构与增强

训练样本:含行人的边框图 + 身份编号

  1. 骨架:ImageNet 预训练 ResNet-50
  • 输入形状:(B, 3, 256, 128)
  • 输出:pool5 特征图 (B, 2048, 8, 4)(原始 ImageNet 是 7×7,这里是 8×4,因为行人图高宽比 2:1)
  • 只保留“卷积+BN+ReLU”部分,把全局平均池化(GAP)和 1000-D fc 全部丢掉;确保得到空间维度 8×4 的 2048 通道卷积特征。
  1. 全局最大池化(GMP)或平均池化(GAP)
  • 使用Global Average Pooling(GAP)或者 Global Max Pooling(GMP)把 (B, 2048, 8, 4) 的特征图压成 (B, 2048, 1, 1),再 flatten 成 (B, 2048) 向量。把空间信息压成固定长度向量
  1. 第一全连接
  • 全连接层:把 2048 维向量映射到 1024 维。
  • 加 BatchNorm1d(缓解内部协变量偏移)
  • 加 ReLU(引入非线性)
  1. 第二全连接
  • 1024 → 128(嵌入层)
  • 直接输出 128-D 向量,保证嵌入空间是线性的,方便后面算欧氏距离
  1. L₂ 归一化
  • 把每个 128-D 向量拉成单位球面:x‖₂=1‖x‖₂ = 1
  1. 最终输出
  • 把网络输出的 128-D 单位向量组织成三元组$ (xa, xp, xn),算欧氏距离,算欧氏距离 d(·,·)$,再代入自适应加权三元组损失,得到梯度并回传。

上述方法的伪代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
model.train()
optim.zero_grad()

# ===== 1. 前向拿到 128-D 单位向量 =====
embs = model(imgs) # (B, 128) 已在模型里 L2-normalize
embs = embs.view(P, K, 128) # (P, K, 128) 方便按身份切片

# ===== 2. 逐身份构造三元组 =====
loss_batch = 0
for i in range(P): # 每个身份当一次锚
xa = embs[i, 0] # 选该身份第 1 张当锚(可随机)
xp = embs[i, 1:] # 同身份其余 K-1 张 = 正
xn = embs[torch.arange(P)!=i] # 其余 (P-1) 个身份 = 负
xn = xn.view(-1, 128) # 拉平成 ((P-1)*K, 128)

# ===== 3. 算欧氏距离 =====
d_ap = torch.cdist(xa.unsqueeze(0), xp) # (1, K-1)
d_an = torch.cdist(xa.unsqueeze(0), xn) # (1, (P-1)*K)

# ===== 4. 自适应权重 =====
w_p = F.softmax(d_ap, dim=1) # 正样本权重 (1, K-1)
w_n = F.softmax(-d_an, dim=1) # 负样本权重 (1, (P-1)*K)

# ===== 5. 加权三元组损失 =====
pos_term = (w_p * d_ap).sum()
neg_term = (w_n * d_an).sum()
loss_i = F.relu(m + pos_term - neg_term) # m=1 论文设置
loss_batch += loss_i

loss = loss_batch / P # 平均到每个锚
loss.backward()
optim.step()

3. 测试:MTMC 跟踪 pipeline

整体流程见下图

3.1 输入检测

采用公开 OpenPose 人体检测器(基于 PAF,在 Part Affinity 上直接监督),输出每帧边界框。

3.2 特征提取

检测给出的任意高宽比框先被等比缩放到高 256 像素、宽 128 像素(不足两侧补灰条),再做 ImageNet 均值-方差归一化;固定权重的 ResNet-50 卷积基提取 2048-D 全局特征,经 2048→1024→128 两层全连接(带 BN 与 ReLU)并 L₂ 归一化后,输出 128 维单位向量 xxᵢ,供后续关联使用。

3.3 相似度计算

  1. 外观相关度
  • 先离线在训练集上统计所有正/负对的平均距离 μ,μμₚ, μₙ,令阈值
      t=(μ+μ)/2tₐ = (μₚ + μₙ)/2  (≤1)
  • 则对任意一对检测,外观相关度为:
      wijA=(tₐ–d(x,x))/tw_{ij}^{A} = (tₐ – d(xᵢ,xⱼ))/tₐ
    值域 (−∞,1],同身份期望为正,异身份期望为负。
  1. 运动相关度
  • 离线:用训练集里已知的短轨迹,按“常速模型”向前、向后各预测 10 帧,得到预测框与真实框的 IoU 误差,统计出能把“同一轨迹对”与“不同轨迹对”分开的误差阈值$ t_m$ 和缩放因子 αα
  • 在线:对两条待关联轨迹,用各自最近 5 帧估速度,采用线性匀速模型,前向-后向双向预测,得误差 em=ef+ebe_m = e_f + e_b
    在训练集上拟合阈值 tmt_m 及缩放 αα,令
      wijM=α(tmem)w_{ij}^{M} = α(t_m – e_m)  若 e_m 可计算;否则$ –∞$
    为正,鼓励关联,为负,拒绝不可能跳跃
  1. 时间折扣:
    对时间差 Δt 的两检测,引入指数衰减, 惩罚“时间隔得太远”的边
      Dij=exp(βΔt)D_{ij} = exp(–βΔt)

  2. 最终边权
      W=(WA+WM)DW = (W^{A} + W^{M}) ⊙ D
    其中 为逐元素乘。

3.4 相关聚类优化

  1. 构造无向图 G=(V,E,W)G=(V,E,W)VV 为所有检测节点(每一帧的每个检测框就是一个节点,带属性 ⟨t, x, y, w, h, 128-D 向量⟩。),边权 WW 如上(正值 → 鼓励同簇;负值 → 鼓励异簇)。

  2. 目标函数:最大化一致边的总权重,给每条边一个二进制变量 xij0,1x_ij ∈ {0,1}

  • xij=1x_{ij} = 1 ⇒ iijj 同身份(放在同一簇)
  • xij=0x_{ij} = 0 ⇒ iijj 不同身份(分属两簇)
    整数规划就是
  • maxΣwijxijmax Σ w_ij x_ij
    尽量多地把正值边收进簇里,把负值边踢到簇外
  1. 约束条件
  • 传递性:
      xij+xjk1+xikx_{ij} + x_{jk} ≤ 1 + x_{ik}
    i,j,ki,j,k 三者中,若 i,ji,j 同身份,则 i,k,ji,k,j 同身份,必须满足传递性。
  1. 求解方法
    求解整数规划:

X=argmaxxij0,1(i,j)Ewijxijs.t.xij+xjk1+xikX* = argmax_{x_{ij}∈{0,1}} ∑_{(i,j)∈E} w_{ij}x_{ij}  s.t. x_{ij}+x_{jk} ≤ 1+x_{ik}

等价于最大一致子图问题,NP-hard,但现有启发式(如 SA、Greedy Agglomerative)在千级节点上足够高效。 解中 xijx_{ij}=1 表示 i,ji,j 同身份,由此得到全局身份标签。

3.5 后处理

  • 线性插值:对同一轨迹 0<tgap20 < t_gap ≤ 2 s 的漏检做线性插补;
  • 低置信修剪:若轨迹检测置信均值 < 0 或长度 < 5 帧,则丢弃。

3.6 三级层次推理降低复杂度

  1. Tracklet 级:1 s 不重叠滑动窗内用贪心最近邻生成短轨迹;
  2. 单相机级:10 s 滑动窗(50 % 重叠)内把 tracklet 作为节点,重复 3.3-3.4 步骤;
  3. 跨相机级:1.5 min 滑动窗,把单相机轨迹作为节点,重复 3.3-3.4 步骤,得到最终跨相机 ID。