目标跟踪VOT-ECO中,cubic_spline_fourier函数推导与源码解释

读visual object tracking -- eco (Efficient Convolution Operator (ECO) tracker.) 算法的源码,一时好奇,想自己推导一下这个cubic spline kernel的计算函数。

作者:Martin-danelljan 原项目地址:https://github.com/martin-danelljan/ECO

原来的matlab是这样写的,

function bf = cubic_spline_fourier(f, a)

% The continuous Fourier transform of a cubic spline kernel.

bf = -(- 12*a + 12*exp(-pi*f*2i) + 12*exp(pi*f*2i) + 6*a*exp(-pi*f*4i) + ...
    6*a*exp(pi*f*4i) + f.*(pi*exp(-pi*f*2i)*12i) - f.*(pi*exp(pi*f*2i)*12i) + ...
    a*f.*(pi*exp(-pi*f*2i)*16i) - a*f.*(pi*exp(pi*f*2i)*16i) + ...
    a*f.*(pi*exp(-pi*f*4i)*4i) - a*f.*(pi*exp(pi*f*4i)*4i) - 24)./(16*f.^4*pi^4);

bf(f == 0) = 1;

首先是自己走了些弯路,不知道作者到底用的哪个cubic spline, 找了一通,最后发现是这个函数(很普通,但没找到之前让好一番好猜,再后来才发现作者提供的supplementary material中有说明),详情可参考wikimedia :

https://en.wikipedia.org/wiki/Bicubic_interpolation


f(x) =\left\{\begin{matrix} 0 & x<-2 \\ -a x^3-5 a x^2-8 a x-4 a & -2<x\leq -1 \\ (-a-2) x^3-(a+3) x^2+1 & -1<x\leq 0 \\ (a+2) x^3-(a+3) x^2+1 & 0<x\leq 1 \\ a x^3-5 a x^2+8 a x-4 a & 1<x\leq 2 \\ 0 & x>2 \end{matrix}\right.

对该函数作傅立叶变换,得到
\frac{\sqrt{\frac{2}{\pi }} e^{-2 i t} \left(a \left(-1+e^{2 i t}\right) \left(4 i e^{i t} t+i t+i e^{2 i t} (t+3 i)+3\right)+3 e^{i t} \left(-1+e^{i t}\right) \left(i t+i e^{i t} (t+2 i)+2\right)\right)}{t^4}

表达式有点乱,因为最终和作者给出的相差一个(不影响计算结果的)系数,我这里把这个系数去掉

\sqrt{\frac{1}{2\pi }}

显然前面的t相当于我们平常说的2\omega t,代进去,再整理一下顺序就和作者提供的完全一样了 :-),

\frac{1}{16\pi^4t^4}(-24 - 12 a + 12 e^{_{-2\pi i t}} + 12e^{_{2\pi i t}} + 6a e^{_{-4\pi i t}} + 6a e^{_{4\pi i t}} + 12\pi ite^{_{-2\pi i t}} - 12\pi it e^{_{2\pi i t}} + 16\pi ait e^{_{-2\pi i t}} - 16\pi ait e^{_{2\pi i t}} + 4\pi ait e^{_{-4\pi i t}} - 4\pi ait e^{_{4\pi i t}})

另外,作者最后面加了一个负号,我看了下,如果没有这个负号,所以结果都是负值,所以必须转成正数。
其实在计算时,最后只用到了函数的实部,取出来直接计算的话就是这样的

\frac{1}{16\pi^4t^4}(-12a + 24cos(2\pi t) + 12a cos(4\pi t)+ 24\pi t sin(2t\pi) + 32a\pi t sin(2t\pi) + 8a\pi t sin(4t\pi) - 24)

如果要看C++源码的话,可以去这里看:https://github.com/nicewsyly/ECO/blob/master/ECO/interpolator.cpp
这里我把他贴出来,如下

cv::Mat interpolator::cubic_spline_fourier(cv::Mat f, float a)
{
	if (f.empty())
		return cv::Mat();

	cv::Mat bf(f.size(), CV_32FC1), temp1(f.size(), CV_32FC1), temp2(f.size(), CV_32FC1),
		temp3(f.size(), CV_32FC1), temp4(f.size(), CV_32FC1);
	std::transform(f.begin<float>(), f.end<float>(), temp1.begin<float>(), mat_cos2);
	std::transform(f.begin<float>(), f.end<float>(), temp2.begin<float>(), mat_cos4);

	std::transform(f.begin<float>(), f.end<float>(), temp3.begin<float>(), mat_sin2);
	std::transform(f.begin<float>(), f.end<float>(), temp4.begin<float>(), mat_sin4);

	bf = -1 * (-12 * a * cv::Mat::ones(f.size(), CV_32FC1) + 24 * temp1 +
		12 * a * temp2 + CV_PI * 24 * f.mul(temp3) +
		CV_PI * a * 32 * f.mul(temp3) + CV_PI * 8 * a * f.mul(temp4) -
		24 * cv::Mat::ones(f.size(), CV_32FC1));

	cv::Mat L(f.size(), CV_32FC1);
	cv::pow(f, 4, L);
	cv::divide(bf, 16 * L * cv::pow(CV_PI, 4), bf);
	bf.at<float>(bf.rows / 2, bf.cols / 2) = 1;

	return bf;
}

嗯,希望看到的童鞋可以省点时间。

Latex写长公式好累,眼都花了!

posted @ 2018-10-12 13:50  SpaceVision  阅读(37)  评论(0编辑  收藏  举报