]> rtime.felk.cvut.cz Git - hercules2020/kcf.git/commitdiff
Added non-template version of the ComplexMat class to test out the HERCULES compiler.
authorShanigen <vkaraf@gmail.com>
Wed, 23 May 2018 12:18:53 +0000 (14:18 +0200)
committerShanigen <vkaraf@gmail.com>
Wed, 23 May 2018 12:18:53 +0000 (14:18 +0200)
src/CMakeLists.txt
src/complexmat.cpp [new file with mode: 0644]
src/complexmat.hpp

index 7b7d6b958005bbde985cf7ff0321e4e39170730b..085178cc12a1750a9b90d54198f8f53ad7c72f49 100644 (file)
@@ -10,6 +10,7 @@ option(OPENMP "Use OpenMP library. Works with FFTW and OpenCV implementation." O
 option(ASYNC "Works only if OPENCV_CUFFT is not ON. Will enable C++ async directive." OFF)
 option(CUDA_DEBUG "Enables error cheking for cuda and cufft. " OFF)
 option(BIG_BATCH "Enable transforming all features from all scales together." OFF)
+option(TEMPLATE_COMPLEXMAT "Use ComplexMat as abstract class." ON)
 
 IF(PROFILING)
   add_definitions(-DPROFILING )
@@ -21,6 +22,11 @@ IF(BIG_BATCH)
   MESSAGE(STATUS "Big_batch mode")
 ENDIF()
 
+IF(TEMPLATE_COMPLEXMAT)
+  add_definitions(-DTEMPLATE_COMPLEXMAT )
+  MESSAGE(STATUS "ComplexMat abstract class version.")
+ENDIF()
+
 SET(use_cuda OFF)
 
 IF(FFT STREQUAL "OpenCV")
@@ -81,14 +87,19 @@ IF(use_cuda)
   cuda_add_library(complexmat complexmat.cu)
   cuda_add_library(cuda_func cuda_functions.cu)
   ENDIF()
-  
+
 ENDIF()
 
 add_subdirectory(piotr_fhog)
 add_subdirectory(cn)
 
 add_library(kcf STATIC ${KCF_LIB_SRC})
-target_link_libraries(kcf fhog cndata  ${OpenCV_LIBS})
+IF(NOT TEMPLATE_COMPLEXMAT)
+    add_library(complexmat complexmat.cpp)
+    target_link_libraries(kcf fhog cndata complexmat ${OpenCV_LIBS})
+ELSE()
+    target_link_libraries(kcf fhog cndata ${OpenCV_LIBS})
+ENDIF()
 set_target_properties(kcf PROPERTIES VERSION 1.0.0 SOVERSION 1)
 
 IF(FFT STREQUAL "fftw")
diff --git a/src/complexmat.cpp b/src/complexmat.cpp
new file mode 100644 (file)
index 0000000..72a2a3f
--- /dev/null
@@ -0,0 +1,231 @@
+#include "complexmat.hpp"
+
+ComplexMat::ComplexMat() : cols(0), rows(0), n_channels(0) {}
+ComplexMat::ComplexMat(int _rows, int _cols, int _n_channels) : cols(_cols), rows(_rows), n_channels(_n_channels)
+{
+    p_data.resize(n_channels*cols*rows);
+}
+
+
+//assuming that mat has 2 channels (real, img)
+ComplexMat::ComplexMat(const cv::Mat & mat) : cols(mat.cols), rows(mat.rows), n_channels(1)
+{
+    p_data = convert(mat);
+}
+
+void ComplexMat::create(int _rows, int _cols, int _n_channels)
+{
+    rows = _rows;
+    cols = _cols;
+    n_channels = _n_channels;
+    p_data.resize(n_channels*cols*rows);
+}
+
+void ComplexMat::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
+cv::Size ComplexMat::size() { return cv::Size(cols, rows); }
+int ComplexMat::channels() { return n_channels; }
+int ComplexMat::channels() const { return n_channels; }
+
+//assuming that mat has 2 channels (real, imag)
+void ComplexMat::set_channel(int idx, const cv::Mat & mat)
+{
+    assert(idx >= 0 && idx < n_channels);
+    for (int i = 0; i < rows; ++i){
+        const std::complex<float> *row = mat.ptr<std::complex<float>>(i);
+        for (int j = 0; j < cols; ++j)
+            p_data[idx*rows*cols+i*cols+j]=row[j];
+    }
+}
+
+
+void ComplexMat::sqr_norm(float *sums_sqr_norms) const
+{
+    int n_channels_per_scale = n_channels/n_scales;
+    int scale_offset = n_channels_per_scale*rows*cols;
+    float 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<float>(cols*rows);
+    }
+    return;
+}
+
+ComplexMat ComplexMat::sqr_mag() const
+{
+    return mat_const_operator( [](std::complex<float> & c) { c = c.real()*c.real() + c.imag()*c.imag(); } );
+}
+
+ComplexMat ComplexMat::conj() const
+{
+    return mat_const_operator( [](std::complex<float> & c) { c = std::complex<float>(c.real(), -c.imag()); } );
+}
+
+ComplexMat ComplexMat::sum_over_channels() const
+{
+    assert(p_data.size() > 1);
+
+    int n_channels_per_scale = n_channels/n_scales;
+    int scale_offset = n_channels_per_scale*rows*cols;
+
+    ComplexMat result(this->rows, this->cols, n_scales);
+    for (int scale = 0; scale < n_scales; ++scale) {
+        std::copy(p_data.begin()+scale*scale_offset,p_data.begin()+rows*cols+scale*scale_offset, result.p_data.begin()+scale*rows*cols);
+        for (int i = 1; i < n_channels_per_scale; ++i) {
+            std::transform(result.p_data.begin()+scale*rows*cols, result.p_data.begin()+(scale+1)*rows*cols, p_data.begin()+i*rows*cols+scale*scale_offset,
+                           result.p_data.begin()+scale*rows*cols, std::plus<std::complex<float>>());
+        }
+    }
+    return result;
+}
+
+//return 2 channels (real, imag) for first complex channel
+cv::Mat ComplexMat::to_cv_mat() const
+{
+    assert(p_data.size() >= 1);
+    return channel_to_cv_mat(0);
+}
+// return a vector of 2 channels (real, imag) per one complex channel
+std::vector<cv::Mat> ComplexMat::to_cv_mat_vector() const
+{
+    std::vector<cv::Mat> result;
+    result.reserve(n_channels);
+
+    for (int i = 0; i < n_channels; ++i)
+        result.push_back(channel_to_cv_mat(i));
+
+    return result;
+}
+
+std::complex<float>* ComplexMat::get_p_data() const
+{
+    return p_data.data();
+}
+
+//element-wise per channel multiplication, division and addition
+ComplexMat ComplexMat::operator*(const ComplexMat & rhs) const
+{
+    return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
+}
+ComplexMat ComplexMat::operator/(const ComplexMat & rhs) const
+{
+    return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs /= c_rhs; }, rhs);
+}
+ComplexMat ComplexMat::operator+(const ComplexMat & rhs) const
+{
+    return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs)  { c_lhs += c_rhs; }, rhs);
+}
+
+//multiplying or adding constant
+ComplexMat ComplexMat::operator*(const float & rhs) const
+{
+    return ComplexMat::mat_const_operator( [&rhs](std::complex<float> & c) { c *= rhs; });
+}
+ComplexMat ComplexMat::operator+(const float & rhs) const
+{
+    return ComplexMat::mat_const_operator( [&rhs](std::complex<float> & c) { c += rhs; });
+}
+
+//multiplying element-wise multichannel by one channel mats (rhs mat is with one channel)
+ComplexMat ComplexMat::mul(const ComplexMat & rhs) const
+{
+    return ComplexMat::matn_mat1_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
+}
+
+//multiplying element-wise multichannel by one channel mats (rhs mat is with multiple channel)
+ComplexMat ComplexMat::mul2(const ComplexMat & rhs) const
+{
+    return ComplexMat::matn_mat2_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
+}
+
+
+//convert 2 channel mat (real, imag) to vector row-by-row
+std::vector<std::complex<float>> ComplexMat::convert(const cv::Mat & mat)
+{
+    std::vector<std::complex<float>> result;
+    result.reserve(mat.cols*mat.rows);
+    for (int y = 0; y < mat.rows; ++y) {
+        const float * row_ptr = mat.ptr<float>(y);
+        for (int x = 0; x < 2*mat.cols; x += 2){
+            result.push_back(std::complex<float>(row_ptr[x], row_ptr[x+1]));
+        }
+    }
+    return result;
+}
+
+ComplexMat ComplexMat::mat_mat_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
+{
+    assert(mat_rhs.n_channels == n_channels && mat_rhs.cols == cols && mat_rhs.rows == rows);
+
+    ComplexMat result = *this;
+    for (int i = 0; i < n_channels; ++i) {
+        auto lhs = result.p_data.begin()+i*rows*cols;
+        auto rhs = mat_rhs.p_data.begin()+i*rows*cols;
+        for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
+            op(*lhs, *rhs);
+    }
+
+    return result;
+}
+ComplexMat ComplexMat::matn_mat1_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
+{
+    assert(mat_rhs.n_channels == 1 && mat_rhs.cols == cols && mat_rhs.rows == rows);
+
+    ComplexMat result = *this;
+    for (int i = 0; i < n_channels; ++i) {
+        auto lhs = result.p_data.begin()+i*rows*cols;
+        auto rhs = mat_rhs.p_data.begin();
+        for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
+            op(*lhs, *rhs);
+    }
+
+    return result;
+}
+ComplexMat ComplexMat::matn_mat2_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
+{
+    assert(mat_rhs.n_channels == n_channels/n_scales && mat_rhs.cols == cols && mat_rhs.rows == rows);
+
+    int n_channels_per_scale = n_channels/n_scales;
+    int scale_offset = n_channels_per_scale*rows*cols;
+    ComplexMat result = *this;
+    for (int i = 0; i < n_scales; ++i) {
+        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()+((j+1)*rows*cols)+(i*scale_offset); ++lhs, ++rhs)
+                op(*lhs, *rhs);
+        }
+    }
+
+    return result;
+}
+ComplexMat ComplexMat::mat_const_operator(const std::function<void(std::complex<float> & c_rhs)> & op) const
+{
+    ComplexMat result = *this;
+    for (int i = 0; i < n_channels; ++i)
+        for (auto lhs = result.p_data.begin()+i*rows*cols; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs)
+            op(*lhs);
+    return result;
+}
+
+cv::Mat ComplexMat::channel_to_cv_mat(int channel_id) const
+{
+    cv::Mat result(rows, cols, CV_32FC2);
+    for (int y = 0; y < rows; ++y) {
+        std::complex<float> * row_ptr = result.ptr<std::complex<float>>(y);
+        for (int x = 0; x < cols; ++x){
+            row_ptr[x] = p_data[channel_id*rows*cols+y*cols+x];
+        }
+    }
+    return result;
+}
index 5ef40e7d39f4ff335275067cbcd46eb37e8b7dcc..22560c8839248f7d4cbbd91d55435a511b578e64 100644 (file)
@@ -6,6 +6,7 @@
 #include <algorithm>
 #include <functional>
 
