Problem with scaling.
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)
+ void create(int _rows, int _cols, int _n_channels)
{
+ rows = _rows;
+ cols = _cols;
+ n_channels = _n_channels;
+ p_data.resize(n_channels*cols*rows);
+ }
+
+ void create(int _rows, int _cols, int _n_channels, int _n_scales)
+ {
+ rows = _rows;
+ cols = _cols;
+ n_channels = _n_channels;
+ n_scales = _n_scales;
p_data.resize(n_channels*cols*rows);
}
// cv::Mat API compatibility
}
- T sqr_norm() const
+ std::vector<T> sqr_norm() const
{
- T sum_sqr_norm = 0;
- for (int i = 0; i < n_channels; ++i)
- for (auto lhs = p_data.begin()+i*rows*cols; lhs != p_data.begin()+(i+1)*rows*cols; ++lhs)
- sum_sqr_norm += lhs->real()*lhs->real() + lhs->imag()*lhs->imag();
-
- return sum_sqr_norm / static_cast<T>(cols*rows);
+ std::vector<T> sums_sqr_norms;
+ sums_sqr_norms.resize(n_scales);
+ int n_channels_per_scale = n_channels/n_scales;
+ int scale_offset = n_channels_per_scale*rows*cols;
+ T sum_sqr_norm;
+ for(int scale = 0; scale < n_scales; ++scale){
+ sum_sqr_norm = 0;
+ for (int i = 0; i < n_channels_per_scale; ++i)
+ for (auto lhs = p_data.begin()+i*rows*cols+scale*scale_offset; lhs != p_data.begin()+(i+1)*rows*cols+scale*scale_offset; ++lhs)
+ sum_sqr_norm += lhs->real()*lhs->real() + lhs->imag()*lhs->imag();
+ sums_sqr_norms[scale] = sum_sqr_norm/static_cast<T>(cols*rows);
+ }
+ return sums_sqr_norms;
}
ComplexMat_<T> sqr_mag() const
assert(p_data.size() > 1);
ComplexMat_<T> result(this->rows, this->cols, 1);
std::copy(p_data.begin(),p_data.begin()+rows*cols, result.p_data.begin());
- std::cout << "TEST\n"<< *this << std::endl;
for (int i = 1; i < n_channels; ++i) {
std::transform(result.p_data.begin(), result.p_data.end(), p_data.begin()+i*rows*cols, result.p_data.begin(), std::plus<std::complex<T>>());
}
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)
+ for ( ; lhs != result.p_data.begin()+((j+1)*rows*cols)+(i*scale_offset); ++lhs, ++rhs)
op(*lhs, *rhs);
}
}
FFTW_MEASURE);
}
//FFT forward all scales
- if(num_of_scales > 1)
+ if(m_num_of_scales > 1)
{
- cv::Mat in_f_all = cv::Mat::zeros(m_height*m_num_of_scales, m_width, CV_32FC1);
+ cv::Mat in_f_all = cv::Mat::zeros(m_height*m_num_of_scales, m_width, CV_32F);
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());
FFTW_MEASURE);
}
//FFT forward window all scales all feats
- if(num_of_scales > 1)
+ if(m_num_of_scales > 1)
{
- cv::Mat in_all = cv::Mat::zeros(m_height * (num_of_scales*m_num_of_feats), m_width, CV_32F);
- ComplexMat out_all(m_height, m_width / 2 + 1, num_of_scales*m_num_of_feats);
+ cv::Mat in_all = cv::Mat::zeros(m_height * (m_num_of_scales*m_num_of_feats), m_width, CV_32F);
+ ComplexMat out_all(m_height, m_width / 2 + 1, m_num_of_scales*m_num_of_feats);
float *in = reinterpret_cast<float*>(in_all.data);
fftwf_complex *out = reinterpret_cast<fftwf_complex*>(out_all.get_p_data());
int rank = 2;
FFTW_MEASURE);
}
//FFT inverse all scales
- if(num_of_scales > 1)
+ if(m_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));
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 istride = 1, ostride = m_num_of_feats*m_num_of_scales;
int inembed[] = {(int)m_height, (int)m_width/2+1}, *onembed = n;
FFTW_PLAN_WITH_THREADS();
FFTW_MEASURE);
}
//FFT inver one channel all scales
- if(num_of_scales > 1)
+ if(m_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));
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 istride = 1, ostride = m_num_of_scales;
int inembed[] = {(int)m_height, (int)m_width/2+1}, *onembed = n;
FFTW_PLAN_WITH_THREADS();
ComplexMat Fftw::forward(const cv::Mat &input)
{
- 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.get_p_data()));
-
- return ComplexMat(complex_result);
+ ComplexMat complex_result;
+ if(input.rows == (int)(m_height*m_num_of_scales)){
+ complex_result.create(m_height, m_width / 2 + 1, m_num_of_scales);
+ fftwf_execute_dft_r2c(plan_f_all_scales, reinterpret_cast<float*>(input.data),
+ reinterpret_cast<fftwf_complex*>(complex_result.get_p_data()));
+ } else {
+ complex_result.create(m_height, m_width / 2 + 1, 1);
+ fftwf_execute_dft_r2c(plan_f, reinterpret_cast<float*>(input.data),
+ reinterpret_cast<fftwf_complex*>(complex_result.get_p_data()));
+ }
+ return complex_result;
}
ComplexMat Fftw::forward_window(const std::vector<cv::Mat> &input)
cv::Mat in_roi(in_all, cv::Rect(0, i*m_height, m_width, m_height));
in_roi = input[i].mul(m_window);
}
- ComplexMat result(m_height, m_width/2 + 1, n_channels);
+ ComplexMat result;
+ if(n_channels > (int) m_num_of_feats)
+ result.create(m_height, m_width/2 + 1, n_channels,m_num_of_scales);
+ else
+ result.create(m_height, m_width/2 + 1, n_channels);
float *in = reinterpret_cast<float*>(in_all.data);
fftwf_complex *out = reinterpret_cast<fftwf_complex*>(result.get_p_data());
- if (n_channels <= m_num_of_feats)
+ if (n_channels <= (int) m_num_of_feats)
fftwf_execute_dft_r2c(plan_fw, in, out);
else
fftwf_execute_dft_r2c(plan_fw_all_scales, in, out);
fftwf_complex *in = reinterpret_cast<fftwf_complex*>(inputf.get_p_data());
float *out = reinterpret_cast<float*>(real_result.data);
- if(n_channels != 1)
- fftwf_execute_dft_c2r(plan_i_features, in, out);
- else
+ if(n_channels == 1)
fftwf_execute_dft_c2r(plan_i_1ch, in, out);
+ else if(n_channels == (int) m_num_of_scales)
+ fftwf_execute_dft_c2r(plan_i_1ch_all_scales, in, out);
+ else if(n_channels == (int) m_num_of_feats * (int) m_num_of_scales)
+ fftwf_execute_dft_c2r(plan_i_features_all_scales, in, out);
+ else
+ fftwf_execute_dft_c2r(plan_i_features, in, out);
return real_result/(m_width*m_height);
}
#endif //OPENMP
#define DEBUG_PRINT(obj) if (m_debug) {std::cout << #obj << " @" << __LINE__ << std::endl << (obj) << std::endl;}
-#define DEBUG_PRINTM(obj) if (m_debug) {std::cout << #obj << " @" << __LINE__ << " " << (obj).size() << std::endl << (obj) << std::endl;}
+#define DEBUG_PRINTM(obj) if (m_debug) {std::cout << #obj << " @" << __LINE__ << " " << (obj).size() << " CH: " << (obj).channels() << std::endl << (obj) << std::endl;}
KCF_Tracker::KCF_Tracker(double padding, double kernel_sigma, double lambda, double interp_factor, double output_sigma_factor, int cell_size) :
fft(*new FFT()),
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);
- response = fft.inverse(p_model_alphaf * kzf);
+ response = fft.inverse(kzf.mul(p_model_alphaf));
}
DEBUG_PRINTM(response);
+ std::vector<cv::Mat> scales;
+ cv::split(response,scales);
/* target location is at the maximum response. we must take into
account the fact that, if the target doesn't move, the peak
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);
+ cv::minMaxLoc(scales[i], &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_map = scales[i];
max_response_pt = max_loc;
scale_index = i;
}
ComplexMat KCF_Tracker::gaussian_correlation(const ComplexMat &xf, const ComplexMat &yf, double sigma, bool auto_correlation)
{
- float xf_sqr_norm = xf.sqr_norm();
- float yf_sqr_norm = auto_correlation ? xf_sqr_norm : yf.sqr_norm();
+ std::vector<float> xf_sqr_norm = xf.sqr_norm();
+ std::vector<float> yf_sqr_norm = auto_correlation ? xf_sqr_norm : yf.sqr_norm();
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
cv::Mat ifft2_res = fft.inverse(xyf);
- cv::Mat xy_sum(ifft2_res.size(), CV_32FC1);
+ cv::Mat xy_sum;
+ if(xf.channels() != 308)
+ xy_sum.create(ifft2_res.size(), CV_32FC1);
+ else
+ xy_sum.create(ifft2_res.size(), CV_32FC(p_scales.size()));
xy_sum.setTo(0);
for (int y = 0; y < ifft2_res.rows; ++y) {
float * row_ptr = ifft2_res.ptr<float>(y);
float * row_ptr_sum = xy_sum.ptr<float>(y);
- for (int x = 0; x < ifft2_res.cols; ++x){
- row_ptr_sum[x] = std::accumulate((row_ptr + x*ifft2_res.channels()), (row_ptr + x*ifft2_res.channels() + ifft2_res.channels()), 0.f);
+ for (int x = 0; x < ifft2_res.cols; ++x) {
+ for (int sum_ch = 0; sum_ch < xy_sum.channels(); ++sum_ch) {
+ row_ptr_sum[(x*xy_sum.channels())+sum_ch] += std::accumulate(row_ptr + x*ifft2_res.channels() + sum_ch*(ifft2_res.channels()/xy_sum.channels()),
+ (row_ptr + x*ifft2_res.channels() + (sum_ch+1)*(ifft2_res.channels()/xy_sum.channels())), 0.f);
+ }
}
}
DEBUG_PRINTM(ifft2_res);
DEBUG_PRINTM(xy_sum);
- float numel_xf_inv = 1.f/(xf.cols * xf.rows * xf.n_channels);
- cv::Mat tmp;
- cv::exp(- 1.f / (sigma * sigma) * cv::max((xf_sqr_norm + yf_sqr_norm - 2 * xy_sum) * numel_xf_inv, 0), tmp);
+ std::vector<cv::Mat> scales;
+ cv::split(xy_sum,scales);
+ cv::Mat in_all(scales[0].rows * xf.n_scales, scales[0].cols, CV_32F);
- return fft.forward(tmp);
+ float numel_xf_inv = 1.f/(xf.cols * xf.rows * (xf.channels()/xf.n_scales));
+ for(int i = 0; i < xf.n_scales; ++i){
+ cv::Mat in_roi(in_all, cv::Rect(0, i*scales[0].rows, scales[0].cols, scales[0].rows));
+ cv::exp(- 1.f / (sigma * sigma) * cv::max((xf_sqr_norm[i] + yf_sqr_norm[i] - 2 * scales[i]) * numel_xf_inv, 0), in_roi);
+ DEBUG_PRINTM(in_roi);
+ }
+
+ DEBUG_PRINTM(in_all);
+ return fft.forward(in_all);
}
float get_response_circular(cv::Point2i & pt, cv::Mat & response)