Henriques, João F., et al. “High-speed tracking with kernelized
correlation filters.” Pattern Analysis and Machine Intelligence, IEEE
Transactions on 37.3 (2015): 583-596.
本文的跟踪方法效果甚好,速度奇高,思想和实现均十分简洁。其中利用循环矩阵进行快速计算的方法尤其值得学习。另外,作者在主页上十分慷慨地给出了各种语言的实现代码。
本文详细推导论文中的一系列步骤,包括论文中未能阐明的部分。请务必先参看这篇简介循环矩阵性质的博客。
思想
一般化的跟踪问题可以分解成如下几步:
- 在 I t I_t It帧中,在当前位置 p t p_t pt附近采样,训练一个回归器。这个回归器能计算一个小窗口采样的响应。
- 在 I t + 1 I_{t+1} It+1帧中,在前一帧位置 p t p_t pt附近采样,用前述回归器判断每个采样的响应。
- 响应最强的采样作为本帧位置 p t + 1 p_{t+1} pt+1。
循环矩阵表示图像块
在图像中,循环位移操作可以用来近似采样窗口的位移。
训练时,围绕着当前位置进行的一系列位移采样可以用二维分块循环矩阵
X
X
X表示,第ij块表示原始图像下移i行右移j列的结果。类似地,测试时,前一帧结果附近的一系列位移采样也可以用
X
X
X表示。
这样的
X
X
X可以利用傅里叶变换快速完成许多线性运算。
线性回归训练提速
此部分频繁用到了循环矩阵的各类性质,请参看这篇博客。
线性回归的最小二乘方法解为:
w
=
(
X
H
X
+
λ
I
)
−
1
X
H
y
w=\left( X^HX+\lambda I\right)^{-1}X^Hy
w=(XHX+λI)−1XHy
根据循环矩阵乘法性质,
X
H
X
X^HX
XHX的特征值为
x
^
⊙
x
^
∗
\hat x \odot \hat x^*
x^⊙x^∗。
I
I
I本身就是一个循环矩阵,其生成向量为
[
1
,
0
,
0...0
]
[1,0,0...0]
[1,0,0...0],这个生成向量的傅里叶变换为全1向量,记为
δ
\delta
δ。
w
=
(
F
d
i
a
g
(
x
^
⊙
x
^
∗
)
F
H
+
λ
F
d
i
a
g
(
δ
)
F
H
)
−
1
X
H
y
w=\left( Fdiag(\hat x \odot \hat x^*)F^H+\lambda Fdiag(\delta)F^H\right)^{-1}X^Hy
w=(Fdiag(x^⊙x^∗)FH+λFdiag(δ)FH)−1XHy
= ( F d i a g ( x ^ ⊙ x ^ ∗ + λ δ ) F H ) − 1 X H y =\left( Fdiag(\hat x \odot \hat x^*+\lambda\delta)F^H \right)^{-1}X^Hy =(Fdiag(x^⊙x^∗+λδ)FH)−1XHy
根据循环矩阵求逆性质,可以把矩阵求逆转换为特征值求逆。
w
=
F
⋅
d
i
a
g
(
1
x
^
⊙
x
^
∗
+
λ
δ
)
⋅
F
H
X
H
y
w=F\cdot diag\left(\frac{1}{\hat x \odot \hat x^*+\lambda\delta} \right) \cdot F^H X^H y
w=F⋅diag(x^⊙x^∗+λδ1)⋅FHXHy
w = F ⋅ d i a g ( 1 x ^ ⊙ x ^ ∗ + λ δ ) ⋅ F H ⋅ F d i a g ( x ^ ∗ ) F H ⋅ y w=F\cdot diag\left(\frac{1}{\hat x \odot \hat x^*+\lambda\delta} \right) \cdot F^H \cdot Fdiag(\hat{x}^*)F^H\cdot y w=F⋅diag(x^⊙x^∗+λδ1)⋅FH⋅Fdiag(x^∗)FH⋅y
利用
F
F
F的酉矩阵性质消元:
w
=
F
⋅
d
i
a
g
(
x
^
∗
x
^
⊙
x
^
∗
+
λ
δ
)
⋅
F
H
⋅
y
w=F\cdot diag\left(\frac{\hat{x}^*}{\hat x \odot \hat x^*+\lambda\delta} \right) \cdot F^H \cdot y
w=F⋅diag(x^⊙x^∗+λδx^∗)⋅FH⋅y
分号表示用1进行对位相除。
反用对角化性质:
F
d
i
a
g
(
y
)
F
H
=
C
(
F
−
1
(
y
)
)
Fdiag(y)F^H=C(\mathcal{F}^{-1}(y))
Fdiag(y)FH=C(F−1(y)),上式的前三项还是一个循环矩阵。
w
=
C
(
F
−
1
(
x
^
∗
x
^
⊙
x
^
∗
+
λ
δ
)
)
⋅
y
w=C\left( \mathcal{F}^{-1}\left( \frac{\hat{x}^*}{\hat x \odot \hat x^*+\lambda\delta}\right) \right) \cdot y
w=C(F−1(x^⊙x^∗+λδx^∗))⋅y
利用循环矩阵卷积性质
F
(
C
(
x
)
⋅
y
)
=
x
^
∗
⊙
y
^
\mathcal F(C(x)\cdot y)=\hat x ^* \odot \hat y
F(C(x)⋅y)=x^∗⊙y^:
F
(
w
)
=
(
x
^
∗
x
^
⊙
x
^
∗
+
λ
δ
)
∗
⊙
F
(
y
)
\mathcal{F}(w)=\left( \frac{\hat{x}^*}{\hat x \odot \hat x^*+\lambda\delta}\right )^* \odot \mathcal F(y)
F(w)=(x^⊙x^∗+λδx^∗)∗⊙F(y)
由于
x
^
⊙
x
^
∗
\hat x \odot \hat x^*
x^⊙x^∗的每个元素都是实数,所以共轭不变:
F ( w ) = x ^ x ^ ⊙ x ^ ∗ + λ δ ⊙ F ( y ) = x ^ ⊙ y ^ x ^ ⊙ x ^ ∗ + λ δ \mathcal{F}(w)=\frac{\hat{x}}{\hat x \odot \hat x^*+\lambda\delta} \odot \mathcal F(y)=\frac{\hat{x}\odot \hat{y}}{\hat x \odot \hat x^*+\lambda\delta} F(w)=x^⊙x^∗+λδx^⊙F(y)=x^⊙x^∗+λδx^⊙y^
论文中,最后这一步推导的分子部分写成 x ^ ∗ ⊙ y ^ \hat x ^* \odot \hat y x^∗⊙y^,是错误的。但代码中没有涉及。
线性回归系数 ω \omega ω可以通过向量的傅里叶变换和对位乘法计算得到。
核回归训练提速
不熟悉核方法的同学可以参看这篇博客的简单说明。核回归方法的回归式为:
f
(
z
)
=
α
T
κ
(
z
)
f(z)=\alpha^T \kappa(z)
f(z)=αTκ(z)
其中
κ
(
z
)
\kappa(z)
κ(z)表示测试样本
z
z
z和所有训练样本的核函数。参数有闭式解:
α
=
(
K
+
λ
I
)
−
1
y
\alpha = \left( K + \lambda I\right)^{-1}y
α=(K+λI)−1y
K
K
K为所有训练样本的核相关矩阵:
K
i
j
=
κ
(
x
i
,
x
j
)
K_{ij}=\kappa(x_i,x_j)
Kij=κ(xi,xj)。如果核函数选择得当,使得
x
x
x内部元素顺序更换不影响核函数取值,则可以保证
K
K
K也是循环矩阵。以下核都满足这样的条件:
设核相关矩阵的生成向量是
k
k
k。推导和之前线性回归的套路非常类似:
α
=
(
F
d
i
a
g
(
k
^
)
F
H
+
F
d
i
a
g
(
λ
δ
)
F
H
)
−
1
y
=
(
F
d
i
a
g
(
k
^
+
λ
δ
)
F
H
)
−
1
y
\alpha = \left( Fdiag(\hat k)F^H+Fdiag(\lambda\delta)F^H \right)^{-1}y=\left( Fdiag(\hat k + \lambda\delta)F^H \right)^{-1}y
α=(Fdiag(k^)FH+Fdiag(λδ)FH)−1y=(Fdiag(k^+λδ)FH)−1y
= F d i a g ( 1 k ^ + λ δ ) F H y = C ( F − 1 ( 1 k ^ + λ δ ) ) y =Fdiag\left(\frac{1}{\hat k + \lambda\delta}\right)F^Hy=C\left( \mathcal F^{-1} \left(\frac{1}{\hat k + \lambda\delta} \right) \right)y =Fdiag(k^+λδ1)FHy=C(F−1(k^+λδ1))y
利用循环矩阵卷积性质
F
(
C
(
x
)
⋅
y
)
=
x
^
∗
⊙
y
^
\mathcal F(C(x)\cdot y)=\hat x ^* \odot \hat y
F(C(x)⋅y)=x^∗⊙y^:
α
^
=
(
1
k
^
+
λ
δ
)
∗
⊙
y
^
\hat{\alpha}=\left( \frac{1}{\hat k + \lambda\delta} \right)^* \odot \hat y
α^=(k^+λδ1)∗⊙y^
这里
k
k
k是核相关矩阵的第一行,表示原始生成向量
x
0
x^0
x0和移位了
i
i
i的向量
x
i
x^i
xi的核函数。考察其处于对称位置上的两个元素:
k
i
=
κ
(
x
0
,
x
i
)
,
k
N
−
i
=
κ
(
x
0
,
x
N
−
i
)
k_i=\kappa(x^0,x^i), k_{N-i}=\kappa(x^0,x^{N-i})
ki=κ(x0,xi),kN−i=κ(x0,xN−i)
两者都是同一个向量和自身位移结果进行运算。因为所有涉及到的核函数都只和位移的绝对值有关,所以 k i = k N − i k_i=k_{N-i} ki=kN−i,即 k k k是对称向量。
举例: x 0 = [ 1 , 2 , 3 , 4 ] x^0=[1,2,3,4] x0=[1,2,3,4], x 1 = [ 4 , 1 , 2 , 3 ] x^1=[4,1,2,3] x1=[4,1,2,3], x 3 = [ 2 , 3 , 4 , 1 ] x^3=[2,3,4,1] x3=[2,3,4,1]。使用多项式核 κ ( x , y ) = x T y \kappa(x,y)=x^Ty κ(x,y)=xTy,容易验证 κ ( x 0 , x 1 ) = κ ( x 0 , x 3 ) \kappa(x^0,x^1)=\kappa(x^0,x^3) κ(x0,x1)=κ(x0,x3)。
对称向量的傅里叶变换为实数,有:
α ^ = ( 1 k ^ + λ δ ) ⊙ y ^ = y ^ k ^ + λ δ \hat{\alpha}=\left( \frac{1}{\hat k + \lambda\delta} \right) \odot \hat y=\frac{\hat y}{\hat k + \lambda\delta} α^=(k^+λδ1)⊙y^=k^+λδy^
论文中,利用 k k k的对称性消除共轭的步骤没有提及。
线性回归系数 α \alpha α可以通过向量的傅里叶变换和对位乘法计算得到。
核回归检测提速
所有待检测样本和所有训练样本的核相关矩阵为 K K K,每一列对应一个待测样本。可以一次计算所有样本的响应( N × 1 N\times 1 N×1向量):
y ′ = K T α y'=K^T\alpha y′=KTα
利用循环矩阵的转置性质性质,
C
(
k
)
C^(k)
C(k)的特征值为
k
^
∗
\hat k^*
k^∗:
y
′
=
C
(
k
)
T
⋅
α
=
C
(
k
^
∗
)
⋅
α
=
k
∗
∗
α
y'=C(k)^T\cdot \alpha=C(\hat k ^*)\cdot \alpha =k^**\alpha
y′=C(k)T⋅α=C(k^∗)⋅α=k∗∗α
利用循环矩阵的卷积性质:
y
′
=
(
k
∗
)
∗
α
=
k
∗
α
y'=(k^*)*\alpha=k*\alpha
y′=(k∗)∗α=k∗α
两边傅里叶变换:
y
′
^
=
k
^
⊙
α
^
\hat {y'}=\hat k \odot \hat \alpha
y′^=k^⊙α^
论文中,利用转置消除共轭的步骤没有提及。
所有侯选块的检测响应可以通过向量的傅里叶变换和对位乘法计算得到。
核相关矩阵计算提速
无论训练还是检测,都需要计算核相关矩阵 K K K的生成向量 k k k。除了直接计算每一个核函数,在某些特定的核函数下可以进一步加速。
多项式核
κ ( x , y ) = f ( x T y ) \kappa(x,y)=f\left( x^Ty\right) κ(x,y)=f(xTy)
其中
f
f
f为多项式函数。写成矩阵形式:
K
=
f
(
X
T
Y
)
K=f\left( X^T Y\right)
K=f(XTY)
f
f
f在矩阵的每个元素上单独进行。根据循环矩阵性质,
X
T
Y
X^TY
XTY也是一个循环矩阵,其生成向量为
F
−
1
(
y
^
⊙
x
^
∗
)
\mathcal F^{-1}(\hat y\odot \hat x^*)
F−1(y^⊙x^∗)。所以核相关矩阵的生成向量为:
k
=
f
(
F
−
1
(
y
^
⊙
x
^
∗
)
)
k=f\left( \mathcal F^{-1}(\hat y\odot \hat x^*) \right)
k=f(F−1(y^⊙x^∗))
RBF核
κ
(
x
,
y
)
=
f
(
∣
∣
x
−
y
∣
∣
2
)
\kappa(x,y)=f(||x-y||^2)
κ(x,y)=f(∣∣x−y∣∣2)
其中
f
f
f是线性函数。简单展开:
κ
(
x
,
y
)
=
f
(
∣
∣
x
−
y
∣
∣
2
)
=
f
(
∣
∣
x
∣
∣
2
+
∣
∣
y
∣
∣
2
+
2
x
T
y
)
\kappa(x,y)=f(||x-y||^2)=f(||x||^2+||y||^2+2x^Ty)
κ(x,y)=f(∣∣x−y∣∣2)=f(∣∣x∣∣2+∣∣y∣∣2+2xTy)
由于
X
X
X中的所有
x
x
x都通过循环移位获得,故
∣
∣
x
∣
∣
2
||x||^2
∣∣x∣∣2对于所有
x
x
x是常数,同理
∣
∣
y
∣
∣
2
||y||^2
∣∣y∣∣2也是。所以核相关矩阵的生成向量为:
k
=
f
(
∣
∣
x
∣
∣
2
+
∣
∣
y
∣
∣
2
+
F
−
1
(
y
^
⊙
x
^
∗
)
)
k=f\left( ||x||^2 + ||y||^2+\mathcal F^{-1}(\hat y\odot \hat x^*) \right)
k=f(∣∣x∣∣2+∣∣y∣∣2+F−1(y^⊙x^∗))
其他核
有一些核函数,虽然能保证 K K K是循环矩阵,但无法直接拆解出其特征值,快速得到生成向量。比如Hellinger核: ∑ i x i y i \sum_i\sqrt{x_iy_i} ∑ixiyi,Intersection核: ∑ i min ( x i , y i ) \sum_i\min(x_i,y_i) ∑imin(xi,yi)。
多通道
在多通道情况下(例如使用了HOG特征),生成向量
x
x
x变成
M
×
L
M\times L
M×L,其中
M
M
M是样本像素数,
L
L
L是特征维度。在上述所有计算中,需要更改的只有向量的内积:
x
T
y
=
∑
l
(
x
l
)
T
y
l
x^Ty=\sum_l(x^l)^Ty^l
xTy=l∑(xl)Tyl
注:非常感谢GX1415926535和大家的帮助,发现原文一处错误。(21)式中不应有转置,应为:
f ( z ) = K z α f(z)=K^z\alpha f(z)=Kzα