diff --git a/modules/photo/src/arrays.hpp b/modules/photo/src/arrays.hpp index 0d86cb6e3..cb434a611 100644 --- a/modules/photo/src/arrays.hpp +++ b/modules/photo/src/arrays.hpp @@ -47,20 +47,20 @@ template struct Array2d { int n1,n2; bool needToDeallocArray; - Array2d(const Array2d& array2d): - a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false) + 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 exception(); } } - - Array2d(T* _a, int _n1, int _n2): + + Array2d(T* _a, int _n1, int _n2): a(_a), n1(_n1), n2(_n2), needToDeallocArray(false) {} - Array2d(int _n1, int _n2): - n1(_n1), n2(_n2), needToDeallocArray(true) + Array2d(int _n1, int _n2): + n1(_n1), n2(_n2), needToDeallocArray(true) { a = new T[n1*n2]; } @@ -74,7 +74,7 @@ template struct Array2d { T* operator [] (int i) { return a + i*n2; } - + inline T* row_ptr(int i) { return (*this)[i]; } @@ -84,12 +84,12 @@ template struct Array3d { T* a; int n1,n2,n3; bool needToDeallocArray; - - Array3d(T* _a, int _n1, int _n2, int _n3): + + Array3d(T* _a, int _n1, int _n2, int _n3): 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) + Array3d(int _n1, int _n2, int _n3): + n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true) { a = new T[n1*n2*n3]; } @@ -115,25 +115,25 @@ template struct Array4d { int n1,n2,n3,n4; bool needToDeallocArray; int steps[4]; - + void init_steps() { - steps[0] = n2*n3*n4; - steps[1] = n3*n4; - steps[2] = n4; - steps[3] = 1; + 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): - a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false) + 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(); + init_steps(); } - Array4d(int _n1, int _n2, int _n3, int _n4): - n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true) + 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(); + a = new T[n1*n2*n3*n4]; + init_steps(); } ~Array4d() { diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index 42620575b..d3f1c09aa 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -51,37 +51,37 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, Mat src = _src.getMat(); _dst.create(src.size(), src.type()); Mat dst = _dst.getMat(); - + switch (src.type()) { case CV_8U: - parallel_for(cv::BlockedRange(0, src.rows), + parallel_for(cv::BlockedRange(0, src.rows), FastNlMeansDenoisingInvoker( src, dst, templateWindowSize, searchWindowSize, h)); break; case CV_8UC2: - parallel_for(cv::BlockedRange(0, src.rows), + parallel_for(cv::BlockedRange(0, src.rows), FastNlMeansDenoisingInvoker( src, dst, templateWindowSize, searchWindowSize, h)); break; case CV_8UC3: - parallel_for(cv::BlockedRange(0, src.rows), + parallel_for(cv::BlockedRange(0, src.rows), FastNlMeansDenoisingInvoker( src, dst, templateWindowSize, searchWindowSize, h)); break; default: - CV_Error(CV_StsBadArg, - "Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported"); + CV_Error(CV_StsBadArg, + "Unsupported image format! Only CV_8UC1, CV_8UC2 and CV_8UC3 are supported"); } } void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, - int templateWindowSize, int searchWindowSize, + int templateWindowSize, int searchWindowSize, int h, int hForColorComponents) { Mat src = _src.getMat(); _dst.create(src.size(), src.type()); Mat dst = _dst.getMat(); - + if (src.type() != CV_8UC3) { CV_Error(CV_StsBadArg, "Type of input image should be CV_8UC3!"); return; @@ -89,13 +89,13 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, Mat src_lab; cvtColor(src, src_lab, CV_LBGR2Lab); - + Mat l(src.size(), CV_8U); Mat ab(src.size(), CV_8UC2); Mat l_ab[] = { l, ab }; int from_to[] = { 0,0, 1,1, 2,2 }; mixChannels(&src_lab, 1, l_ab, 2, from_to, 3); - + fastNlMeansDenoising(l, l, templateWindowSize, searchWindowSize, h); fastNlMeansDenoising(ab, ab, templateWindowSize, searchWindowSize, hForColorComponents); @@ -106,10 +106,10 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, cvtColor(dst_lab, dst, CV_Lab2LBGR); } -static void fastNlMeansDenoisingMultiCheckPreconditions( - const std::vector& srcImgs, +static void fastNlMeansDenoisingMultiCheckPreconditions( + const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, - int templateWindowSize, int searchWindowSize) + int templateWindowSize, int searchWindowSize) { int src_imgs_size = (int)srcImgs.size(); if (src_imgs_size == 0) { @@ -123,10 +123,10 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( } int temporalWindowHalfSize = temporalWindowSize / 2; - if (imgToDenoiseIndex - temporalWindowHalfSize < 0 || - imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size) - { - CV_Error(CV_StsBadArg, + if (imgToDenoiseIndex - temporalWindowHalfSize < 0 || + imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size) + { + CV_Error(CV_StsBadArg, "imgToDenoiseIndex and temporalWindowSize " "should be choosen corresponding srcImgs size!"); } @@ -138,16 +138,16 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( } } -void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, +void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, int imgToDenoiseIndex, int temporalWindowSize, OutputArray _dst, int templateWindowSize, int searchWindowSize, int h) { vector srcImgs; _srcImgs.getMatVector(srcImgs); - + fastNlMeansDenoisingMultiCheckPreconditions( - srcImgs, imgToDenoiseIndex, + srcImgs, imgToDenoiseIndex, temporalWindowSize, templateWindowSize, searchWindowSize ); _dst.create(srcImgs[0].size(), srcImgs[0].type()); @@ -155,43 +155,43 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, switch (srcImgs[0].type()) { case CV_8U: - parallel_for(cv::BlockedRange(0, srcImgs[0].rows), + parallel_for(cv::BlockedRange(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, + srcImgs, imgToDenoiseIndex, temporalWindowSize, dst, templateWindowSize, searchWindowSize, h)); break; case CV_8UC2: - parallel_for(cv::BlockedRange(0, srcImgs[0].rows), + parallel_for(cv::BlockedRange(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, + srcImgs, imgToDenoiseIndex, temporalWindowSize, dst, templateWindowSize, searchWindowSize, h)); break; case CV_8UC3: - parallel_for(cv::BlockedRange(0, srcImgs[0].rows), + parallel_for(cv::BlockedRange(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, + srcImgs, imgToDenoiseIndex, temporalWindowSize, dst, templateWindowSize, searchWindowSize, h)); break; default: - CV_Error(CV_StsBadArg, + CV_Error(CV_StsBadArg, "Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported"); } } -void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, +void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, int imgToDenoiseIndex, int temporalWindowSize, OutputArray _dst, - int templateWindowSize, int searchWindowSize, + int templateWindowSize, int searchWindowSize, int h, int hForColorComponents) { vector srcImgs; _srcImgs.getMatVector(srcImgs); - + fastNlMeansDenoisingMultiCheckPreconditions( - srcImgs, imgToDenoiseIndex, + srcImgs, imgToDenoiseIndex, temporalWindowSize, templateWindowSize, searchWindowSize ); - + _dst.create(srcImgs[0].size(), srcImgs[0].type()); Mat dst = _dst.getMat(); @@ -207,26 +207,26 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, // TODO convert only required images vector src_lab(src_imgs_size); vector l(src_imgs_size); - vector ab(src_imgs_size); + vector ab(src_imgs_size); 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); cvtColor(srcImgs[i], src_lab[i], CV_LBGR2Lab); - + Mat l_ab[] = { l[i], ab[i] }; mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3); } - + Mat dst_l; Mat dst_ab; fastNlMeansDenoisingMulti( - l, imgToDenoiseIndex, temporalWindowSize, + l, imgToDenoiseIndex, temporalWindowSize, dst_l, templateWindowSize, searchWindowSize, h); fastNlMeansDenoisingMulti( - ab, imgToDenoiseIndex, temporalWindowSize, + ab, imgToDenoiseIndex, temporalWindowSize, dst_ab, templateWindowSize, searchWindowSize, hForColorComponents); Mat l_ab_denoised[] = { dst_l, dst_ab }; diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp index 82839c98b..07159bba4 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp @@ -56,17 +56,15 @@ using namespace cv; template struct FastNlMeansDenoisingInvoker { - public: - FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, + public: + FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, int template_window_size, int search_window_size, const double h); void operator() (const BlockedRange& range) const; - void operator= (const FastNlMeansDenoisingInvoker&) { - CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented"); - } - private: + void operator= (const FastNlMeansDenoisingInvoker&); + const Mat& src_; Mat& dst_; @@ -80,41 +78,48 @@ struct FastNlMeansDenoisingInvoker { int search_window_half_size_; int fixed_point_mult_; - int almost_template_window_size_sq_bin_shift; - vector almost_dist2weight; + int almost_template_window_size_sq_bin_shift_; + vector almost_dist2weight_; void calcDistSumsForFirstElementInRow( - int i, - Array2d& dist_sums, - Array3d& col_dist_sums, - Array3d& up_col_dist_sums) const; + int i, + Array2d& dist_sums, + Array3d& col_dist_sums, + Array3d& up_col_dist_sums) const; void calcDistSumsForElementInFirstRow( int i, - int j, + int j, int first_col_num, - Array2d& dist_sums, - Array3d& col_dist_sums, - Array3d& up_col_dist_sums) const; + Array2d& dist_sums, + Array3d& col_dist_sums, + Array3d& up_col_dist_sums) const; }; +inline int getNearestPowerOf2(int value) +{ + int p = 0; + while( 1 << p < value) ++p; + return p; +} + template FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( - const cv::Mat& src, - cv::Mat& dst, - int template_window_size, - int search_window_size, + const cv::Mat& src, + cv::Mat& dst, + int template_window_size, + int search_window_size, const double h) : src_(src), dst_(dst) { - CV_Assert(src.channels() <= 3); + CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b template_window_half_size_ = template_window_size / 2; - search_window_half_size_ = search_window_size / 2; - template_window_size_ = template_window_half_size_ * 2 + 1; - search_window_size_ = search_window_half_size_ * 2 + 1; + search_window_half_size_ = search_window_size / 2; + template_window_size_ = template_window_half_size_ * 2 + 1; + search_window_size_ = search_window_half_size_ * 2 + 1; border_size_ = search_window_half_size_ + template_window_half_size_; - copyMakeBorder(src_, extended_src_, + copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT); const int max_estimate_sum_value = search_window_size_ * search_window_size_ * 255; @@ -122,19 +127,15 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( // 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) int template_window_size_sq = template_window_size_ * template_window_size_; - almost_template_window_size_sq_bin_shift = 0; - while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) { - almost_template_window_size_sq_bin_shift++; - } - - int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift; - double almost_dist2actual_dist_multiplier = - ((double) almost_template_window_size_sq) / template_window_size_sq; + 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 = 256 * 256 * src_.channels(); int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1); - almost_dist2weight.resize(almost_max_dist); + almost_dist2weight_.resize(almost_max_dist); const double WEIGHT_THRESHOLD = 0.001; for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) { @@ -145,7 +146,7 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( weight = 0; } - almost_dist2weight[almost_dist] = weight; + almost_dist2weight_[almost_dist] = weight; } // additional optimization init end @@ -160,10 +161,10 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons int row_to = range.end() - 1; Array2d dist_sums(search_window_size_, search_window_size_); - + // for lazy calc optimization Array3d col_dist_sums(template_window_size_, search_window_size_, search_window_size_); - + int first_col_num = -1; Array3d up_col_dist_sums(src_.cols, search_window_size_, search_window_size_); @@ -179,17 +180,17 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons } else { // calc cur dist_sums using previous dist_sums if (i == row_from) { - calcDistSumsForElementInFirstRow(i, j, first_col_num, - dist_sums, col_dist_sums, up_col_dist_sums); + calcDistSumsForElementInFirstRow(i, j, first_col_num, + dist_sums, col_dist_sums, up_col_dist_sums); } else { - int ay = border_size_ + i; + int ay = border_size_ + i; int ax = border_size_ + j + template_window_half_size_; - int start_by = + int start_by = border_size_ + i - search_window_half_size_; - int start_bx = + int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_; T a_up = extended_src_.at(ay - template_window_half_size_ - 1, ax); @@ -200,64 +201,64 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons for (int y = 0; y < search_window_size; 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); - const T* b_up_ptr = + const T* b_up_ptr = extended_src_.ptr(start_by - template_window_half_size_ - 1 + y); - const T* b_down_ptr = + const T* b_down_ptr = extended_src_.ptr(start_by + template_window_half_size_ + y); - + for (int x = 0; x < search_window_size; x++) { dist_sums_row[x] -= col_dist_sums_row[x]; - - col_dist_sums_row[x] = - up_col_dist_sums_row[x] + + + col_dist_sums_row[x] = + up_col_dist_sums_row[x] + calcUpDownDist( - a_up, a_down, + a_up, a_down, b_up_ptr[start_bx + x], b_down_ptr[start_bx + x] ); dist_sums_row[x] += col_dist_sums_row[x]; - + up_col_dist_sums_row[x] = col_dist_sums_row[x]; - + } } } - + first_col_num = (first_col_num + 1) % template_window_size_; } // calc weights int weights_sum = 0; - - int estimation[3]; + + int estimation[3]; for (int channel_num = 0; channel_num < src_.channels(); channel_num++) { estimation[channel_num] = 0; } - + for (int y = 0; y < search_window_size_; y++) { const T* cur_row_ptr = extended_src_.ptr(border_size_ + search_window_y + y); 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]; + int weight = almost_dist2weight_[almostAvgDist]; weights_sum += weight; - + T p = cur_row_ptr[border_size_ + search_window_x + x]; incWithWeight(estimation, weight, p); } } - + if (weights_sum > 0) { for (int channel_num = 0; channel_num < src_.channels(); channel_num++) { - estimation[channel_num] = + estimation[channel_num] = cvRound(((double)estimation[channel_num]) / weights_sum); } @@ -272,9 +273,9 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons template inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElementInRow( - int i, - Array2d& dist_sums, - Array3d& col_dist_sums, + int i, + Array2d& dist_sums, + Array3d& col_dist_sums, Array3d& up_col_dist_sums) const { int j = 0; @@ -291,7 +292,7 @@ inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElementInRow( for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) { for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++) { - int dist = calcDist(extended_src_, + int dist = calcDist(extended_src_, border_size_ + i + ty, border_size_ + j + tx, border_size_ + start_y + ty, border_size_ + start_x + tx); @@ -310,29 +311,29 @@ inline void FastNlMeansDenoisingInvoker::calcDistSumsForElementInFirstRow( int i, int j, int first_col_num, - Array2d& dist_sums, - Array3d& col_dist_sums, + Array2d& dist_sums, + Array3d& col_dist_sums, Array3d& up_col_dist_sums) const { - int ay = border_size_ + i; + int ay = border_size_ + i; int ax = border_size_ + j + template_window_half_size_; int start_by = border_size_ + i - search_window_half_size_; int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_; - + int new_last_col_num = first_col_num; for (int y = 0; y < search_window_size_; y++) { for (int x = 0; x < search_window_size_; x++) { dist_sums[y][x] -= col_dist_sums[first_col_num][y][x]; - - col_dist_sums[new_last_col_num][y][x] = 0; - int by = start_by + y; + + col_dist_sums[new_last_col_num][y][x] = 0; + 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] += + 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]; diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp index c1084f15e..c05d64f9e 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp @@ -65,7 +65,7 @@ template <> inline int calcDist(const Vec3b a, const Vec3b b) { template static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2) { const T a = m.at(i1, j1); - const T b = m.at(i2, j2); + const T b = m.at(i2, j2); return calcDist(a,b); } @@ -108,7 +108,7 @@ template <> inline Vec2b saturateCastFromArray(int* estimation) { res[1] = saturate_cast(estimation[1]); return res; } - + template <> inline Vec3b saturateCastFromArray(int* estimation) { Vec3b res; res[0] = saturate_cast(estimation[0]); diff --git a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp index f8d387ce7..b9b8e7f0f 100644 --- a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp @@ -56,16 +56,16 @@ using namespace cv; template struct FastNlMeansMultiDenoisingInvoker { - public: + public: FastNlMeansMultiDenoisingInvoker( - const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, + const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, Mat& dst, int template_window_size, int search_window_size, const double h); void operator() (const BlockedRange& range) const; - void operator= (const FastNlMeansMultiDenoisingInvoker&) { - CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented"); - } + void operator= (const FastNlMeansMultiDenoisingInvoker&) { + CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented"); + } private: int rows_; @@ -91,28 +91,28 @@ struct FastNlMeansMultiDenoisingInvoker { vector almost_dist2weight; void calcDistSumsForFirstElementInRow( - int i, - Array3d& dist_sums, - Array4d& col_dist_sums, - Array4d& up_col_dist_sums) const; + int i, + Array3d& dist_sums, + Array4d& col_dist_sums, + Array4d& up_col_dist_sums) const; void calcDistSumsForElementInFirstRow( int i, - int j, + int j, int first_col_num, - Array3d& dist_sums, - Array4d& col_dist_sums, - Array4d& up_col_dist_sums) const; + Array3d& dist_sums, + Array4d& col_dist_sums, + Array4d& up_col_dist_sums) const; }; template FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( - const vector& srcImgs, - int imgToDenoiseIndex, - int temporalWindowSize, - cv::Mat& dst, - int template_window_size, - int search_window_size, + const vector& srcImgs, + int imgToDenoiseIndex, + int temporalWindowSize, + cv::Mat& dst, + int template_window_size, + int search_window_size, const double h) : dst_(dst), extended_srcs_(srcImgs.size()) { CV_Assert(srcImgs.size() > 0); @@ -131,14 +131,14 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( temporal_window_size_ = temporal_window_half_size_ * 2 + 1; border_size_ = search_window_half_size_ + template_window_half_size_; - for (int i = 0; i < temporal_window_size_; i++) { + for (int i = 0; i < temporal_window_size_; i++) { copyMakeBorder( - srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i], + srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i], border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT); } main_extended_src_ = extended_srcs_[temporal_window_half_size_]; - const int max_estimate_sum_value = + const int max_estimate_sum_value = temporal_window_size_ * search_window_size_ * search_window_size_ * 255; fixed_point_mult_ = numeric_limits::max() / max_estimate_sum_value; @@ -150,9 +150,9 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) { almost_template_window_size_sq_bin_shift++; } - + int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift; - double almost_dist2actual_dist_multiplier = + double almost_dist2actual_dist_multiplier = ((double) almost_template_window_size_sq) / template_window_size_sq; int max_dist = 256 * 256 * channels_count_; @@ -183,16 +183,16 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) int row_to = range.end() - 1; Array3d dist_sums(temporal_window_size_, search_window_size_, search_window_size_); - + // for lazy calc optimization Array4d col_dist_sums( - template_window_size_, temporal_window_size_, search_window_size_, search_window_size_); - + template_window_size_, temporal_window_size_, search_window_size_, search_window_size_); + int first_col_num = -1; Array4d up_col_dist_sums( cols_, temporal_window_size_, search_window_size_, search_window_size_); - + for (int i = row_from; i <= row_to; i++) { for (int j = 0; j < cols_; j++) { int search_window_y = i - search_window_half_size_; @@ -205,17 +205,17 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) } else { // calc cur dist_sums using previous dist_sums if (i == row_from) { - calcDistSumsForElementInFirstRow(i, j, first_col_num, - dist_sums, col_dist_sums, up_col_dist_sums); + calcDistSumsForElementInFirstRow(i, j, first_col_num, + dist_sums, col_dist_sums, up_col_dist_sums); } else { - int ay = border_size_ + i; + int ay = border_size_ + i; int ax = border_size_ + j + template_window_half_size_; - int start_by = + int start_by = border_size_ + i - search_window_half_size_; - int start_bx = + int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_; T a_up = main_extended_src_.at(ay - template_window_half_size_ - 1, ax); @@ -231,41 +231,41 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) Array2d cur_up_col_dist_sums = up_col_dist_sums[j][d]; for (int y = 0; y < search_window_size; y++) { int* dist_sums_row = cur_dist_sums.row_ptr(y); - + int* col_dist_sums_row = cur_col_dist_sums.row_ptr(y); - + int* up_col_dist_sums_row = cur_up_col_dist_sums.row_ptr(y); - const T* b_up_ptr = + const T* b_up_ptr = cur_extended_src.ptr(start_by - template_window_half_size_ - 1 + y); - const T* b_down_ptr = + const T* b_down_ptr = cur_extended_src.ptr(start_by + template_window_half_size_ + y); - + for (int x = 0; x < search_window_size; x++) { dist_sums_row[x] -= col_dist_sums_row[x]; - - col_dist_sums_row[x] = up_col_dist_sums_row[x] + + + col_dist_sums_row[x] = up_col_dist_sums_row[x] + calcUpDownDist( - a_up, a_down, + a_up, a_down, b_up_ptr[start_bx + x], b_down_ptr[start_bx + x] ); dist_sums_row[x] += col_dist_sums_row[x]; - + up_col_dist_sums_row[x] = col_dist_sums_row[x]; - + } } } } - + first_col_num = (first_col_num + 1) % template_window_size_; } // calc weights int weights_sum = 0; - - int estimation[3]; + + int estimation[3]; for (int channel_num = 0; channel_num < channels_count_; channel_num++) { estimation[channel_num] = 0; } @@ -277,12 +277,12 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) int* dist_sums_row = dist_sums.row_ptr(d, y); for (int x = 0; x < search_window_size_; x++) { - int almostAvgDist = + int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift; int weight = almost_dist2weight[almostAvgDist]; weights_sum += weight; - + T p = cur_row_ptr[border_size_ + search_window_x + x]; incWithWeight(estimation, weight, p); } @@ -291,7 +291,7 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) if (weights_sum > 0) { for (int channel_num = 0; channel_num < channels_count_; channel_num++) { - estimation[channel_num] = + estimation[channel_num] = cvRound(((double)estimation[channel_num]) / weights_sum); } @@ -307,9 +307,9 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) template inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForFirstElementInRow( - int i, - Array3d& dist_sums, - Array4d& col_dist_sums, + int i, + Array3d& dist_sums, + Array4d& col_dist_sums, Array4d& up_col_dist_sums) const { int j = 0; @@ -328,7 +328,7 @@ inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForFirstElementInRo int* dist_sums_ptr = &dist_sums[d][y][x]; int* col_dist_sums_ptr = &col_dist_sums[0][d][y][x]; - int col_dist_sums_step = col_dist_sums.step_size(0); + int col_dist_sums_step = col_dist_sums.step_size(0); for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++) { for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) { int dist = calcDist( @@ -355,16 +355,16 @@ inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForElementInFirstRo int i, int j, int first_col_num, - Array3d& dist_sums, - Array4d& col_dist_sums, + Array3d& dist_sums, + Array4d& col_dist_sums, Array4d& up_col_dist_sums) const { - int ay = border_size_ + i; + int ay = border_size_ + i; int ax = border_size_ + j + template_window_half_size_; int start_by = border_size_ + i - search_window_half_size_; int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_; - + int new_last_col_num = first_col_num; for (int d = 0; d < temporal_window_size_; d++) { @@ -372,19 +372,19 @@ inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForElementInFirstRo for (int y = 0; y < search_window_size_; y++) { for (int x = 0; x < search_window_size_; x++) { dist_sums[d][y][x] -= col_dist_sums[first_col_num][d][y][x]; - - col_dist_sums[new_last_col_num][d][y][x] = 0; - int by = start_by + y; + + col_dist_sums[new_last_col_num][d][y][x] = 0; + int by = start_by + y; int bx = start_bx + x; int* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][x]; for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) { *col_dist_sums_ptr += calcDist( - main_extended_src_.at(ay + ty, ax), + main_extended_src_.at(ay + ty, ax), cur_extended_src.at(by + ty, bx) ); - } + } dist_sums[d][y][x] += col_dist_sums[new_last_col_num][d][y][x];