论文地址:链接
一、 介绍
大多数追踪DBT范式的方法退化为连续两帧之间的集合的匹配问题,如上图,追踪器就是用来寻找到这两个集合中的这么一个可能的关联(黑线)。这种范式检测器可以独立进行操作,最后将检测器和追踪器整合进一个单元完成MOT。
这篇论文提出了一个不同于DBT范式的框架,实时,能够多帧推理。是一个基于动态无方向的二分图的神经网络,主要受到经典MOT方法如MHT这类概率图表示启发而来。架构本质上是一个带有通信存储单元的消息传递神经网络(MPNN),它的的图形结构会随着时间的推移而变化。虽然已经有其他方法将GNNs应用于多目标跟踪问题,但是并没有方法利用通信存储单元来关联图中的节点的。和早期基于假设的传统方法一样,我们不显示的产生目标的追踪树,通过限制图的活跃区域的大小来决定关联,抑制算力的指数性增长。通过在计算节点关联时引入交叉熵损失完成概率的聚集操作。图形结构代表了轨迹的叠加,最终解码为最优的轨迹。
二、 追踪框架
传统的MOT关联步骤就是使用连续帧上的二分图匹配,这里思考的是,直接使用GNN在图结构上直接建模MOT。这个图结构也可以扩展到包含多个连续的时间步,从而包含非局部信息并推断出遥远的关联。
2.1 动态无向图结构
将MOT任务建模为一个无向图推理问题,每个检测作为一个图上的结点,之间的潜在关联作为边。
当每个时间戳新的检测加入的时候,图会动态更新,并去除老的监测点。总体结构如下图:
模型从左到右在图上某一窗口内动态操作。动态图是二分图,由检测节点和关联节点两个独立的集合。检测节点代表一个时间序列的检测对象,由相应的目标特征表示;关联节点表示不同时间戳下两个检测之间潜在的成对关联,初始化为
0
0
0向量,后续会被模型更新,以便获得每个节点的在图中的隐藏表示。
这样转变可以在对任意两个检测间或者多个时间步进行关联计算得分时,可以考虑多个竞争关联。并且储存的信息可以通过消息传递机制传递多个时间步,从而修正过去的错误信息。
由于网络可以从特征进行端到端学习,因此不需要带有加权分数的精细调整的代价函数。
2.2 训练和推导
介绍结构和优化前,提供宏观训练和推导伪代码:
一次训练迭代伪代码:
MOT序列推理伪代码:
- initialize graph():从两个连续帧初始图,检测点为两个连续的时间帧,每对检测间存在一个关联点。
- update graph():在当前图的后面加入新增加检测和关联(节点和边),关联节点只在那些新引入的检测节点之间以及过去时间中未匹配的检测节点之间增加。并且该函数用与去除当前图中过去的结点和边。类似于滑动窗口向后执行。
- prune graph():使用一个自定义阈值,去除当前图中的低可信度边和点。
- decode graph():这个函数被调用来解码图中每个节点的模型产生的输出概率到相应的目标轨迹(贪婪方式,或者用匈牙利算法)
- TrackMPNN():初始化模型
- TrackMPNN.forward():前向传播一次数据
- TrackMPNN.backward():通过产生的梯度损失进行一次反向传播
推理使用滑动窗口的方式,从过去(左)到未来(右)的方式,达到连续推理。训练时动态图需要为所有检测和关联存储梯度,所以无法连续。为了简化训练,将整个序列分割为多块,用作单独训练处理,最终累计损失,如算法1。
三、模型结构
TrackMPNN主要由以下几个部分组成:
- 消息传递函数: m ⃗ v k = ∑ w ∈ N ( v ) M ( h ⃗ v k − 1 , h ⃗ w k − 1 ) (1) \vec{m}_{v}^{k}=\sum_{w \in \mathcal{N}(v)} M\left(\vec{h}_{v}^{k-1}, \vec{h}_{w}^{k-1}\right) \tag{1} mvk=w∈N(v)∑M(hvk−1,hwk−1)(1)
- 节点更新函数: h ⃗ v k = U ( h ⃗ v k − 1 , m ⃗ v k ) (2) \vec{h}_{v}^{k}=U\left(\vec{h}_{v}^{k-1}, \vec{m}_{v}^{k}\right) \tag{2} hvk=U(hvk−1,mvk)(2)
- 输出函数:
y ^ v k = R ( h ⃗ v k ) (3) \hat{y}_{v}^{k}=R\left(\vec{h}_{v}^{k}\right) \tag{3} y^vk=R(hvk)(3)
v , w v, w v,w是图内节点,可以是上下文的检测节点或者关联节点。迭代 k k k不同于跟踪序列的当前时间步长 t t t。 t t t表示整个图的生存期, k k k表示这个动态图中每个单独节点的生存期。
3.1检测节点操作
设检测节点
d
d
d,及其邻居节点
a
i
∈
N
(
d
)
a_i ∈ N(d)
ai∈N(d),如下图3。
初始化:
检测节点的隐藏状态首先通过他的输入特征
x
⃗
d
\vec x_d
xd,经过线性转换(先激活和BN标准化)初始化得到:
h
⃗
d
0
=
W
det
i
′
BatchNorm
(
x
′
→
d
)
+
b
⃗
det
′
(4)
\vec{h}_{d}^{0}=\mathbf{W}_{\text {det }}^{i^{\prime}} \text { BatchNorm }\left(\overrightarrow{x^{\prime}}_{d}\right)+\vec{b}_{\text {det }}^{\prime} \tag{4}
hd0=Wdet i′ BatchNorm (x′d)+bdet ′(4)
其中:
x
′
→
d
=
ReLU
(
W
d
e
t
i
x
⃗
d
+
b
⃗
d
e
t
i
)
(5)
\overrightarrow{x^{\prime}}_{d}=\operatorname{ReLU}\left(\mathbf{W}_{d e t}^{i} \vec{x}_{d}+\vec{b}_{d e t}^{i}\right) \tag{5}
x′d=ReLU(Wdetixd+bdeti)(5)
检测节点的输入特征
x
⃗
d
\vec x_d
xd由一个检测器获得,但只使用一个2D的边界框坐标和检测器的目标类别来表示目标实例,依赖模型来学习图片位置模式:
x
⃗
d
=
[
x
⃗
d
;
2
d
∥
x
⃗
d
;
c
a
t
]
(6)
\vec{x}_{d}=\left[\vec{x}_{d ; 2 d} \| \vec{x}_{d ; c a t}\right] \tag{6}
xd=[xd;2d∥xd;cat](6)
其中
∣
∣
||
∣∣表示concat操作,其中:
x
⃗
d
;
2
d
=
(
x
1
,
y
1
,
x
2
−
x
1
,
y
2
−
y
1
,
score
)
⊤
(7)
\vec{x}_{d ; 2 d}=\left(x_{1}, y_{1}, x_{2}-x_{1}, y_{2}-y_{1}, \text { score }\right)^{\top} \tag{7}
xd;2d=(x1,y1,x2−x1,y2−y1, score )⊤(7)表示由边界框坐标和得分计算的2维特征,
x
⃗
d
;
c
a
t
=
(
0
,
⋯
,
1
,
⋯
,
0
)
⊤
(8)
\vec{x}_{d ; c a t}=(0, \cdots, 1, \cdots, 0)^{\top} \tag{8}
xd;cat=(0,⋯,1,⋯,0)⊤(8)表示目标类别的one-hot编码。
消息传递和节点更新函数:
检测节点的隐藏状态是通过其过去隐藏状态和过去邻接节点的隐藏状态更新的,由一个注意力机制赋权从而进行连接:
h
⃗
d
k
=
GRU
(
h
⃗
d
k
−
1
,
m
⃗
d
k
)
=
GRU
(
h
⃗
d
k
−
1
,
∑
a
i
∈
N
(
d
)
α
d
a
i
k
−
1
h
⃗
a
i
k
−
1
)
(9)
\begin{aligned} \vec{h}_{d}^{k} &=\operatorname{GRU}\left(\vec{h}_{d}^{k-1}, \vec{m}_{d}^{k}\right) \\ &=\operatorname{GRU}\left(\vec{h}_{d}^{k-1}, \sum_{a_{i} \in \mathcal{N}(d)} \alpha_{d a_{i}}^{k-1} \vec{h}_{a_{i}}^{k-1}\right) \end{aligned} \tag{9}
hdk=GRU(hdk−1,mdk)=GRU⎝⎛hdk−1,ai∈N(d)∑αdaik−1haik−1⎠⎞(9)
m
⃗
d
k
\vec m_d^k
mdk是检测节点
d
d
d第
k
k
k个迭代的信息。
α
d
a
i
k
−
1
\alpha_{d a_{i}}^{k-1}
αdaik−1是分配到每个关联节点
a
i
k
−
1
a_i^{k-1}
aik−1的注意力权重,计算如下:
α
d
a
i
k
−
1
=
exp
(
L
Re
L
U
(
a
⊤
[
W
d
e
t
h
h
⃗
d
k
−
1
∥
W
d
e
t
h
h
⃗
d
i
k
−
1
]
)
)
∑
d
j
∈
N
2
(
d
)
exp
(
L
ReL
U
(
a
T
[
W
d
e
t
h
h
⃗
d
k
−
1
∣
∣
W
d
e
t
h
h
⃗
d
j
k
−
1
]
)
)
(10)
\alpha_{d a_{i}}^{k-1}=\frac{\exp \left(L \operatorname{Re} L U\left(\mathbf{a}^{\top}\left[\mathbf{W}_{\mathrm{det}}^{\mathrm{h}} \vec{h}_{d}^{k-1} \| \mathbf{W}_{\mathrm{det}}^{\mathrm{h}} \vec{h}_{d_{i}}^{k-1}\right]\right)\right)}{\sum_{d_{j} \in \mathcal{N}^{2}(d)} \exp \left(L \operatorname{ReL} U\left(\mathbf{a}^{T}\left[\mathbf{W}_{\mathrm{det}}^{\mathrm{h}} \vec{h}_{d}^{k-1}|| \mathbf{W}_{\mathrm{det}}^{\mathrm{h}} \vec{h}_{d_{j}}^{k-1}\right]\right)\right)} \tag{10}
αdaik−1=∑dj∈N2(d)exp(LReLU(aT[Wdethhdk−1∣∣Wdethhdjk−1]))exp(LReLU(a⊤[Wdethhdk−1∥Wdethhdik−1]))(10)
其中
d
i
∈
N
(
a
i
)
,
d
i
≠
d
d_i \in N(a_i),d_i≠d
di∈N(ai),di=d,
N
2
(
⋅
)
N^2(·)
N2(⋅)表示二阶邻接节点,
L
R
e
L
U
LReLU
LReLU代表LeakyReLU。模型中使用三个注意头来实现多个注意。
输出函数:
o
d
k
o_{d}^{k}
odk代表隐藏状态通过一个简单的线性变换获得置信度输出:
o
d
k
=
W
d
e
t
o
h
⃗
d
k
+
b
⃗
d
e
t
o
(11)
o_{d}^{k}=\mathbf{W}_{d e t}^{o} \vec{h}_{d}^{k}+\vec{b}_{d e t}^{o}\tag{11}
odk=Wdetohdk+bdeto(11)
3.2 关联节点操作
关联节点 a a a和他相邻检测节点如下图所示:
初始化:
关联节点的隐藏状态为0向量: h ⃗ a 0 = 0 → (12) \vec{h}_{a}^{0}=\overrightarrow{0} \tag{12} ha0=0(12)
消息传递和节点更新函数:
使用两种更新函数进行对比,第一种基于和邻接节点的隐藏状态的差进行更新:
h
⃗
a
k
=
GRU
(
h
⃗
a
k
−
1
,
m
⃗
a
k
)
=
GRU
(
h
⃗
a
k
−
1
,
W
a
s
s
h
[
h
⃗
d
2
k
−
1
−
h
⃗
d
1
k
−
1
]
+
b
⃗
a
s
s
h
)
(13)
\begin{aligned} \vec{h}_{a}^{k} &=\operatorname{GRU}\left(\vec{h}_{a}^{k-1}, \vec{m}_{a}^{k}\right) \\ &=\operatorname{GRU}\left(\vec{h}_{a}^{k-1}, \mathbf{W}_{a s s}^{h}\left[\vec{h}_{d_{2}}^{k-1}-\vec{h}_{d_{1}}^{k-1}\right]+\vec{b}_{a s s}^{h}\right) \end{aligned} \tag{13}
hak=GRU(hak−1,mak)=GRU(hak−1,Wassh[hd2k−1−hd1k−1]+bassh)(13)
第二种基于concat连接进行更新:
h
⃗
a
k
=
GRU
(
h
⃗
a
k
−
1
,
m
⃗
a
k
)
=
GRU
(
h
⃗
a
k
−
1
,
W
a
s
s
h
[
h
⃗
d
1
k
−
1
∥
h
⃗
d
2
k
−
1
]
+
b
⃗
a
s
s
h
)
(14)
\begin{aligned} \vec{h}_{a}^{k} &=\operatorname{GRU}\left(\vec{h}_{a}^{k-1}, \vec{m}_{a}^{k}\right) \\ &=\operatorname{GRU}\left(\vec{h}_{a}^{k-1}, \mathbf{W}_{a s s}^{h}\left[\vec{h}_{d_{1}}^{k-1} \| \vec{h}_{d_{2}}^{k-1}\right]+\vec{b}_{a s s}^{h}\right) \end{aligned}\tag{14}
hak=GRU(hak−1,mak)=GRU(hak−1,Wassh[hd1k−1∥hd2k−1]+bassh)(14)
m
⃗
a
k
\vec{m}_{a}^{k}
mak表示关联节点
a
a
a在
k
k
k次迭代时的消息传递。
输出函数:
o a k = W a s s s o h ⃗ a k + b ⃗ a s s o (15) o_{a}^{k}=\mathbf{W}_{a s s s}^{o} \vec{h}_{a}^{k}+\vec{b}_{a s s}^{o} \tag{15} oak=Wasssohak+basso(15)
3.3训练损失
动态图 G = ( V , E ) G = (V,E) G=(V,E),进一步将顶点集合分割成两个不相交的集合。例如 V = D N ∪ A N V = DN ∪ AN V=DN∪AN 、 D N ∩ A N = ∅ DN ∩ AN = ∅ DN∩AN=∅,其中DN和AN分别代表检测节点集合和关联节点集合。
对于每个检测节点,使用二进制交叉熵损失:
L
b
c
e
;
D
N
=
−
1
∣
D
N
∣
∑
d
∈
D
N
(
y
d
log
(
Sigmoid
(
o
d
k
d
)
)
+
(
1
−
y
d
)
log
(
1
−
Sigmoid
(
o
d
k
d
)
)
)
(16)
\begin{array}{r} \mathcal{L}_{b c e ; D N}=-\frac{1}{|D N|} \sum_{d \in D N}\left(y_{d} \log \left(\operatorname{Sigmoid}\left(o_{d}^{k_{d}}\right)\right)\right. \\ \left.+\left(1-y_{d}\right) \log \left(1-\operatorname{Sigmoid}\left(o_{d}^{k_{d}}\right)\right)\right) \end{array} \tag{16}
Lbce;DN=−∣DN∣1∑d∈DN(ydlog(Sigmoid(odkd))+(1−yd)log(1−Sigmoid(odkd)))(16)
k
d
k_d
kd代表节点
d
d
d的最后一次迭代,且
y
d
=
{
1
,
if true positive
0
,
otherwise
(17)
y_{d}=\left\{\begin{array}{ll} 1, & \text { if true positive } \\ 0, & \text { otherwise } \end{array}\right. \tag{17}
yd={1,0, if true positive otherwise (17)
相同,关联节点也使用二进制交叉熵损失:
L
b
c
e
;
A
N
=
−
1
∣
A
N
∣
∑
a
∈
A
N
(
y
a
log
(
Sigmoid
(
o
a
k
a
)
)
+
(
1
−
y
a
)
log
(
1
−
Sigmoid
(
o
a
k
a
)
)
)
(18)
\begin{aligned} \mathcal{L}_{b c e ; A N}=-\frac{1}{|A N|} & \sum_{a \in A N}\left(y_{a} \log \left(\operatorname{Sigmoid}\left(o_{a}^{k_{a}}\right)\right)\right.\\ +&\left.\left(1-y_{a}\right) \log \left(1-\operatorname{Sigmoid}\left(o_{a}^{k_{a}}\right)\right)\right) \end{aligned} \tag{18}
Lbce;AN=−∣AN∣1+a∈AN∑(yalog(Sigmoid(oaka))(1−ya)log(1−Sigmoid(oaka)))(18)
k
a
k_a
ka代表节点
a
a
a的最后一次迭代,且
y
a
=
{
1
,
if
N
(
a
)
belongs to the same track
0
,
otherwise.
(19)
y_{a}=\left\{\begin{array}{ll} 1, & \text { if } \mathcal{N}(a) \text { belongs to the same track } \\ 0, & \text { otherwise. } \end{array}\right. \tag{19}
ya={1,0, if N(a) belongs to the same track otherwise. (19)
同样,对于每个竞争关联的关联节点,同样适用交叉熵损失:
L
c
e
;
A
N
=
−
1
∣
D
N
∣
∑
d
∈
D
N
(
1
∣
N
−
(
d
)
∣
∑
a
∈
N
−
(
d
)
y
a
log
(
Softmax
(
o
a
k
a
)
)
+
1
∣
N
+
(
d
)
∣
∑
a
∈
N
+
(
d
)
y
a
log
(
Softmax
(
o
a
k
a
)
)
)
(20)
\begin{aligned} \mathcal{L}_{c e ; A N} &=-\frac{1}{|D N|} \sum_{d \in D N}(\\ & \frac{1}{\left|\mathcal{N}^{-}(d)\right|} \sum_{a \in \mathcal{N}^{-}(d)} y_{a} \log \left(\operatorname{Softmax}\left(o_{a}^{k_{a}}\right)\right) \\ &\left.+\frac{1}{\left|\mathcal{N}^{+}(d)\right|} \sum_{a \in \mathcal{N}^{+}(d)} y_{a} \log \left(\operatorname{Softmax}\left(o_{a}^{k_{a}}\right)\right)\right) \end{aligned} \tag{20}
Lce;AN=−∣DN∣1d∈DN∑(∣N−(d)∣1a∈N−(d)∑yalog(Softmax(oaka))+∣N+(d)∣1a∈N+(d)∑yalog(Softmax(oaka))⎠⎞(20)
其中:
y
a
=
{
1
,
if
N
(
a
)
belongs to the same track
0
,
otherwise,
(21)
y_{a}=\left\{\begin{array}{ll} 1, & \text { if } \mathcal{N}(a) \text { belongs to the same track } \\ 0, & \text { otherwise, } \end{array}\right. \tag{21}
ya={1,0, if N(a) belongs to the same track otherwise, (21)
N
−
(
⋅
)
N−(·)
N−(⋅)代表过去时间步的所有邻居节点,
N
+
(
⋅
)
N+(·)
N+(⋅)代表未来时间步的邻居节点。
最终总损失为:
L
=
L
b
c
e
;
D
N
+
L
b
c
e
;
A
N
+
L
c
e
;
A
N
(22)
\mathcal{L}=\mathcal{L}_{b c e ; D N}+\mathcal{L}_{b c e ; A N}+\mathcal{L}_{c e ; A N} \tag{22}
L=Lbce;DN+Lbce;AN+Lce;AN(22)
四、实验
实验中两个超参,一个当前窗口大小(CWS)和一个保留窗口大小(RWS)。CWS确定离散时间步/帧的形式进行滚动窗口的大小,RWS确定一个未关联的检测节点在不再处于滚动窗口后,在动态图中保留的离散时间步数。
训练时,该实验不是对每个训练样本使用一个小批量的例子,而是对每个训练样本使用一个在MOT视频中根据CWS进行随机采样的连续小序列。
不同CWS,RWS和隐藏状态层数下在KITTI中车辆追踪的表现结果:
KITTI验证集上的消融实验:
KITTI车辆追踪结果对比:
KITTI行人追踪结果对比:
五、总结
由于利用图结构,时间和内存方面还要根据实际产生的图的大小来考虑。
提出一种基于无向图的追踪框架,用以表示追踪检测模式下的多时间步数据关联问题。这个框架下,单个检测和检测对之间的关联都在图中表示为节点。图是动态的,只有在基于滑动窗口下特定时间范围内的检测(及其关联)会处理。
这种端到端的基于窗口的方法,可以在竞争关联的时候,考虑两方甚至更久之前的检测。信息能够通过消息传递机制进行传播和存储,过去的错误可以通过动态图来进行修正。