int cols;
int rows;
int n_channels;
+ int n_scales = 1;
ComplexMat_() : cols(0), rows(0), n_channels(0) {}
ComplexMat_(int _rows, int _cols, int _n_channels) : cols(_cols), rows(_rows), n_channels(_n_channels)
p_data.resize(n_channels*cols*rows);
}
+
//assuming that mat has 2 channels (real, img)
ComplexMat_(const cv::Mat & mat) : cols(mat.cols), rows(mat.rows), n_channels(1)
{
{
p_data = data;
}
+
+ ComplexMat_(int _rows, int _cols, int _n_channels,int _n_scales) : cols(_cols), rows(_rows), n_channels(_n_channels), n_scales(_n_scales)
+ {
+ p_data.resize(n_channels*cols*rows);
+ }
// cv::Mat API compatibility
cv::Size size() { return cv::Size(cols, rows); }
int channels() { return n_channels; }
+ int channels() const { return n_channels; }
//assuming that mat has 2 channels (real, imag)
void set_channel(int idx, const cv::Mat & mat)
return matn_mat1_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs *= c_rhs; }, rhs);
}
+ //multiplying element-wise multichannel by one channel mats (rhs mat is with multiple channel)
+ ComplexMat_<T> mul2(const ComplexMat_<T> & rhs) const
+ {
+ return matn_mat2_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs *= c_rhs; }, rhs);
+ }
+
//text output
friend std::ostream & operator<<(std::ostream & os, const ComplexMat_<T> & mat)
{
return result;
}
+ ComplexMat_<T> matn_mat2_operator(void (*op)(std::complex<T> & c_lhs, const std::complex<T> & c_rhs), const ComplexMat_<T> & mat_rhs) const
+ {
+ assert(mat_rhs.n_channels == n_channels/n_scales && mat_rhs.cols == cols && mat_rhs.rows == rows);
+
+ int n_channels_per_scale = n_channels/n_scales;
+ int scale_offset = n_channels_per_scale*rows*cols;
+ ComplexMat_<T> result = *this;
+ for (int i = 0; i < n_scales; ++i) {
+ for (int j = 0; j < n_channels_per_scale; ++j) {
+ auto lhs = result.p_data.begin()+(j*rows*cols)+(i*scale_offset);
+ auto rhs = mat_rhs.p_data.begin()+(j*rows*cols);
+ for ( ; lhs != result.p_data.begin()+((i+1)*rows*cols)+(i*scale_offset); ++lhs, ++rhs)
+ op(*lhs, *rhs);
+ }
+ }
+
+ return result;
+ }
ComplexMat_<T> mat_const_operator(const std::function<void(std::complex<T> & c_rhs)> & op) const
{
ComplexMat_<T> result = *this;
#include <omp.h>
#endif
-#ifdef ASYNC
+#if defined(ASYNC) && !defined(CUFFTW)
#define FFTW_PLAN_WITH_THREADS() fftw_plan_with_nthreads(m_num_threads);
-#elif OPENMP
+#elif defined(OPENMP) && !defined(CUFFTW)
#define FFTW_PLAN_WITH_THREADS() fftw_plan_with_nthreads(omp_get_max_threads());
#else
#define FFTW_PLAN_WITH_THREADS()
#else
std::cout << "FFT: cuFFTW" << std::endl;
#endif
-
+ //FFT forward one scale
{
cv::Mat in_f = cv::Mat::zeros(m_height, m_width, CV_32FC1);
ComplexMat out_f(m_height, m_width / 2 + 1, 1);
reinterpret_cast<fftwf_complex*>(out_f.get_p_data()),
FFTW_MEASURE);
}
-
+ //FFT forward all scales
+ if(num_of_scales > 1)
+ {
+ cv::Mat in_f_all = cv::Mat::zeros(m_height*m_num_of_scales, m_width, CV_32FC1);
+ ComplexMat out_f_all(m_height, m_width / 2 + 1, m_num_of_scales);
+ float *in = reinterpret_cast<float*>(in_f_all.data);
+ fftwf_complex *out = reinterpret_cast<fftwf_complex*>(out_f_all.get_p_data());
+ int rank = 2;
+ int n[] = {(int)m_height, (int)m_width};
+ int howmany = m_num_of_scales;
+ int idist = m_height*m_width, odist = m_height*(m_width/2+1);
+ int istride = 1, ostride = 1;
+ int *inembed = NULL, *onembed = NULL;
+
+ FFTW_PLAN_WITH_THREADS();
+ plan_f_all_scales = fftwf_plan_many_dft_r2c(rank, n, howmany,
+ in, inembed, istride, idist,
+ out, onembed, ostride, odist,
+ FFTW_MEASURE);
+ }
+ //FFT forward window one scale
{
cv::Mat in_fw = cv::Mat::zeros(m_height * m_num_of_feats, m_width, CV_32F);
ComplexMat out_fw(m_height, m_width / 2 + 1, m_num_of_feats);
out, onembed, ostride, odist,
FFTW_MEASURE);
}
+ //FFT forward window all scales all feats
if(num_of_scales > 1)
{
cv::Mat in_all = cv::Mat::zeros(m_height * (num_of_scales*m_num_of_feats), m_width, CV_32F);
fftwf_complex *out = reinterpret_cast<fftwf_complex*>(out_all.get_p_data());
int rank = 2;
int n[] = {(int)m_height, (int)m_width};
- int howmany = num_of_scales*m_num_of_feats;
+ int howmany = m_num_of_scales*m_num_of_feats;
int idist = m_height*m_width, odist = m_height*(m_width/2+1);
int istride = 1, ostride = 1;
int *inembed = NULL, *onembed = NULL;
out, onembed, ostride, odist,
FFTW_MEASURE);
}
-
+ //FFT inverse one scale
{
ComplexMat in_i(m_height,m_width,m_num_of_feats);
cv::Mat out_i = cv::Mat::zeros(m_height, m_width, CV_32FC(m_num_of_feats));
out, onembed, ostride, odist,
FFTW_MEASURE);
}
+ //FFT inverse all scales
+ if(num_of_scales > 1)
+ {
+ ComplexMat in_i_all(m_height,m_width,m_num_of_feats*m_num_of_scales);
+ cv::Mat out_i_all = cv::Mat::zeros(m_height, m_width, CV_32FC(m_num_of_feats*m_num_of_scales));
+ fftwf_complex *in = reinterpret_cast<fftwf_complex*>(in_i_all.get_p_data());
+ float *out = reinterpret_cast<float*>(out_i_all.data);
+ int rank = 2;
+ int n[] = {(int)m_height, (int)m_width};
+ int howmany = m_num_of_feats*m_num_of_scales;
+ int idist = m_height*(m_width/2+1), odist = 1;
+ int istride = 1, ostride = m_num_of_feats;
+ int inembed[] = {(int)m_height, (int)m_width/2+1}, *onembed = n;
+ FFTW_PLAN_WITH_THREADS();
+ plan_i_features_all_scales = fftwf_plan_many_dft_c2r(rank, n, howmany,
+ in, inembed, istride, idist,
+ out, onembed, ostride, odist,
+ FFTW_MEASURE);
+ }
+ //FFT inver one channel one scale
{
ComplexMat in_i1(m_height,m_width,1);
cv::Mat out_i1 = cv::Mat::zeros(m_height, m_width, CV_32FC1);
out, onembed, ostride, odist,
FFTW_MEASURE);
}
+ //FFT inver one channel all scales
+ if(num_of_scales > 1)
+ {
+ ComplexMat in_i1_all(m_height,m_width,m_num_of_scales);
+ cv::Mat out_i1_all = cv::Mat::zeros(m_height, m_width, CV_32FC(m_num_of_scales));
+ fftwf_complex *in = reinterpret_cast<fftwf_complex*>(in_i1_all.get_p_data());
+ float *out = reinterpret_cast<float*>(out_i1_all.data);
+ int rank = 2;
+ int n[] = {(int)m_height, (int)m_width};
+ int howmany = m_num_of_scales;
+ int idist = m_height*(m_width/2+1), odist = 1;
+ int istride = 1, ostride = 1;
+ int inembed[] = {(int)m_height, (int)m_width/2+1}, *onembed = n;
+
+ FFTW_PLAN_WITH_THREADS();
+ plan_i_1ch_all_scales = fftwf_plan_many_dft_c2r(rank, n, howmany,
+ in, inembed, istride, idist,
+ out, onembed, ostride, odist,
+ FFTW_MEASURE);
+ }
}
void Fftw::set_window(const cv::Mat &window)
ComplexMat Fftw::forward(const cv::Mat &input)
{
- cv::Mat complex_result(m_height, m_width / 2 + 1, CV_32FC2);
+ ComplexMat complex_result(m_height, m_width / 2 + 1, 1);
- fftwf_execute_dft_r2c(plan_f,reinterpret_cast<float*>(input.data),reinterpret_cast<fftwf_complex*>(complex_result.data));
+ fftwf_execute_dft_r2c(plan_f,reinterpret_cast<float*>(input.data),reinterpret_cast<fftwf_complex*>(complex_result.get_p_data()));
return ComplexMat(complex_result);
}
float *in = reinterpret_cast<float*>(in_all.data);
fftwf_complex *out = reinterpret_cast<fftwf_complex*>(result.get_p_data());
- if (n_channels <= 44)
+ if (n_channels <= m_num_of_feats)
fftwf_execute_dft_r2c(plan_fw, in, out);
else
fftwf_execute_dft_r2c(plan_fw_all_scales, in, out);
Fftw::~Fftw()
{
fftwf_destroy_plan(plan_f);
+ fftwf_destroy_plan(plan_f_all_scales);
fftwf_destroy_plan(plan_fw);
fftwf_destroy_plan(plan_fw_all_scales);
fftwf_destroy_plan(plan_i_features);
+ fftwf_destroy_plan(plan_i_features_all_scales);
fftwf_destroy_plan(plan_i_1ch);
+ fftwf_destroy_plan(plan_i_1ch_all_scales);
}
ComplexMat zf = fft.forward_window(patch_feat);
DEBUG_PRINTM(zf);
cv::Mat response;
- for (size_t i = 0; i < p_scales.size(); ++i) {
+
if (m_use_linearkernel)
- response = fft.inverse((p_model_alphaf * zf.get_part(i,num_of_feats)).sum_over_channels());
+ response = fft.inverse((zf.mul2(p_model_alphaf)).sum_over_channels());
else {
- ComplexMat kzf = gaussian_correlation(zf.get_part(i,num_of_feats), p_model_xf, p_kernel_sigma);
+ ComplexMat kzf = gaussian_correlation(zf, p_model_xf, p_kernel_sigma);
DEBUG_PRINTM(p_model_alphaf);
DEBUG_PRINTM(kzf);
DEBUG_PRINTM(p_model_alphaf * kzf);
account the fact that, if the target doesn't move, the peak
will appear at the top-left corner, not at the center (this is
discussed in the paper). the responses wrap around cyclically. */
- double min_val, max_val;
- cv::Point2i min_loc, max_loc;
- cv::minMaxLoc(response, &min_val, &max_val, &min_loc, &max_loc);
- DEBUG_PRINT(max_loc);
+ for (size_t i = 0; i < p_scales.size(); ++i) {
+ double min_val, max_val;
+ cv::Point2i min_loc, max_loc;
+ cv::minMaxLoc(response, &min_val, &max_val, &min_loc, &max_loc);
+ DEBUG_PRINT(max_loc);
- double weight = p_scales[i] < 1. ? p_scales[i] : 1./p_scales[i];
- if (max_val*weight > max_response) {
- max_response = max_val*weight;
- max_response_map = response;
- max_response_pt = max_loc;
- scale_index = i;
+ double weight = p_scales[i] < 1. ? p_scales[i] : 1./p_scales[i];
+ if (max_val*weight > max_response) {
+ max_response = max_val*weight;
+ max_response_map = response;
+ max_response_pt = max_loc;
+ scale_index = i;
+ }
+ scale_responses.push_back(max_val*weight);
}
- scale_responses.push_back(max_val*weight);
- }
} else {
#pragma omp parallel for ordered private(patch_feat) schedule(dynamic)
for (size_t i = 0; i < p_scales.size(); ++i) {
float xf_sqr_norm = xf.sqr_norm();
float yf_sqr_norm = auto_correlation ? xf_sqr_norm : yf.sqr_norm();
- ComplexMat xyf = auto_correlation ? xf.sqr_mag() : xf * yf.conj();
+ ComplexMat xyf;
+ if(xf.channels() != 308)
+ xyf = auto_correlation ? xf.sqr_mag() : xf * yf.conj();
+ else
+ xyf = auto_correlation ? xf.sqr_mag() : xf.mul2(yf.conj());
DEBUG_PRINTM(xyf);
//ifft2 and sum over 3rd dimension, we dont care about individual channels