]> rtime.felk.cvut.cz Git - hercules2020/kcf.git/blobdiff - src/threadctx.hpp
Extend to support not only multiple scales but also multiple angles
[hercules2020/kcf.git] / src / threadctx.hpp
index c4bb5356484925b34a5871ba6e134bd69812ff86..0b23707172cbbc1033e5de02980c076041f8834f 100644 (file)
 
 #include <future>
 #include "dynmem.hpp"
-
-#ifdef CUFFT
-#include "complexmat.cuh"
-#else
+#include "kcf.h"
 #include "complexmat.hpp"
-#ifndef CUFFTW
-// For compatibility reasons between CuFFT and FFTW, OpenCVfft versions.
-typedef int *cudaStream_t;
-#endif
-#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 windows_size, uint cell_size, uint num_of_feats, double scale, uint num_of_scales = 1)
-        : scale(scale)
-    {
-        this->xf_sqr_norm = DynMem(num_of_scales * sizeof(float));
-        this->yf_sqr_norm = DynMem(sizeof(float));
-        this->patch_feats.reserve(uint(num_of_feats));
-
-        uint cells_size =
-            ((uint(windows_size.width) / cell_size) * (uint(windows_size.height) / cell_size)) * sizeof(float);
-
-#if  !defined(BIG_BATCH) && defined(CUFFT) && (defined(ASYNC) || defined(OPENMP))
-        CudaSafeCall(cudaStreamCreate(&this->stream));
+    ThreadCtx(cv::Size roi, uint num_features
+#ifdef BIG_BATCH
+              , const std::vector<double> &scales
+              , const std::vector<double> &angles
+#else
+              , double scale
+              , double angle
 #endif
-
-#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 = (uint(windows_size.width) / cell_size) / 2 + 1;
-
-        this->in_all = cv::Mat(windows_size.height / int(cell_size) * int(num_of_scales),
-                               windows_size.width / int(cell_size), CV_32F, this->gauss_corr_res.hostMem());
-
-        this->fw_all = cv::Mat((windows_size.height / int(cell_size)) * int(num_of_feats),
-                               windows_size.width / int(cell_size), CV_32F, this->data_features.hostMem());
+             )
+        : 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
+        , max(scales, angles)
+        , dbg_patch(scales, angles)
+        {
+            max.resize(scales.size() * angles.size());
+            dbg_patch.resize(scales.size() * angles.size());
+        }
 #else
-        uint width_freq = uint(windows_size.width) / cell_size;
-
-        this->in_all = cv::Mat((windows_size.height / int(cell_size)), windows_size.width / int(cell_size), CV_32F);
+        , scale(scale)
+        , angle(angle)
+        {}
 #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(windows_size.height / int(cell_size), windows_size.width / int(cell_size),
-                                  CV_32FC(int(num_of_feats)), this->data_i_features.hostMem());
+    ThreadCtx(ThreadCtx &&) = default;
 
-        this->response = cv::Mat(windows_size.height / int(cell_size), windows_size.width / int(cell_size),
-                                 CV_32FC(int(num_of_scales)), this->data_i_1ch.hostMem());
+    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);
 
-        this->patch_feats.reserve(num_of_feats);
+    MatScaleFeats patch_feats{num_scales * num_angles, num_features, roi};
+    MatScaleFeats temp{num_scales * num_angles, num_features, roi};
 
-#ifdef CUFFT
-        this->zf.create(uint(windows_size.height) / cell_size, width_freq, num_of_feats, num_of_scales, this->stream);
-        this->kzf.create(uint(windows_size.height) / cell_size, width_freq, num_of_scales, this->stream);
-        this->kf.create(uint(windows_size.height) / cell_size, width_freq, num_of_scales, this->stream);
-#else
-        this->zf.create(uint(windows_size.height) / cell_size, width_freq, num_of_feats, num_of_scales);
-        this->kzf.create(uint(windows_size.height) / cell_size, width_freq, num_of_scales);
-        this->kf.create(uint(windows_size.height) / cell_size, width_freq, num_of_scales);
-#endif
+    KCF_Tracker::GaussianCorrelation gaussian_correlation{num_scales * num_angles, num_features, roi};
 
-        if (num_of_scales > 1) {
-            this->max_responses.reserve(uint(num_of_scales));
-            this->max_locs.reserve(uint(num_of_scales));
-            this->response_maps.reserve(uint(num_of_scales));
-        }
-    }
-    ThreadCtx(ThreadCtx &&) = default;
-    ~ThreadCtx()
-    {
-#if  !defined(BIG_BATCH) && defined(CUFFT) && (defined(ASYNC) || defined(OPENMP))
-        CudaSafeCall(cudaStreamDestroy(this->stream));
-#endif
-    }
+    MatScales ifft2_res{num_scales * num_angles, roi};
 
-    const double scale;
+    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};
+
+public:
 #ifdef ASYNC
     std::future<void> async_res;
 #endif
 
-    DynMem xf_sqr_norm, yf_sqr_norm;
-    std::vector<cv::Mat> patch_feats;
-
-    cv::Mat in_all, fw_all, ifft2_res, response;
-    ComplexMat zf, kzf, kf, xyf;
-
-    DynMem data_i_features, data_i_1ch;
-    // CuFFT and FFTW variables
-    DynMem gauss_corr_res, data_features;
+    MatScales response{num_scales * num_angles, roi};
 
-    // CuFFT variables
-    cudaStream_t stream = nullptr;
-    ComplexMat model_alphaf, model_xf;
+    struct Max {
+        cv::Point2i loc;
+        double response;
+    };
 
-    // 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;
-
-    // Big batch variables
-    // 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;
+#ifdef BIG_BATCH
+    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
 };
 
 #endif // SCALE_VARS_HPP