#include <future>
#include "dynmem.hpp"
#include "kcf.h"
-
-#ifdef CUFFT
-#include "complexmat.cuh"
-#else
#include "complexmat.hpp"
-#endif
+#include <vector>
class KCF_Tracker;
+template <typename T>
+class ScaleRotVector : public std::vector<T> {
+public:
+ ScaleRotVector(const std::vector<double> &scales, const std::vector<double> &angles)
+ : scales(scales)
+ , angles(angles)
+ {}
+
+ uint getIdx(uint scale_idx, uint angle_idx) const { return angles.size() * scale_idx + angle_idx; }
+ uint getScaleIdx(uint idx) const { return idx / angles.size(); }
+ uint getAngleIdx(uint idx) const { return idx % angles.size(); }
+ T& operator()(uint scale_idx, uint angle_idx) { return std::vector<T>::at(getIdx(scale_idx, angle_idx)); }
+ double scale(uint idx) const { return scales[getScaleIdx(idx)]; }
+ double angle(uint idx) const { return angles[getAngleIdx(idx)]; }
+private:
+ const std::vector<double> scales, angles;
+};
+
struct ThreadCtx {
public:
- ThreadCtx(cv::Size roi, uint num_of_feats, double scale, uint num_of_scales)
- : scale(scale)
- , gc(num_of_scales)
- {
- uint cells_size = roi.width * roi.height * sizeof(float);
-
-#if defined(CUFFT) || defined(FFTW)
- this->gauss_corr_res = DynMem(cells_size * num_of_scales);
- this->data_features = DynMem(cells_size * num_of_feats);
-
- uint width_freq = roi.width / 2 + 1;
-
- this->in_all = cv::Mat(roi.height * num_of_scales, roi.width, CV_32F, this->gauss_corr_res.hostMem());
- this->fw_all = cv::Mat(roi.height * num_of_feats, roi.width, CV_32F, this->data_features.hostMem());
-#else
- uint width_freq = roi.width;
-
- this->in_all = cv::Mat(roi, CV_32F);
-#endif
-
- this->data_i_features = DynMem(cells_size * num_of_feats);
- this->data_i_1ch = DynMem(cells_size * num_of_scales);
-
- this->ifft2_res = cv::Mat(roi, CV_32FC(num_of_feats), this->data_i_features.hostMem());
- this->response = cv::Mat(roi, CV_32FC(num_of_scales), this->data_i_1ch.hostMem());
-
-#ifdef CUFFT
- this->zf.create(roi.height, width_freq, num_of_feats, num_of_scales);
- this->kzf.create(roi.height, width_freq, num_of_scales);
- this->kf.create(roi.height, width_freq, num_of_scales);
+ ThreadCtx(cv::Size roi, uint num_features
+#ifdef BIG_BATCH
+ , const std::vector<double> &scales
+ , const std::vector<double> &angles
#else
- this->zf.create(roi.height, width_freq, num_of_feats, num_of_scales);
- this->kzf.create(roi.height, width_freq, num_of_scales);
- this->kf.create(roi.height, width_freq, num_of_scales);
+ , double scale
+ , double angle
#endif
-
+ )
+ : roi(roi)
+ , num_features(num_features)
+ , num_scales(IF_BIG_BATCH(scales.size(), 1))
+ , num_angles(IF_BIG_BATCH(angles.size(), 1))
#ifdef BIG_BATCH
- if (num_of_scales > 1) {
- this->max_responses.reserve(num_of_scales);
- this->max_locs.reserve(num_of_scales);
- this->response_maps.reserve(num_of_scales);
+ , max(scales, angles)
+ , dbg_patch(scales, angles)
+ {
+ max.resize(scales.size() * angles.size());
+ dbg_patch.resize(scales.size() * angles.size());
}
+#else
+ , scale(scale)
+ , angle(angle)
+ {}
#endif
- }
+
+
ThreadCtx(ThreadCtx &&) = default;
- const double scale;
-#ifdef ASYNC
- std::future<void> async_res;
-#endif
+ void track(const KCF_Tracker &kcf, cv::Mat &input_rgb, cv::Mat &input_gray);
+private:
+ cv::Size roi;
+ uint num_features;
+ uint num_scales;
+ uint num_angles;
+ cv::Size freq_size = Fft::freq_size(roi);
+
+ MatScaleFeats patch_feats{num_scales * num_angles, num_features, roi};
+ MatScaleFeats temp{num_scales * num_angles, num_features, roi};
- class gaussian_correlation_data {
- friend void KCF_Tracker::gaussian_correlation(struct ThreadCtx &vars, const ComplexMat &xf, const ComplexMat &yf, double sigma, bool auto_correlation);
- DynMem xf_sqr_norm;
- DynMem yf_sqr_norm{sizeof(float)};
+ KCF_Tracker::GaussianCorrelation gaussian_correlation{num_scales * num_angles, num_features, roi};
- public:
- gaussian_correlation_data(uint num_of_scales) : xf_sqr_norm(num_of_scales * sizeof(float)) {}
- } gc;
+ MatScales ifft2_res{num_scales * num_angles, roi};
- cv::Mat in_all, fw_all, ifft2_res, response;
- ComplexMat zf, kzf, kf, xyf;
+ ComplexMat zf{uint(freq_size.height), uint(freq_size.width), num_features, num_scales * num_angles};
+ ComplexMat kzf{uint(freq_size.height), uint(freq_size.width), 1, num_scales * num_angles};
- DynMem data_i_features, data_i_1ch;
- // CuFFT and FFTW variables
- DynMem gauss_corr_res, data_features;
+public:
+#ifdef ASYNC
+ std::future<void> async_res;
+#endif
- // CuFFT variables
- ComplexMat model_alphaf, model_xf;
+ MatScales response{num_scales * num_angles, roi};
- // 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;
+ struct Max {
+ cv::Point2i loc;
+ double response;
+ };
#ifdef BIG_BATCH
- // Stores value of responses, location of maximal response and response maps for each scale
- std::vector<double> max_responses;
- std::vector<cv::Point2i> max_locs;
- std::vector<cv::Mat> response_maps;
+ ScaleRotVector<Max> max;
+ ScaleRotVector<cv::Mat> dbg_patch; // images for visual debugging
+#else
+ Max max;
+ const double scale, angle;
+ cv::Mat dbg_patch; // image for visual debugging
#endif
};