1 #ifndef COMPLEX_MAT_HPP_213123048309482094
2 #define COMPLEX_MAT_HPP_213123048309482094
4 #include <opencv2/opencv.hpp>
10 #include "managed_allocator.h"
13 using managed_vector = std::vector<T,managed_allocator<T>>;
16 template<typename T> class ComplexMat_
24 ComplexMat_() : cols(0), rows(0), n_channels(0) {}
25 ComplexMat_(int _rows, int _cols, int _n_channels) : cols(_cols), rows(_rows), n_channels(_n_channels)
27 p_data.resize(n_channels*cols*rows);
31 //assuming that mat has 2 channels (real, img)
32 ComplexMat_(const cv::Mat & mat) : cols(mat.cols), rows(mat.rows), n_channels(1)
34 p_data = convert(mat);
37 ComplexMat_(int _rows, int _cols, int _n_channels,std::vector<std::complex<T>> data) : cols(_cols), rows(_rows), n_channels(_n_channels)
42 void create(int _rows, int _cols, int _n_channels)
46 n_channels = _n_channels;
47 p_data.resize(n_channels*cols*rows);
50 void create(int _rows, int _cols, int _n_channels, int _n_scales)
54 n_channels = _n_channels;
56 p_data.resize(n_channels*cols*rows);
58 // cv::Mat API compatibility
59 cv::Size size() { return cv::Size(cols, rows); }
60 int channels() { return n_channels; }
61 int channels() const { return n_channels; }
63 //assuming that mat has 2 channels (real, imag)
64 void set_channel(int idx, const cv::Mat & mat)
66 assert(idx >= 0 && idx < n_channels);
67 for (int i = 0; i < rows; ++i){
68 const std::complex<T> *row = mat.ptr<std::complex<T>>(i);
69 for (int j = 0; j < cols; ++j)
70 p_data[idx*rows*cols+i*cols+j]=row[j];
75 std::vector<T> sqr_norm() const
77 std::vector<T> sums_sqr_norms;
78 sums_sqr_norms.resize(n_scales);
79 int n_channels_per_scale = n_channels/n_scales;
80 int scale_offset = n_channels_per_scale*rows*cols;
82 for(int scale = 0; scale < n_scales; ++scale){
84 for (int i = 0; i < n_channels_per_scale; ++i)
85 for (auto lhs = p_data.begin()+i*rows*cols+scale*scale_offset; lhs != p_data.begin()+(i+1)*rows*cols+scale*scale_offset; ++lhs)
86 sum_sqr_norm += lhs->real()*lhs->real() + lhs->imag()*lhs->imag();
87 sums_sqr_norms[scale] = sum_sqr_norm/static_cast<T>(cols*rows);
89 return sums_sqr_norms;
92 ComplexMat_<T> sqr_mag() const
94 return mat_const_operator( [](std::complex<T> & c) { c = c.real()*c.real() + c.imag()*c.imag(); } );
97 ComplexMat_<T> conj() const
99 return mat_const_operator( [](std::complex<T> & c) { c = std::complex<T>(c.real(), -c.imag()); } );
102 ComplexMat_<T> sum_over_channels() const
104 assert(p_data.size() > 1);
105 ComplexMat_<T> result(this->rows, this->cols, 1);
106 std::copy(p_data.begin(),p_data.begin()+rows*cols, result.p_data.begin());
107 for (int i = 1; i < n_channels; ++i) {
108 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>>());
113 //return 2 channels (real, imag) for first complex channel
114 cv::Mat to_cv_mat() const
116 assert(p_data.size() >= 1);
117 return channel_to_cv_mat(0);
119 // return a vector of 2 channels (real, imag) per one complex channel
120 std::vector<cv::Mat> to_cv_mat_vector() const
122 std::vector<cv::Mat> result;
123 result.reserve(n_channels);
125 for (int i = 0; i < n_channels; ++i)
126 result.push_back(channel_to_cv_mat(i));
131 std::complex<T>* get_p_data() const
133 return p_data.data();
136 ComplexMat_<T> get_part(int id, int n_of_feat)
138 std::vector<std::complex<T>> data(p_data.begin()+id*rows*cols*n_of_feat,
139 p_data.begin()+(id+1)*rows*cols*n_of_feat);
140 ComplexMat_<T> result(this->rows,this->cols,n_of_feat,data);
144 //element-wise per channel multiplication, division and addition
145 ComplexMat_<T> operator*(const ComplexMat_<T> & rhs) const
147 return mat_mat_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs *= c_rhs; }, rhs);
149 ComplexMat_<T> operator/(const ComplexMat_<T> & rhs) const
151 return mat_mat_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs /= c_rhs; }, rhs);
153 ComplexMat_<T> operator+(const ComplexMat_<T> & rhs) const
155 return mat_mat_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs += c_rhs; }, rhs);
158 //multiplying or adding constant
159 ComplexMat_<T> operator*(const T & rhs) const
161 return mat_const_operator( [&rhs](std::complex<T> & c) { c *= rhs; });
163 ComplexMat_<T> operator+(const T & rhs) const
165 return mat_const_operator( [&rhs](std::complex<T> & c) { c += rhs; });
168 //multiplying element-wise multichannel by one channel mats (rhs mat is with one channel)
169 ComplexMat_<T> mul(const ComplexMat_<T> & rhs) const
171 return matn_mat1_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs *= c_rhs; }, rhs);
174 //multiplying element-wise multichannel by one channel mats (rhs mat is with multiple channel)
175 ComplexMat_<T> mul2(const ComplexMat_<T> & rhs) const
177 return matn_mat2_operator( [](std::complex<T> & c_lhs, const std::complex<T> & c_rhs) { c_lhs *= c_rhs; }, rhs);
181 friend std::ostream & operator<<(std::ostream & os, const ComplexMat_<T> & mat)
183 //for (int i = 0; i < mat.n_channels; ++i){
184 for (int i = 0; i < 1; ++i){
185 os << "Channel " << i << std::endl;
186 for (int j = 0; j < mat.rows; ++j) {
187 for (int k = 0; k < mat.cols-1; ++k)
188 os << mat.p_data[j*mat.cols + k] << ", ";
189 os << mat.p_data[j*mat.cols + mat.cols-1] << std::endl;
198 mutable managed_vector<std::complex<T>> p_data;
200 mutable std::vector<std::complex<T>> p_data;
202 //convert 2 channel mat (real, imag) to vector row-by-row
203 std::vector<std::complex<T>> convert(const cv::Mat & mat)
205 std::vector<std::complex<T>> result;
206 result.reserve(mat.cols*mat.rows);
207 for (int y = 0; y < mat.rows; ++y) {
208 const T * row_ptr = mat.ptr<T>(y);
209 for (int x = 0; x < 2*mat.cols; x += 2){
210 result.push_back(std::complex<T>(row_ptr[x], row_ptr[x+1]));
216 ComplexMat_<T> mat_mat_operator(void (*op)(std::complex<T> & c_lhs, const std::complex<T> & c_rhs), const ComplexMat_<T> & mat_rhs) const
218 assert(mat_rhs.n_channels == n_channels && mat_rhs.cols == cols && mat_rhs.rows == rows);
220 ComplexMat_<T> result = *this;
221 for (int i = 0; i < n_channels; ++i) {
222 auto lhs = result.p_data.begin()+i*rows*cols;
223 auto rhs = mat_rhs.p_data.begin()+i*rows*cols;
224 for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
230 ComplexMat_<T> matn_mat1_operator(void (*op)(std::complex<T> & c_lhs, const std::complex<T> & c_rhs), const ComplexMat_<T> & mat_rhs) const
232 assert(mat_rhs.n_channels == 1 && mat_rhs.cols == cols && mat_rhs.rows == rows);
234 ComplexMat_<T> result = *this;
235 for (int i = 0; i < n_channels; ++i) {
236 auto lhs = result.p_data.begin()+i*rows*cols;
237 auto rhs = mat_rhs.p_data.begin();
238 for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
244 ComplexMat_<T> matn_mat2_operator(void (*op)(std::complex<T> & c_lhs, const std::complex<T> & c_rhs), const ComplexMat_<T> & mat_rhs) const
246 assert(mat_rhs.n_channels == n_channels/n_scales && mat_rhs.cols == cols && mat_rhs.rows == rows);
248 int n_channels_per_scale = n_channels/n_scales;
249 int scale_offset = n_channels_per_scale*rows*cols;
250 ComplexMat_<T> result = *this;
251 for (int i = 0; i < n_scales; ++i) {
252 for (int j = 0; j < n_channels_per_scale; ++j) {
253 auto lhs = result.p_data.begin()+(j*rows*cols)+(i*scale_offset);
254 auto rhs = mat_rhs.p_data.begin()+(j*rows*cols);
255 for ( ; lhs != result.p_data.begin()+((j+1)*rows*cols)+(i*scale_offset); ++lhs, ++rhs)
262 ComplexMat_<T> mat_const_operator(const std::function<void(std::complex<T> & c_rhs)> & op) const
264 ComplexMat_<T> result = *this;
265 for (int i = 0; i < n_channels; ++i)
266 for (auto lhs = result.p_data.begin()+i*rows*cols; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs)
271 cv::Mat channel_to_cv_mat(int channel_id) const
273 cv::Mat result(rows, cols, CV_32FC2);
274 for (int y = 0; y < rows; ++y) {
275 std::complex<T> * row_ptr = result.ptr<std::complex<T>>(y);
276 for (int x = 0; x < cols; ++x){
277 row_ptr[x] = p_data[channel_id*rows*cols+y*cols+x];
285 typedef ComplexMat_<float> ComplexMat;
288 #endif //COMPLEX_MAT_HPP_213123048309482094