From d27068f79ada4d1a344d2e2381ee239af2946178 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 13 Feb 2014 15:15:05 +0400 Subject: [PATCH] some more refactoring --- modules/photo/src/arrays.hpp | 84 ++++++++++++------- modules/photo/src/denoising.cpp | 25 +++--- .../src/fast_nlmeans_denoising_invoker.hpp | 53 +++++------- ...fast_nlmeans_denoising_invoker_commons.hpp | 2 +- 4 files changed, 86 insertions(+), 78 deletions(-) diff --git a/modules/photo/src/arrays.hpp b/modules/photo/src/arrays.hpp index a33018e59..4aec5f7a1 100644 --- a/modules/photo/src/arrays.hpp +++ b/modules/photo/src/arrays.hpp @@ -39,10 +39,14 @@ // //M*/ +#include "opencv2/core/base.hpp" + #ifndef __OPENCV_DENOISING_ARRAYS_HPP__ #define __OPENCV_DENOISING_ARRAYS_HPP__ -template struct Array2d { +template +struct Array2d +{ T* a; int n1,n2; bool needToDeallocArray; @@ -50,14 +54,16 @@ template struct Array2d { Array2d(const Array2d& array2d): a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false) { - if (array2d.needToDeallocArray) { - // copy constructor for self allocating arrays not supported - throw new std::exception(); + if (array2d.needToDeallocArray) + { + CV_Error(Error::BadDataPtr, "Copy constructor for self allocating arrays not supported"); } } Array2d(T* _a, int _n1, int _n2): - a(_a), n1(_n1), n2(_n2), needToDeallocArray(false) {} + a(_a), n1(_n1), n2(_n2), needToDeallocArray(false) + { + } Array2d(int _n1, int _n2): n1(_n1), n2(_n2), needToDeallocArray(true) @@ -65,28 +71,34 @@ template struct Array2d { a = new T[n1*n2]; } - ~Array2d() { - if (needToDeallocArray) { + ~Array2d() + { + if (needToDeallocArray) delete[] a; - } } - T* operator [] (int i) { + T* operator [] (int i) + { return a + i*n2; } - inline T* row_ptr(int i) { + inline T* row_ptr(int i) + { return (*this)[i]; } }; -template struct Array3d { +template +struct Array3d +{ T* a; int n1,n2,n3; bool needToDeallocArray; Array3d(T* _a, int _n1, int _n2, int _n3): - a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false) {} + a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false) + { + } Array3d(int _n1, int _n2, int _n3): n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true) @@ -94,64 +106,72 @@ template struct Array3d { a = new T[n1*n2*n3]; } - ~Array3d() { - if (needToDeallocArray) { + ~Array3d() + { + if (needToDeallocArray) delete[] a; - } } - Array2d operator [] (int i) { + Array2d operator [] (int i) + { Array2d array2d(a + i*n2*n3, n2, n3); return array2d; } - inline T* row_ptr(int i1, int i2) { + inline T* row_ptr(int i1, int i2) + { return a + i1*n2*n3 + i2*n3; } }; -template struct Array4d { +template +struct Array4d +{ T* a; int n1,n2,n3,n4; bool needToDeallocArray; int steps[4]; - void init_steps() { + void init_steps() + { steps[0] = n2*n3*n4; steps[1] = n3*n4; steps[2] = n4; steps[3] = 1; } - Array4d(T* _a, int _n1, int _n2, int _n3, int _n4): + Array4d(T* _a, int _n1, int _n2, int _n3, int _n4) : a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false) - { + { init_steps(); - } + } - Array4d(int _n1, int _n2, int _n3, int _n4): + Array4d(int _n1, int _n2, int _n3, int _n4) : n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true) { a = new T[n1*n2*n3*n4]; init_steps(); - } - - ~Array4d() { - if (needToDeallocArray) { - delete[] a; - } } - Array3d operator [] (int i) { + ~Array4d() + { + if (needToDeallocArray) + delete[] a; + } + + Array3d operator [] (int i) + { Array3d array3d(a + i*n2*n3*n4, n2, n3, n4); return array3d; } - inline T* row_ptr(int i1, int i2, int i3) { + inline T* row_ptr(int i1, int i2, int i3) + { return a + i1*n2*n3*n4 + i2*n3*n4 + i3*n4; } - inline int step_size(int dimension) { + inline int step_size(int dimension) + { return steps[dimension]; } }; diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index 166d7f892..c9a711b32 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -117,7 +117,8 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( int templateWindowSize, int searchWindowSize) { int src_imgs_size = static_cast(srcImgs.size()); - if (src_imgs_size == 0) { + if (src_imgs_size == 0) + { CV_Error(Error::StsBadArg, "Input images vector should not be empty!"); } @@ -136,11 +137,11 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( "should be choosen corresponding srcImgs size!"); } - for (int i = 1; i < src_imgs_size; i++) { - if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type()) { + for (int i = 1; i < src_imgs_size; i++) + if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type()) + { CV_Error(Error::StsBadArg, "Input images should have the same size and type!"); } - } } void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, @@ -152,12 +153,13 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds fastNlMeansDenoisingMultiCheckPreconditions( srcImgs, imgToDenoiseIndex, - temporalWindowSize, templateWindowSize, searchWindowSize - ); + temporalWindowSize, templateWindowSize, searchWindowSize); + _dst.create(srcImgs[0].size(), srcImgs[0].type()); Mat dst = _dst.getMat(); - switch (srcImgs[0].type()) { + switch (srcImgs[0].type()) + { case CV_8U: parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker( @@ -192,15 +194,15 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr fastNlMeansDenoisingMultiCheckPreconditions( srcImgs, imgToDenoiseIndex, - temporalWindowSize, templateWindowSize, searchWindowSize - ); + temporalWindowSize, templateWindowSize, searchWindowSize); _dst.create(srcImgs[0].size(), srcImgs[0].type()); Mat dst = _dst.getMat(); int src_imgs_size = static_cast(srcImgs.size()); - if (srcImgs[0].type() != CV_8UC3) { + if (srcImgs[0].type() != CV_8UC3) + { CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!"); return; } @@ -211,7 +213,8 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr std::vector src_lab(src_imgs_size); std::vector l(src_imgs_size); std::vector ab(src_imgs_size); - for (int i = 0; i < src_imgs_size; i++) { + for (int i = 0; i < src_imgs_size; i++) + { src_lab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC3); l[i] = Mat::zeros(srcImgs[0].size(), CV_8UC1); ab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC2); diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp index b274c6889..b8f5a0392 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp @@ -101,7 +101,7 @@ inline int getNearestPowerOf2(int value) template FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( - const cv::Mat& src, cv::Mat& dst, + const Mat& src, Mat& dst, int template_window_size, int search_window_size, const float h) : @@ -115,22 +115,20 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( search_window_size_ = search_window_half_size_ * 2 + 1; border_size_ = search_window_half_size_ + template_window_half_size_; - copyMakeBorder(src_, extended_src_, - border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT); + copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, BORDER_DEFAULT); const int max_estimate_sum_value = search_window_size_ * search_window_size_ * 255; fixed_point_mult_ = std::numeric_limits::max() / max_estimate_sum_value; // precalc weight for every possible l2 dist between blocks // additional optimization of precalced weights to replace division(averaging) by binary shift - - CV_Assert(template_window_size_ <= 46340 ); // sqrt(INT_MAX) + CV_Assert(template_window_size_ <= 46340); // sqrt(INT_MAX) int template_window_size_sq = template_window_size_ * template_window_size_; almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq); double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq; int max_dist = 255 * 255 * sizeof(T); - int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1); + int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1); almost_dist2weight_.resize(almost_max_dist); const double WEIGHT_THRESHOLD = 0.001; @@ -157,12 +155,14 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const int row_from = range.start; int row_to = range.end - 1; + // sums of cols anf rows for current pixel p Array2d dist_sums(search_window_size_, search_window_size_); - // for lazy calc optimization + // for lazy calc optimization (sum of cols for current pixel) Array3d col_dist_sums(template_window_size_, search_window_size_, search_window_size_); int first_col_num = -1; + // last elements of column sum (for each element in row) Array3d up_col_dist_sums(src_.cols, search_window_size_, search_window_size_); for (int i = row_from; i <= row_to; i++) @@ -177,7 +177,6 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const { calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums); first_col_num = 0; - } else { @@ -186,7 +185,6 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const { calcDistSumsForElementInFirstRow(i, j, first_col_num, dist_sums, col_dist_sums, up_col_dist_sums); - } else { @@ -204,29 +202,23 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const for (int y = 0; y < search_window_size; y++) { - int* dist_sums_row = dist_sums.row_ptr(y); + int * dist_sums_row = dist_sums.row_ptr(y); + int * col_dist_sums_row = col_dist_sums.row_ptr(first_col_num, y); + int * up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y); - int* col_dist_sums_row = col_dist_sums.row_ptr(first_col_num,y); - int* up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y); - - const T* b_up_ptr = extended_src_.ptr(start_by - template_window_half_size_ - 1 + y); - const T* b_down_ptr = extended_src_.ptr(start_by + template_window_half_size_ + y); + const T * b_up_ptr = extended_src_.ptr(start_by - template_window_half_size_ - 1 + y); + const T * b_down_ptr = extended_src_.ptr(start_by + template_window_half_size_ + y); for (int x = 0; x < search_window_size; x++) { + // remove from current pixel sum column sum with index "first_col_num" dist_sums_row[x] -= col_dist_sums_row[x]; - col_dist_sums_row[x] = - up_col_dist_sums_row[x] + - calcUpDownDist( - a_up, a_down, - b_up_ptr[start_bx + x], b_down_ptr[start_bx + x] - ); + int bx = start_bx + x; + col_dist_sums_row[x] = up_col_dist_sums_row[x] + calcUpDownDist(a_up, a_down, b_up_ptr[bx], b_down_ptr[bx]); dist_sums_row[x] += col_dist_sums_row[x]; - up_col_dist_sums_row[x] = col_dist_sums_row[x]; - } } } @@ -235,9 +227,7 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const } // calc weights - int weights_sum = 0; - - int estimation[3]; + int estimation[3], weights_sum = 0; for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) estimation[channel_num] = 0; @@ -247,9 +237,7 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) const int* dist_sums_row = dist_sums.row_ptr(y); for (int x = 0; x < search_window_size_; x++) { - int almostAvgDist = - dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_; - + int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_; int weight = almost_dist2weight_[almostAvgDist]; weights_sum += weight; @@ -302,9 +290,7 @@ inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElementInRow( template inline void FastNlMeansDenoisingInvoker::calcDistSumsForElementInFirstRow( - int i, - int j, - int first_col_num, + int i, int j, int first_col_num, Array2d& dist_sums, Array3d& col_dist_sums, Array3d& up_col_dist_sums) const @@ -326,8 +312,7 @@ inline void FastNlMeansDenoisingInvoker::calcDistSumsForElementInFirstRow( int by = start_by + y; int bx = start_bx + x; for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) - col_dist_sums[new_last_col_num][y][x] += - calcDist(extended_src_, ay + ty, ax, by + ty, bx); + col_dist_sums[new_last_col_num][y][x] += calcDist(extended_src_, ay + ty, ax, by + ty, bx); dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x]; up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x]; diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp index 3e8f4c498..7a2650077 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp @@ -70,7 +70,7 @@ template static inline int calcDist(const Mat& m, int i1, int j1, i template static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down) { - return calcDist(a_down,b_down) - calcDist(a_up, b_up); + return calcDist(a_down, b_down) - calcDist(a_up, b_up); } template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uchar b_down)