From 94da17302db65cc10aed7a421453c16bb2ad5355 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Thu, 20 Sep 2018 06:55:18 +0200 Subject: [PATCH] Move scale_track method from KCF to ThreadCtx --- src/complexmat.cuh | 2 +- src/complexmat.hpp | 2 +- src/kcf.cpp | 61 +++++++++++++++++++++++----------------------- src/kcf.h | 4 +-- src/threadctx.hpp | 23 +++++++---------- 5 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/complexmat.cuh b/src/complexmat.cuh index 940900e..cf1389a 100644 --- a/src/complexmat.cuh +++ b/src/complexmat.cuh @@ -72,7 +72,7 @@ class ComplexMat { CudaSafeCall(cudaMalloc(&p_data, n_channels * cols * rows * sizeof(cufftComplex))); } // cv::Mat API compatibility - cv::Size size() { return cv::Size(cols, rows); } + cv::Size size() const { return cv::Size(cols, rows); } int channels() { return n_channels; } int channels() const { return n_channels; } diff --git a/src/complexmat.hpp b/src/complexmat.hpp index c93eed7..2bd625c 100644 --- a/src/complexmat.hpp +++ b/src/complexmat.hpp @@ -54,7 +54,7 @@ template class ComplexMat_ { p_data.resize(n_channels * cols * rows); } // cv::Mat API compatibility - cv::Size size() { return cv::Size(cols, rows); } + cv::Size size() const { return cv::Size(cols, rows); } uint channels() const { return n_channels; } // assuming that mat has 2 channels (real, imag) diff --git a/src/kcf.cpp b/src/kcf.cpp index ec3e901..d207fdc 100644 --- a/src/kcf.cpp +++ b/src/kcf.cpp @@ -367,7 +367,7 @@ void KCF_Tracker::track(cv::Mat &img) #ifdef ASYNC for (auto &it : d.threadctxs) it.async_res = std::async(std::launch::async, [this, &input_gray, &input_rgb, &it]() -> void { - scale_track(it, input_rgb, input_gray); + it.track(*this, input_rgb, input_gray); }); for (auto const &it : d.threadctxs) it.async_res.wait(); @@ -376,7 +376,7 @@ void KCF_Tracker::track(cv::Mat &img) // FIXME: Iterate correctly in big batch mode - perhaps have only one element in the list NORMAL_OMP_PARALLEL_FOR for (uint i = 0; i < d.threadctxs.size(); ++i) - scale_track(d.threadctxs[i], input_rgb, input_gray); + d.threadctxs[i].track(*this, input_rgb, input_gray); #endif cv::Point2f new_location; @@ -406,70 +406,71 @@ void KCF_Tracker::track(cv::Mat &img) train(input_rgb, input_gray, p_interp_factor); } -void KCF_Tracker::scale_track(ThreadCtx &vars, cv::Mat &input_rgb, cv::Mat &input_gray) +void ThreadCtx::track(const KCF_Tracker &kcf, cv::Mat &input_rgb, cv::Mat &input_gray) { // TODO: Move matrices to thread ctx - int sizes[3] = {p_num_of_feats, p_windows_size.height, p_windows_size.width}; + int sizes[3] = {kcf.p_num_of_feats, kcf.p_windows_size.height, kcf.p_windows_size.width}; MatDynMem patch_feats(3, sizes, CV_32FC1); MatDynMem temp(3, sizes, CV_32FC1); #ifdef BIG_BATCH BIG_BATCH_OMP_PARALLEL_FOR - for (uint i = 0; i < p_num_scales; ++i) + for (uint i = 0; i < kcf.p_num_scales; ++i) #endif { - get_features(patch_feats, input_rgb, input_gray, this->p_pose.cx, this->p_pose.cy, - this->p_windows_size.width, this->p_windows_size.height, - this->p_current_scale * IF_BIG_BATCH(this->p_scales[i], vars.scale)); + kcf.get_features(patch_feats, input_rgb, input_gray, kcf.p_pose.cx, kcf.p_pose.cy, + kcf.p_windows_size.width, kcf.p_windows_size.height, + kcf.p_current_scale * IF_BIG_BATCH(kcf.p_scales[i], scale)); } - fft.forward_window(patch_feats, vars.zf, temp); - DEBUG_PRINTM(vars.zf); + kcf.fft.forward_window(patch_feats, zf, temp); + DEBUG_PRINTM(zf); - if (m_use_linearkernel) { - vars.kzf = vars.zf.mul(p_model_alphaf).sum_over_channels(); + if (kcf.m_use_linearkernel) { + kzf = zf.mul(kcf.p_model_alphaf).sum_over_channels(); } else { - (*gaussian_correlation)(*this, vars.kzf, vars.zf, this->p_model_xf, this->p_kernel_sigma); - DEBUG_PRINTM(this->p_model_alphaf); - DEBUG_PRINTM(vars.kzf); - vars.kzf = vars.kzf.mul(this->p_model_alphaf); + gaussian_correlation(kcf, kzf, zf, kcf.p_model_xf, kcf.p_kernel_sigma); + DEBUG_PRINTM(kcf.p_model_alphaf); + DEBUG_PRINTM(kzf); + kzf = kzf.mul(kcf.p_model_alphaf); } - fft.inverse(vars.kzf, vars.response); + kcf.fft.inverse(kzf, response); - DEBUG_PRINTM(vars.response); + DEBUG_PRINTM(response); /* target location is at the maximum response. we must take into 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. */ #ifdef BIG_BATCH - cv::split(vars.response, vars.response_maps); + cv::split(response, response_maps); - for (size_t i = 0; i < p_scales.size(); ++i) { + for (size_t i = 0; i < kcf.p_scales.size(); ++i) { double min_val, max_val; cv::Point2i min_loc, max_loc; - cv::minMaxLoc(vars.response_maps[i], &min_val, &max_val, &min_loc, &max_loc); + cv::minMaxLoc(response_maps[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]; - vars.max_responses[i] = max_val * weight; - vars.max_locs[i] = max_loc; + double weight = kcf.p_scales[i] < 1. ? kcf.p_scales[i] : 1. / kcf.p_scales[i]; + max_responses[i] = max_val * weight; + max_locs[i] = max_loc; } #else double min_val; cv::Point2i min_loc; - cv::minMaxLoc(vars.response, &min_val, &vars.max_val, &min_loc, &vars.max_loc); + cv::minMaxLoc(response, &min_val, &max_val, &min_loc, &max_loc); - DEBUG_PRINT(vars.max_loc); + DEBUG_PRINT(max_loc); - double weight = vars.scale < 1. ? vars.scale : 1. / vars.scale; - vars.max_response = vars.max_val * weight; + double weight = scale < 1. ? scale : 1. / scale; + max_response = max_val * weight; #endif return; } // **************************************************************************** -void KCF_Tracker::get_features(MatDynMem &result_3d, cv::Mat & input_rgb, cv::Mat & input_gray, int cx, int cy, int size_x, int size_y, double scale) +void KCF_Tracker::get_features(MatDynMem &result_3d, cv::Mat &input_rgb, cv::Mat &input_gray, int cx, int cy, + int size_x, int size_y, double scale) const { assert(result_3d.size[0] == p_num_of_feats); assert(result_3d.size[1] == size_x); @@ -634,7 +635,7 @@ cv::Mat KCF_Tracker::cosine_window_function(int dim1, int dim2) // Returns sub-window of image input centered at [cx, cy] coordinates), // with size [width, height]. If any pixels are outside of the image, // they will replicate the values at the borders. -cv::Mat KCF_Tracker::get_subwindow(const cv::Mat &input, int cx, int cy, int width, int height) +cv::Mat KCF_Tracker::get_subwindow(const cv::Mat &input, int cx, int cy, int width, int height) const { cv::Mat patch; diff --git a/src/kcf.h b/src/kcf.h index 9408e11..7ce4f2d 100644 --- a/src/kcf.h +++ b/src/kcf.h @@ -148,12 +148,12 @@ private: //helping functions void scale_track(ThreadCtx &vars, cv::Mat &input_rgb, cv::Mat &input_gray); - cv::Mat get_subwindow(const cv::Mat &input, int cx, int cy, int size_x, int size_y); + cv::Mat get_subwindow(const cv::Mat &input, int cx, int cy, int size_x, int size_y) const; MatDynMem gaussian_shaped_labels(double sigma, int dim1, int dim2); std::unique_ptr gaussian_correlation; MatDynMem circshift(const cv::Mat &patch, int x_rot, int y_rot); cv::Mat cosine_window_function(int dim1, int dim2); - void get_features(MatDynMem &feat_3d, cv::Mat &input_rgb, cv::Mat &input_gray, int cx, int cy, int size_x, int size_y, double scale); + void get_features(MatDynMem &feat_3d, cv::Mat &input_rgb, cv::Mat &input_gray, int cx, int cy, int size_x, int size_y, double scale) const; cv::Point2f sub_pixel_peak(cv::Point &max_loc, cv::Mat &response) const; double sub_grid_scale(uint index); void resizeImgs(cv::Mat &input_rgb, cv::Mat &input_gray); diff --git a/src/threadctx.hpp b/src/threadctx.hpp index 85529dd..1e9a3fb 100644 --- a/src/threadctx.hpp +++ b/src/threadctx.hpp @@ -30,34 +30,27 @@ struct ThreadCtx { ThreadCtx(ThreadCtx &&) = default; + void track(const KCF_Tracker &kcf, cv::Mat &input_rgb, cv::Mat &input_gray); private: cv::Size roi; uint num_channels; uint num_of_scales; cv::Size freq_size = Fft::freq_size(roi); -public: -#ifdef ASYNC - std::future async_res; -#endif KCF_Tracker::GaussianCorrelation gaussian_correlation{roi, num_of_scales, num_channels}; -#if defined(CUFFT) || defined(FFTW) // TODO: Why this ifdef? - MatDynMem in_all{roi.height * int(num_of_scales), roi.width, CV_32F}; -#else - MatDynMem in_all{roi, CV_32F}; -#endif - MatDynMem fw_all{roi.height * int(num_channels), roi.width, CV_32F}; MatDynMem ifft2_res{roi, CV_32FC(int(num_channels))}; - MatDynMem response{roi, CV_32FC(int(num_of_scales))}; ComplexMat zf{uint(freq_size.height), uint(freq_size.width), num_channels, num_of_scales}; ComplexMat kzf{uint(freq_size.height), uint(freq_size.width), num_of_scales}; - // Variables used during non big batch mode and in big batch mode with ThreadCtx in p_threadctxs in kcf on zero index. - cv::Point2i max_loc; - double max_val, max_response; +public: +#ifdef ASYNC + std::future async_res; +#endif + + MatDynMem response{roi, CV_32FC(int(num_of_scales))}; #ifdef BIG_BATCH // Stores value of responses, location of maximal response and response maps for each scale @@ -65,6 +58,8 @@ public: std::vector max_locs = std::vector(num_of_scales); std::vector response_maps = std::vector(num_of_scales); #else + cv::Point2i max_loc; + double max_val, max_response; const double scale; #endif }; -- 2.39.2