前面讲到DeepSORT的核心工作流程:(DeepSORT工作流程)
预测(track)——>观测(detection+数据关联)——>更新
下面我们来看一下算法具体的实现细节吧~主要涉及到卡尔曼滤波怎么进行的预测、如何的进行数据关联
在DeepSORT中,卡尔曼滤波需要做这些事情:
(1)预测tracks在下一时刻的位置
(2)基于detection更新预测的位置
首先来看一下预测:基于之前的轨迹来预测当前时刻的轨迹
x ′ = F x {x}'=Fx x′=Fx
x x x为track在t-1时刻的状态向量,F为状态转移矩阵,该公式预测 t 时刻的状态向量 x ′ {x}' x′
此处的状态向量x:8个dim, x = [ c x , c y , r , h , c x ˙ , c y ˙ , r ˙ , h ˙ ] x=[cx,cy,r,h,\dot{cx},\dot{cy},\dot{r},\dot{h}] x=[cx,cy,r,h,cx˙,cy˙,r˙,h˙]
其中,cx,cy分别表示目标中心店的横坐标和纵坐标位置,r表示长宽比,h表示高,剩下四个分别是它们的导数(对应现实生活中的速度,初始为0),在状态估计中一般状态向量是需要由状态量跟它的导数构成的。
在这里,卡尔曼滤波进行预测时采用线性匀速模型,即认为框的移动和框的尺寸、形变的变化是线性匀速变化的。为什么是线性匀速呢?可以来看一下状态转移矩阵F的设置(图片来源右下角水印)
其中,dt表示当前帧和前帧之间的差,将右边的点乘公式展开的话其实不难发现, c x ′ = c x + d t ⋅ v x c{x}'=cx+dt\cdot vx cx′=cx+dt⋅vx,……依次展开,发现得到的每一个公式都是线性匀速的,所以说采用线性匀速的卡尔曼滤波模型。(至于为什么采用线性匀速,大概是因为难以估计接下来的运动到底怎么变化的,没有一个模型可以估计复杂的运动变化,所以干脆采用最简单的线性匀速,也正因如此,由于卡尔曼滤波预测模型是简单的线性匀速模型,所以它的预测大概率是不太准的)
介绍数据是如何进行关联之前,先来介绍一下协方差,因为要用到一个协方差的概念,先来看一下公式:
P ′ = F P F T + Q {P}'=FPF^{T}+Q P′=FPFT+Q
P为track在t-1时刻的协方差,Q为噪声矩阵,该公式预测 t 时刻的 P ′ {P}' P′
这个协方差是干嘛的呢?我们先来看一下数据关联的时候,是如何关联的。
看追踪和检测的Bbox的状态向量的前四维度 cx,cy,r,h的接近程度。通常来说上下帧之间移动距离不会相差太远,所以坐标越接近就越可能是同一个目标。
如何衡量两者之间的距离呢,第一反应可能就是欧式距离了。
但是,cx,cy,h是像素级的数值,而 r 宽高比 是一个比例,可能是零点几的数值,所以四者之间数量级不一样有差距,而且他们之间也不是相互独立的,存在相关性(比如r和h)。直接用欧氏距离进行计算的话不合适。
DeepSORT采取马氏距离来计算,用马氏距离就需要提供cx,cy,r,h的协方差矩阵(在卡尔曼滤波中,卡尔曼滤波的测量方程,测量空间的协方差矩阵,卡尔曼更新过程中把协方差矩阵提供给数据关联),所以,协方差是干嘛的?就是用来求取马氏距离的;协方差代表什么?表示目标位置信息的不确定性,由8x8的对角矩阵表示,矩阵中数字越大则表明不确定性越大,可以以任意值初始化。马氏距离通过计算检测位置和平均追踪位置之间的标准差将状态测量的不确定性进行了考虑。
马氏距离关联度量计算公式:
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)
d j d_{j} dj表示第j个detection Bbox的位置; y i y_{i} yi表示第i个追踪器对目标的预测位置; S i S_{i} Si表示detection Bbox和track Bbox之间的协方差矩阵;
对该公式的解读:两个向量 d j d_{j} dj, y i y_{i} yi求差,前面提到过由于相关性和数量级,需要利用协方差矩阵 S i S_{i} Si对其进行归一化,最终求得第i个跟踪和第j个检测之间的马氏距离。
如果某次关联的马氏距离小于指定的阈值,则设置运动状态的关联成功
t ( 1 ) t^{(1)} t(1)为阈值,作者设置 t ( 1 ) t^{(1)} t(1)=9.4877
以上仅测量空间马氏距离度量,但是DeepSORT不仅看框与框之间的距离,还要看框内的表观特征才能更好的进行关联匹配,上一篇文章提过IDswitch的问题,显然单纯用马氏距离度量框与框的接近度是远远不够的,依然不能解决IDswitch的问题,所以DeepSORT还引入了表观特征余弦距离度量。
表观特征余弦距离度量公式:
两个Bbox的向量要先提取特征向量,这里就用到了神经网络,由下图可以看出来这个特征提取网络还是很深的,即DeepSORT中的Deep由来,提取特征向量的网络结构如图所示:
网络中运用了很多残差网络结构,最终提取出dim=128的特征向量,通过l2正则化到一个单位球的超球面上(单位球,只不过因为是128维,所以实际是一个超球面,模长仍然是1)
通过 1 − r j T r k i 1-{r_{j}}^{T}r_{k}^{i} 1−rjTrki 求两个特征向量间的余弦距离, r j r_{j} rj对应第 j 个检测的特征向量, r k i r_{k}^{i} rki对应跟踪的特征向量,其中跟踪的特征向量是一个集合,保留过去成功跟踪的 k 次的feature。
表观特征余弦距离度量公式要做的事情就是计算第 i 个物体跟踪的所有特征向量和第 j 个物体检测的之间的最小余弦距离。
根据上述1.马氏距离 2. 表观余弦度量 可知,DeepSORT在数据关联中一共有两个代价,一个是马氏距离,一个是余弦距离,求解过程中要使两者都尽量的小,框也接近、特征也接近的话,就认为两个Bbox中是同一个东西。
综合 马氏距离和表观余弦度量的代价公式如下所示:
c i , j = λ d ( 1 ) ( i , j ) + ( 1 − λ ) d ( 2 ) ( i , j ) c_{i,j}=\lambda d^{(1)(i,j)}+(1-\lambda )d^{(2)}(i,j) ci,j=λd(1)(i,j)+(1−λ)d(2)(i,j)
(实际中代码使用lambda=0。为什么会这样呢?其实马氏距离只起了一个作用,就是剔除错误分配——剔除两个距离很远的框匹配成功的情况,因为距离很远的框即便匹配成功但是阈值判断条件是不符合的,所以通过马氏距离就能把这种失误情况给剔除。所以实际匈牙利算法(解决多个跟踪框和多个匹配框之间的最佳匹配问题)求解任务分配问题的过程中只考虑了余弦距离不再考虑马氏距离)
匈牙利算法主要用于解决分配问题,找到一个最优分配,使得完成所有任务的代价最小,又叫KM算法。
算法步骤(假设矩阵为NxN方阵):
1.对于矩阵的每一行,减去其中最小的元素
2.对于矩阵的每一列,减去其中最小的元素
3.用最少的水平线或垂直线覆盖矩阵中所有的0
4.如果线的数量等于N,则找到了最优分配,算法结束,否则进入步骤5
5.找到没有被任何线覆盖的最小元素,每个没被线覆盖的行减去这个元素,每个被线覆盖的列加上这个元素,返回步骤3。
匈牙利算法之所以能找到最优分配,就是因为它基于的原理:如果代价矩阵的某一行或某一列同时加上或减去某个数,则这个新的代价矩阵的最优分配仍然是原代价矩阵的最优分配。