关于KCF 在网上的文章已经很多了,这篇文章就从我自己的理解分析的角度 来详细分析其原理以及代码
KCF原理
首先,我们假设训练的样本集为 ( x i , y i ) \left( \boldsymbol{x}_{\boldsymbol{i}},\boldsymbol{y}_{\boldsymbol{i}} \right) (xi,yi),那么其线性回归函数 f ( x i ) = ω T x i \boldsymbol{f}\left( \boldsymbol{x}_{\boldsymbol{i}} \right) =\boldsymbol{\omega }^{\boldsymbol{T}}\boldsymbol{x}_{\boldsymbol{i}} f(xi)=ωTxi ,这其中, ω \boldsymbol{\omega } ω是列向量表示的权重系数,可以通过最小二乘法来求解, min ω ∑ i ( f ( x i ) − y i ) 2 + λ ∣ ∣ ω ∣ ∣ 2 \underset{\boldsymbol{\omega }}{\min}\sum_{\boldsymbol{i}}{\left( \boldsymbol{f}\left( \boldsymbol{x}_{\boldsymbol{i}} \right) -\boldsymbol{y}_{\boldsymbol{i}} \right) ^2+\boldsymbol{\lambda }}||\boldsymbol{\omega }||^2 ωmini∑(f(xi)−yi)2+λ∣∣ω∣∣2
目标是最小化我们的采样数据 x i \boldsymbol{x}_{\boldsymbol{i}} xi的计算标签 f ( x i ) \boldsymbol{f}\left( \boldsymbol{x}_{\boldsymbol{i}} \right) f(xi)与下一帧真实目标位置的真实标签 y i \boldsymbol{y}_{\boldsymbol{i}} yi(回归目标)的距离,我计算出来的标签越像真实标签,说明我找到的下一帧的位置就离他真实的位置就越近,写矩阵的形式就是: min ω ∣ ∣ X w − y ∣ ∣ 2 + λ ∣ ∣ ω ∣ ∣ 2 \underset{\boldsymbol{\omega }}{\min}||\boldsymbol{X}_{\boldsymbol{w}}-\boldsymbol{y}||^2+\boldsymbol{\lambda }||\boldsymbol{\omega }||^2 ωmin∣∣Xw−y∣∣2+λ∣∣ω∣∣2
其中 X = [ x 1 , x 2 , ⋯ , x n ] T \boldsymbol{X}=\left[ \boldsymbol{x}_1,\boldsymbol{x}_2,\cdots ,\boldsymbol{x}_{\boldsymbol{n}} \right] ^{\boldsymbol{T}} X=[x1,x2,⋯,xn]T的每一行表示一个向量, y \boldsymbol{y} y是列向量,每个元素对应一个样本的标签,于是令导数为0,可求得: ω = ( X T X + λ I ) − 1 X T y \boldsymbol{\omega }=\left( \boldsymbol{X}^{\boldsymbol{T}}\boldsymbol{X}+\boldsymbol{\lambda I} \right) ^{-1}\boldsymbol{X}^{\boldsymbol{T}}\boldsymbol{y} ω=(XTX+λI)−1XTy
因为后面实在傅里叶域内计算,牵涉到复数矩阵,所以我们将结果都统一写成复数域中形式: ω = ( X H X + λ I ) − 1 X H y \boldsymbol{\omega }=\left( \boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{X}+\boldsymbol{\lambda I} \right) ^{-1}\boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{y} ω=(XHX+λI)−1XHy
其中
X
H
\boldsymbol{X}^{\boldsymbol{H}}
XH表示复共轭转置矩阵。这里我们看到在求
ω
\boldsymbol{\omega }
ω得最小值的时候有矩阵求逆的操作,这使得计算量比较大。然而根据之前说的
X
\boldsymbol{X}
X 是一个循环矩阵,形式为:
将矩阵进行傅立叶变换后,循环矩阵有一个性质:
X
=
F
diag
(
x
^
)
F
H
\boldsymbol{X}=\boldsymbol{F}\text{diag}\left( \boldsymbol{\hat{x}} \right) \boldsymbol{F}^{\boldsymbol{H}}
X=Fdiag(x^)FH
即一个循环矩阵可以用它的第一行的向量进行傅里叶变换之后表示,
x
^
\boldsymbol{\hat{x}}
x^表示对向量
x
\boldsymbol{x}
x进行了傅里叶变换,然后就可以发现一个循环矩阵可以转换成用一个向量来表示。将
X
=
F
diag
(
x
^
)
F
H
\boldsymbol{X}=\boldsymbol{F}\text{diag}\left( \boldsymbol{\hat{x}} \right) \boldsymbol{F}^{\boldsymbol{H}}
X=Fdiag(x^)FH式带入
ω
=
(
X
H
X
+
λ
I
)
−
1
X
H
y
\boldsymbol{\omega }=\left( \boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{X}+\boldsymbol{\lambda I} \right) ^{-1}\boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{y}
ω=(XHX+λI)−1XHy 式化简:
X
H
X
=
F
diag
(
x
^
∗
)
diag
(
x
^
)
F
H
\boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{X}=\boldsymbol{F}\text{diag}\left( \boldsymbol{\hat{x}}^* \right) \text{diag}\left( \boldsymbol{\hat{x}} \right) \boldsymbol{F}^{\boldsymbol{H}}
XHX=Fdiag(x^∗)diag(x^)FH
X H X = F diag ( x ^ ∗ ⊙ x ^ ) F H \boldsymbol{X}^{\boldsymbol{H}}\boldsymbol{X}=\boldsymbol{F}\text{diag}\left( \boldsymbol{\hat{x}}^*\odot \boldsymbol{\hat{x}} \right) \boldsymbol{F}^{\boldsymbol{H}} XHX=Fdiag(x^∗⊙x^)FH
ω ^ = diag ( x ^ ∗ x ^ ∗ ⊙ x ^ + λ ) y ^ \boldsymbol{\hat{\omega}}=\text{diag}\left( \frac{\boldsymbol{\hat{x}}^*}{\boldsymbol{\hat{x}}^*\odot \boldsymbol{\hat{x}}+\boldsymbol{\lambda }} \right) \boldsymbol{\hat{y}} ω^=diag(x^∗⊙x^+λx^∗)y^
ω ^ = x ^ ∗ ⊙ y ^ x ^ ∗ ⊙ x ^ + λ \boldsymbol{\hat{\omega}}=\frac{\boldsymbol{\hat{x}}^*\odot \boldsymbol{\hat{y}}}{\boldsymbol{\hat{x}}^*\odot \boldsymbol{\hat{x}}+\boldsymbol{\lambda }} ω^=x^∗⊙x^+λx^∗⊙y^
其中
ω
^
\boldsymbol{\hat{\omega}}
ω^ 的意思就是进行了傅里叶转换,这样就从一个矩阵的运算换到了向量的运算。减少了求逆的操作。
但是我们大部分情况下都是面对的是非线性问题,这里就需要高维求解和核函数的概念
在求解非线性回归中的
ω
\boldsymbol{\omega }
ω时,如果将数据
x
i
\boldsymbol{x}_{\boldsymbol{i}}
xi 映射到高维空间,那么就可以将非线性回归问题转换为线性求解,同时需要找到一个非线性映射函数
φ
(
x
i
)
\boldsymbol{\varphi }\left( \boldsymbol{x}_{\boldsymbol{i}} \right)
φ(xi),这时的
ω
\boldsymbol{\omega }
ω可以表示为:
ω
=
∑
i
α
i
φ
(
x
i
)
\boldsymbol{\omega }=\sum_{\boldsymbol{i}}{\boldsymbol{\alpha }_{\boldsymbol{i}}\boldsymbol{\varphi }\left( \boldsymbol{x}_{\boldsymbol{i}} \right)}
ω=i∑αiφ(xi)
其中
φ
(
x
i
)
\boldsymbol{\varphi }\left( \boldsymbol{x}_{\boldsymbol{i}} \right)
φ(xi)表示将
x
\boldsymbol{x}
x映射到高位空间的函数。
那我们这里 的目标函数 就可以表示成:
f
(
z
)
=
ω
T
z
=
∑
i
=
1
n
α
i
κ
(
z
,
x
i
)
\boldsymbol{f}\left( \boldsymbol{z} \right) =\boldsymbol{\omega }^{\boldsymbol{T}}\boldsymbol{z}=\sum_{\boldsymbol{i}=1}^{\boldsymbol{n}}{\boldsymbol{\alpha }_{\boldsymbol{i}}\boldsymbol{\kappa }\left( \boldsymbol{z},\boldsymbol{x}_{\boldsymbol{i}} \right)}
f(z)=ωTz=i=1∑nαiκ(z,xi)
其中
κ
\boldsymbol{\kappa }
κ表示核函数的定义运算为:
φ
T
(
x
)
φ
(
x
′
)
=
κ
(
x
,
x
′
)
\boldsymbol{\varphi }^{\boldsymbol{T}}\left( \boldsymbol{x} \right) \boldsymbol{\varphi }\left( \boldsymbol{x}' \right) =\boldsymbol{\kappa }\left( \boldsymbol{x},\boldsymbol{x}' \right)
φT(x)φ(x′)=κ(x,x′)
最后可以解得
α
=
(
K
+
λ
I
)
−
1
y
\boldsymbol{\alpha }=\left( \boldsymbol{K}+\boldsymbol{\lambda I} \right) ^{-1}\boldsymbol{y}
α=(K+λI)−1y
其中,
K
\boldsymbol{K}
K为核函数的矩阵表示,
K
\boldsymbol{K}
K也是一个循环矩阵,可以表示成
K
=
C
(
k
x
x
)
\boldsymbol{K}=\boldsymbol{C}\left( \boldsymbol{k}^{\boldsymbol{xx}} \right)
K=C(kxx) ,
k
x
x
\boldsymbol{k}^{\boldsymbol{xx}}
kxx是核函数矩阵
K
\boldsymbol{K}
K的第一行向量
通过傅里叶对角化的性质
K
z
=
C
(
k
x
z
)
\boldsymbol{K}^{\boldsymbol{z}}=\boldsymbol{C}\left( \boldsymbol{k}^{\boldsymbol{xz}} \right)
Kz=C(kxz)进行简化,得到下式:
α
^
=
y
^
k
^
x
x
+
λ
\boldsymbol{\hat{\alpha}}=\frac{\boldsymbol{\hat{y}}}{\boldsymbol{\hat{k}}^{\boldsymbol{xx}}+\boldsymbol{\lambda }}
α^=k^xx+λy^
这里
k
^
x
x
\boldsymbol{\hat{k}}^{\boldsymbol{xx}}
k^xx 代表
K
\boldsymbol{K}
K矩阵的第一行元素的傅里叶变换。这样式子
f
(
z
)
=
ω
T
z
=
∑
i
=
1
n
α
i
κ
(
z
,
x
i
)
\boldsymbol{f}\left( \boldsymbol{z} \right) =\boldsymbol{\omega }^{\boldsymbol{T}}\boldsymbol{z}=\sum_{\boldsymbol{i}=1}^{\boldsymbol{n}}{\boldsymbol{\alpha }_{\boldsymbol{i}}\boldsymbol{\kappa }\left( \boldsymbol{z},\boldsymbol{x}_{\boldsymbol{i}} \right)}
f(z)=ωTz=i=1∑nαiκ(z,xi)
由于
K
z
=
C
(
k
x
z
)
\boldsymbol{K}^{\boldsymbol{z}}=\boldsymbol{C}\left( \boldsymbol{k}^{\boldsymbol{xz}} \right)
Kz=C(kxz) ,其中
C
(
x
)
\boldsymbol{C}\left( \boldsymbol{x} \right)
C(x)表示由向量
x
\boldsymbol{x}
x循环移位得到的矩阵,
K
z
\boldsymbol{K}^{\boldsymbol{z}}
Kz是所有训练样本和候补patch之间的核矩阵,可以表示成:
f
(
z
)
=
(
K
z
)
T
α
\boldsymbol{f}\left( \boldsymbol{z} \right) =\left( \boldsymbol{K}^{\boldsymbol{z}} \right) ^{\boldsymbol{T}}\boldsymbol{\alpha }
f(z)=(Kz)Tα
傅里叶变换后的形式为:
f ^ ( z ) = k ^ x z ⊙ α ^ \boldsymbol{\hat{f}}\left( \boldsymbol{z} \right) =\boldsymbol{\hat{k}}^{\boldsymbol{xz}}\odot \boldsymbol{\hat{\alpha}} f^(z)=k^xz⊙α^
现在就剩讨论一下 k \boldsymbol{k} k 的形式,如果 k \boldsymbol{k} k 是线性核的话就可以转换成我们在讨论线性问题时求得的w的傅里叶转换之后的形式。本篇文章中用的是高斯核,形式如下:
k x x ′ = exp ( − 1 σ 2 ( ∣ ∣ x ∣ ∣ 2 + ∣ ∣ x ′ ∣ ∣ 2 − 2 F − 1 ( x ^ ∗ ⊙ x ^ ′ ) ) ) \boldsymbol{k}^{\boldsymbol{xx}'}=\exp \left( -\frac{1}{\boldsymbol{\sigma }^2}\left( ||\boldsymbol{x}||^2+||\boldsymbol{x}'||^2-2\mathcal{F}^{-1}\left( \boldsymbol{\hat{x}}^*\odot \boldsymbol{\hat{x}}' \right) \right) \right) kxx′=exp(−σ21(∣∣x∣∣2+∣∣x′∣∣2−2F−1(x^∗⊙x^′)))
实验步骤
代码分析
首先,读取视频帧,并判断是否读取成功
然后,用鼠标框选需要跟踪的目标
如果目标很大,就将其缩小,并且将我们自己画的框向外扩展1.5倍作为window_sz,我们在window_sz内进行寻找目标
再创建高斯形状的回归标签
这里最初的标签是这样的
将峰值移动到(0,0)的位置,主要作用是便于计算,因为峰值在(0,0)的位置的话,根据目标的坐标就可以很轻易的得出目标移动的方向和距离
再存储预先计算的余弦窗口
这里的余弦窗是这样的
,
再将相应的参数写入:
至此,以上只是前期准备工作,接下来进入真正的跟踪过程