+#ifdef TEMPLATE_COMPLEXMAT
 template<typename T> class ComplexMat_
 {
 public:
@@ -88,10 +89,10 @@ public:
     ComplexMat_<T> sum_over_channels() const
     {
         assert(p_data.size() > 1);
-        
+
         int n_channels_per_scale = n_channels/n_scales;
         int scale_offset = n_channels_per_scale*rows*cols;
-        
+
         ComplexMat_<T> result(this->rows, this->cols, n_scales);
         for (int scale = 0; scale < n_scales; ++scale) {
             std::copy(p_data.begin()+scale*scale_offset,p_data.begin()+rows*cols+scale*scale_offset, result.p_data.begin()+scale*rows*cols);
@@ -180,7 +181,7 @@ public:
 
 private:
     mutable std::vector<std::complex<T>> p_data;
-    
+
     //convert 2 channel mat (real, imag) to vector row-by-row
     std::vector<std::complex<T>> convert(const cv::Mat & mat)
     {
@@ -265,6 +266,91 @@ private:
 };
 
 typedef ComplexMat_<float> ComplexMat;
+#else
+class ComplexMat
+{
+public:
+    int cols;
+    int rows;
+    int n_channels;
+    int n_scales = 1;
+
+    ComplexMat();
+    ComplexMat(int _rows, int _cols, int _n_channels);
+    ComplexMat(const cv::Mat & mat);
+
+    void create(int _rows, int _cols, int _n_channels);
+
+    void create(int _rows, int _cols, int _n_channels, int _n_scales);
+    // cv::Mat API compatibility
+    cv::Size size();
+    int channels();
+    int channels() const;
+
+    //assuming that mat has 2 channels (real, imag)
+    void set_channel(int idx, const cv::Mat & mat);
+
+
+    void sqr_norm(float *sums_sqr_norms) const;
+
+    ComplexMat sqr_mag() const;
+
+    ComplexMat conj() const;
+
+    ComplexMat sum_over_channels() const;
+
+    //return 2 channels (real, imag) for first complex channel
+    cv::Mat to_cv_mat() const;
+    // return a vector of 2 channels (real, imag) per one complex channel
+    std::vector<cv::Mat> to_cv_mat_vector() const;
+
+    std::complex<float>* get_p_data() const;
+
+    //element-wise per channel multiplication, division and addition
+    ComplexMat operator*(const ComplexMat & rhs) const;
+    ComplexMat operator/(const ComplexMat & rhs) const;
+    ComplexMat operator+(const ComplexMat & rhs) const;
+
+    //multiplying or adding constant
+    ComplexMat operator*(const float & rhs) const;
+    ComplexMat operator+(const float & rhs) const;
+
+    //multiplying element-wise multichannel by one channel mats (rhs mat is with one channel)
+    ComplexMat mul(const ComplexMat & rhs) const;
 
+    //multiplying element-wise multichannel by one channel mats (rhs mat is with multiple channel)
+    ComplexMat mul2(const ComplexMat & rhs) const;
+
+    //text output
+    friend std::ostream & operator<<(std::ostream & os, const ComplexMat & mat)
+    {
+        //for (int i = 0; i < mat.n_channels; ++i){
+        for (int i = 0; i < 1; ++i){
+            os << "Channel " << i << std::endl;
+            for (int j = 0; j < mat.rows; ++j) {
+                for (int k = 0; k < mat.cols-1; ++k)
+                    os << mat.p_data[j*mat.cols + k] << ", ";
+                os << mat.p_data[j*mat.cols + mat.cols-1] << std::endl;
+            }
+        }
+        return os;
+    }
+
+
+private:
+    mutable std::vector<std::complex<float>> p_data;
+
+    //convert 2 channel mat (real, imag) to vector row-by-row
+    std::vector<std::complex<float>> convert(const cv::Mat & mat);
+
+    ComplexMat mat_mat_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const;
+    ComplexMat matn_mat1_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const;
+    ComplexMat matn_mat2_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const;
+    ComplexMat mat_const_operator(const std::function<void(std::complex<float> & c_rhs)> & op) const;
+
+    cv::Mat channel_to_cv_mat(int channel_id) const;
+
+};
+#endif
 
-#endif //COMPLEX_MAT_HPP_213123048309482094
\ No newline at end of file
+#endif //COMPLEX_MAT_HPP_213123048309482094