]> rtime.felk.cvut.cz Git - hercules2020/kcf.git/commitdiff
Big batch update 2 (not finished)
authorShanigen <vkaraf@gmail.com>
Sun, 25 Mar 2018 15:27:32 +0000 (17:27 +0200)
committerShanigen <vkaraf@gmail.com>
Sun, 25 Mar 2018 15:27:32 +0000 (17:27 +0200)
Problem with scaling.

src/complexmat.hpp
src/fft_fftw.cpp
src/kcf.cpp

index a189229421119b97bb6e49c0bca8abefac54c155..59f3aa623fe51a8ead8c7e4257aebd53415f9812 100644 (file)
@@ -32,8 +32,20 @@ public:
         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
@@ -53,14 +65,21 @@ public:
     }
 
 
-    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
@@ -78,7 +97,6 @@ public:
         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>>());
         }
@@ -224,7 +242,7 @@ private:
             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);
             }
         }
index 7474657db24a1da901b1a0a2eb351f8a19393cbd..8a57da50b4020eb776675bc4e6995e08b0756f7e 100644 (file)
@@ -50,9 +50,9 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
                                    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());
@@ -89,10 +89,10 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
                                           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;
@@ -128,7 +128,7 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
                                                   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));
@@ -138,7 +138,7 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
         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();
@@ -167,7 +167,7 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
                                              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));
@@ -177,7 +177,7 @@ void Fftw::init(unsigned width, unsigned height, unsigned num_of_feats, unsigned
         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();
@@ -195,11 +195,17 @@ void Fftw::set_window(const cv::Mat &window)
 
 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)
@@ -210,12 +216,16 @@ 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);
@@ -230,10 +240,14 @@ cv::Mat Fftw::inverse(const ComplexMat &inputf)
     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);
 }
index 898fbabad800458fcdd7e0409489d277638151b4..dc5e0efebc3ca52293b5a3c7102c0a1677f07022 100644 (file)
@@ -17,7 +17,7 @@
 #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()),
@@ -246,10 +246,11 @@ void KCF_Tracker::track(cv::Mat &img)
                 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
@@ -258,13 +259,13 @@ void KCF_Tracker::track(cv::Mat &img)
             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;
                 }
@@ -586,35 +587,47 @@ cv::Mat KCF_Tracker::get_subwindow(const cv::Mat &input, int cx, int cy, int wid
 
 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)