1 #include "complexmat.hpp"
3 ComplexMat::ComplexMat() : cols(0), rows(0), n_channels(0) {}
4 ComplexMat::ComplexMat(int _rows, int _cols, int _n_channels) : cols(_cols), rows(_rows), n_channels(_n_channels)
6 p_data.resize(n_channels*cols*rows);
10 //assuming that mat has 2 channels (real, img)
11 ComplexMat::ComplexMat(const cv::Mat & mat) : cols(mat.cols), rows(mat.rows), n_channels(1)
13 p_data = convert(mat);
16 void ComplexMat::create(int _rows, int _cols, int _n_channels)
20 n_channels = _n_channels;
21 p_data.resize(n_channels*cols*rows);
24 void ComplexMat::create(int _rows, int _cols, int _n_channels, int _n_scales)
28 n_channels = _n_channels;
30 p_data.resize(n_channels*cols*rows);
32 // cv::Mat API compatibility
33 cv::Size ComplexMat::size() { return cv::Size(cols, rows); }
34 int ComplexMat::channels() { return n_channels; }
35 int ComplexMat::channels() const { return n_channels; }
37 //assuming that mat has 2 channels (real, imag)
38 void ComplexMat::set_channel(int idx, const cv::Mat & mat)
40 assert(idx >= 0 && idx < n_channels);
41 for (int i = 0; i < rows; ++i){
42 const std::complex<float> *row = mat.ptr<std::complex<float>>(i);
43 for (int j = 0; j < cols; ++j)
44 p_data[idx*rows*cols+i*cols+j]=row[j];
49 void ComplexMat::sqr_norm(float *sums_sqr_norms) const
51 int n_channels_per_scale = n_channels/n_scales;
52 int scale_offset = n_channels_per_scale*rows*cols;
54 for (int scale = 0; scale < n_scales; ++scale) {
56 for (int i = 0; i < n_channels_per_scale; ++i)
57 for (auto lhs = p_data.begin()+i*rows*cols+scale*scale_offset; lhs != p_data.begin()+(i+1)*rows*cols+scale*scale_offset; ++lhs)
58 sum_sqr_norm += lhs->real()*lhs->real() + lhs->imag()*lhs->imag();
59 sums_sqr_norms[scale] = sum_sqr_norm/static_cast<float>(cols*rows);
64 ComplexMat ComplexMat::sqr_mag() const
66 return mat_const_operator( [](std::complex<float> & c) { c = c.real()*c.real() + c.imag()*c.imag(); } );
69 ComplexMat ComplexMat::conj() const
71 return mat_const_operator( [](std::complex<float> & c) { c = std::complex<float>(c.real(), -c.imag()); } );
74 ComplexMat ComplexMat::sum_over_channels() const
76 assert(p_data.size() > 1);
78 int n_channels_per_scale = n_channels/n_scales;
79 int scale_offset = n_channels_per_scale*rows*cols;
81 ComplexMat result(this->rows, this->cols, n_scales);
82 for (int scale = 0; scale < n_scales; ++scale) {
83 std::copy(p_data.begin()+scale*scale_offset,p_data.begin()+rows*cols+scale*scale_offset, result.p_data.begin()+scale*rows*cols);
84 for (int i = 1; i < n_channels_per_scale; ++i) {
85 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,
86 result.p_data.begin()+scale*rows*cols, std::plus<std::complex<float>>());
92 //return 2 channels (real, imag) for first complex channel
93 cv::Mat ComplexMat::to_cv_mat() const
95 assert(p_data.size() >= 1);
96 return channel_to_cv_mat(0);
98 // return a vector of 2 channels (real, imag) per one complex channel
99 std::vector<cv::Mat> ComplexMat::to_cv_mat_vector() const
101 std::vector<cv::Mat> result;
102 result.reserve(n_channels);
104 for (int i = 0; i < n_channels; ++i)
105 result.push_back(channel_to_cv_mat(i));
110 std::complex<float>* ComplexMat::get_p_data() const
112 return p_data.data();
115 //element-wise per channel multiplication, division and addition
116 ComplexMat ComplexMat::operator*(const ComplexMat & rhs) const
118 return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
120 ComplexMat ComplexMat::operator/(const ComplexMat & rhs) const
122 return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs /= c_rhs; }, rhs);
124 ComplexMat ComplexMat::operator+(const ComplexMat & rhs) const
126 return ComplexMat::mat_mat_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs += c_rhs; }, rhs);
129 //multiplying or adding constant
130 ComplexMat ComplexMat::operator*(const float & rhs) const
132 return ComplexMat::mat_const_operator( [&rhs](std::complex<float> & c) { c *= rhs; });
134 ComplexMat ComplexMat::operator+(const float & rhs) const
136 return ComplexMat::mat_const_operator( [&rhs](std::complex<float> & c) { c += rhs; });
139 //multiplying element-wise multichannel by one channel mats (rhs mat is with one channel)
140 ComplexMat ComplexMat::mul(const ComplexMat & rhs) const
142 return ComplexMat::matn_mat1_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
145 //multiplying element-wise multichannel by one channel mats (rhs mat is with multiple channel)
146 ComplexMat ComplexMat::mul2(const ComplexMat & rhs) const
148 return ComplexMat::matn_mat2_operator( [](std::complex<float> & c_lhs, const std::complex<float> & c_rhs) { c_lhs *= c_rhs; }, rhs);
152 //convert 2 channel mat (real, imag) to vector row-by-row
153 std::vector<std::complex<float>> ComplexMat::convert(const cv::Mat & mat)
155 std::vector<std::complex<float>> result;
156 result.reserve(mat.cols*mat.rows);
157 for (int y = 0; y < mat.rows; ++y) {
158 const float * row_ptr = mat.ptr<float>(y);
159 for (int x = 0; x < 2*mat.cols; x += 2){
160 result.push_back(std::complex<float>(row_ptr[x], row_ptr[x+1]));
166 ComplexMat ComplexMat::mat_mat_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
168 assert(mat_rhs.n_channels == n_channels && mat_rhs.cols == cols && mat_rhs.rows == rows);
170 ComplexMat result = *this;
171 for (int i = 0; i < n_channels; ++i) {
172 auto lhs = result.p_data.begin()+i*rows*cols;
173 auto rhs = mat_rhs.p_data.begin()+i*rows*cols;
174 for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
180 ComplexMat ComplexMat::matn_mat1_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
182 assert(mat_rhs.n_channels == 1 && mat_rhs.cols == cols && mat_rhs.rows == rows);
184 ComplexMat result = *this;
185 for (int i = 0; i < n_channels; ++i) {
186 auto lhs = result.p_data.begin()+i*rows*cols;
187 auto rhs = mat_rhs.p_data.begin();
188 for ( ; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs, ++rhs)
194 ComplexMat ComplexMat::matn_mat2_operator(void (*op)(std::complex<float> & c_lhs, const std::complex<float> & c_rhs), const ComplexMat & mat_rhs) const
196 assert(mat_rhs.n_channels == n_channels/n_scales && mat_rhs.cols == cols && mat_rhs.rows == rows);
198 int n_channels_per_scale = n_channels/n_scales;
199 int scale_offset = n_channels_per_scale*rows*cols;
200 ComplexMat result = *this;
201 for (int i = 0; i < n_scales; ++i) {
202 for (int j = 0; j < n_channels_per_scale; ++j) {
203 auto lhs = result.p_data.begin()+(j*rows*cols)+(i*scale_offset);
204 auto rhs = mat_rhs.p_data.begin()+(j*rows*cols);
205 for ( ; lhs != result.p_data.begin()+((j+1)*rows*cols)+(i*scale_offset); ++lhs, ++rhs)
212 ComplexMat ComplexMat::mat_const_operator(const std::function<void(std::complex<float> & c_rhs)> & op) const
214 ComplexMat result = *this;
215 for (int i = 0; i < n_channels; ++i)
216 for (auto lhs = result.p_data.begin()+i*rows*cols; lhs != result.p_data.begin()+(i+1)*rows*cols; ++lhs)
221 cv::Mat ComplexMat::channel_to_cv_mat(int channel_id) const
223 cv::Mat result(rows, cols, CV_32FC2);
224 for (int y = 0; y < rows; ++y) {
225 std::complex<float> * row_ptr = result.ptr<std::complex<float>>(y);
226 for (int x = 0; x < cols; ++x){
227 row_ptr[x] = p_data[channel_id*rows*cols+y*cols+x];