From c41efe4e303d51bf207bb54f60d2f4508acfe53d Mon Sep 17 00:00:00 2001 From: Erik Karlsson Date: Thu, 5 Mar 2015 17:50:52 +0100 Subject: [PATCH] Refactoring in preparation for per-channel h-values --- modules/photo/src/denoising.cpp | 96 +++++++------- .../photo/src/fast_nlmeans_denoising_invoker.hpp | 45 +++---- .../src/fast_nlmeans_denoising_invoker_commons.hpp | 147 ++++++++++++++++++--- .../src/fast_nlmeans_multi_denoising_invoker.hpp | 48 +++---- 4 files changed, 216 insertions(+), 120 deletions(-) diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index b41f83e..29899f7 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -65,23 +65,23 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h, switch (src.type()) { case CV_8U: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC2: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC3: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC4: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; default: CV_Error(Error::StsBadArg, @@ -104,43 +104,43 @@ void cv::fastNlMeansDenoisingAbs( InputArray _src, OutputArray _dst, float h, switch (src.type()) { case CV_8U: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC2: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC3: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC4: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16U: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC2: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker, int64, uint64, DistAbs>( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker, int64, uint64, DistAbs, int>( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC3: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker, int64, uint64, DistAbs>( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker, int64, uint64, DistAbs, int>( + src, dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC4: parallel_for_(cv::Range(0, src.rows), - FastNlMeansDenoisingInvoker, int64, uint64, DistAbs>( - src, dst, templateWindowSize, searchWindowSize, h)); + FastNlMeansDenoisingInvoker, int64, uint64, DistAbs, int>( + src, dst, templateWindowSize, searchWindowSize, &h)); break; default: CV_Error(Error::StsBadArg, @@ -239,27 +239,27 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds { case CV_8U: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC2: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC3: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC4: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; default: CV_Error(Error::StsBadArg, @@ -285,51 +285,51 @@ void cv::fastNlMeansDenoisingMultiAbs( InputArrayOfArrays _srcImgs, OutputArray { case CV_8U: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC2: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC3: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_8UC4: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16U: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( + FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC2: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs>( + FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC3: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs>( + FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; case CV_16UC4: parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs>( + FastNlMeansMultiDenoisingInvoker, int64, uint64, DistAbs, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, h)); + dst, templateWindowSize, searchWindowSize, &h)); break; default: CV_Error(Error::StsBadArg, diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp index ec154fb..9dea2a0 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp @@ -50,13 +50,13 @@ using namespace cv; -template +template struct FastNlMeansDenoisingInvoker : public ParallelLoopBody { public: FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, - int template_window_size, int search_window_size, const float h); + int template_window_size, int search_window_size, const float *h); void operator() (const Range& range) const; @@ -77,7 +77,7 @@ private: int fixed_point_mult_; int almost_template_window_size_sq_bin_shift_; - std::vector almost_dist2weight_; + std::vector almost_dist2weight_; void calcDistSumsForFirstElementInRow( int i, Array2d& dist_sums, @@ -99,12 +99,12 @@ inline int getNearestPowerOf2(int value) return p; } -template -FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( +template +FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( const Mat& src, Mat& dst, int template_window_size, int search_window_size, - const float h) : + const float *h) : src_(src), dst_(dst) { CV_Assert(src.channels() == pixelInfo::channels); @@ -133,25 +133,20 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1); almost_dist2weight_.resize(almost_max_dist); - const double WEIGHT_THRESHOLD = 0.001; for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) { double dist = almost_dist * almost_dist2actual_dist_multiplier; - int weight = (int)round(fixed_point_mult_ * D::template calcWeight(dist, h)); - if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) - weight = 0; - - almost_dist2weight_[almost_dist] = weight; + almost_dist2weight_[almost_dist] = + D::template calcWeight(dist, h, fixed_point_mult_); } - CV_Assert(almost_dist2weight_[0] == fixed_point_mult_); // additional optimization init end if (dst_.empty()) dst_ = Mat::zeros(src_.size(), src_.type()); } -template -void FastNlMeansDenoisingInvoker::operator() (const Range& range) const +template +void FastNlMeansDenoisingInvoker::operator() (const Range& range) const { int row_from = range.start; int row_to = range.end - 1; @@ -228,9 +223,9 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) } // calc weights - IT estimation[pixelInfo::channels], weights_sum = 0; + IT estimation[pixelInfo::channels], weights_sum[pixelInfo::channels]; for (size_t channel_num = 0; channel_num < pixelInfo::channels; channel_num++) - estimation[channel_num] = 0; + estimation[channel_num] = weights_sum[channel_num] = 0; for (int y = 0; y < search_window_size_; y++) { @@ -240,23 +235,23 @@ void FastNlMeansDenoisingInvoker::operator() (const Range& range) { int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_; int weight = almost_dist2weight_[almostAvgDist]; - weights_sum += (IT)weight; - T p = cur_row_ptr[border_size_ + search_window_x + x]; - incWithWeight(estimation, weight, p); + incWithWeight(estimation, weights_sum, weight, p); } } for (size_t channel_num = 0; channel_num < pixelInfo::channels; channel_num++) - estimation[channel_num] = (static_cast(estimation[channel_num]) + weights_sum/2) / weights_sum; + estimation[channel_num] = + (static_cast(estimation[channel_num]) + weights_sum[channel_num]/2) / + weights_sum[channel_num]; dst_.at(i,j) = saturateCastFromArray(estimation); } } } -template -inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElementInRow( +template +inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElementInRow( int i, Array2d& dist_sums, Array3d& col_dist_sums, @@ -289,8 +284,8 @@ inline void FastNlMeansDenoisingInvoker::calcDistSumsForFirstElem } } -template -inline void FastNlMeansDenoisingInvoker::calcDistSumsForElementInFirstRow( +template +inline void FastNlMeansDenoisingInvoker::calcDistSumsForElementInFirstRow( int i, int j, int first_col_num, Array2d& dist_sums, Array3d& col_dist_sums, diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp index 4d66efe..53a6f5e 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp @@ -122,6 +122,36 @@ class DistAbs } }; + static const double WEIGHT_THRESHOLD = 0.001; + template struct calcWeight_ + { + static inline WT f(double dist, const float *h, int fixed_point_mult) + { + WT weight = (WT)round(fixed_point_mult * + std::exp(-dist*dist / (h[0]*h[0] * pixelInfo::channels))); + if (weight < WEIGHT_THRESHOLD * fixed_point_mult) + weight = 0; + return weight; + } + }; + + template struct calcWeight_ > + { + static inline Vec f(double dist, const float *h, int fixed_point_mult) + { + Vec res; + for (int i=0; i::channels))); + if (weight < WEIGHT_THRESHOLD * fixed_point_mult) + weight = 0; + res[i] = weight; + } + return res; + } + }; + public: template static inline int calcDist(const T a, const T b) { @@ -142,14 +172,14 @@ public: return calcDist(a_down, b_down) - calcDist(a_up, b_up); }; - template - static double calcWeight(double dist, double h) + template + static inline WT calcWeight(double dist, const float *h, int fixed_point_mult) { - return std::exp(-dist*dist / (h * h * pixelInfo::channels)); + return calcWeight_::f(dist, h, fixed_point_mult); } template - static double maxDist() + static inline double maxDist() { return (int)pixelInfo::sampleMax() * pixelInfo::channels; } @@ -217,6 +247,36 @@ class DistSquared } }; + static const double WEIGHT_THRESHOLD = 0.001; + template struct calcWeight_ + { + static inline WT f(double dist, const float *h, int fixed_point_mult) + { + WT weight = (WT)round(fixed_point_mult * + std::exp(-dist / (h[0]*h[0] * pixelInfo::channels))); + if (weight < WEIGHT_THRESHOLD * fixed_point_mult) + weight = 0; + return weight; + } + }; + + template struct calcWeight_ > + { + static inline Vec f(double dist, const float *h, int fixed_point_mult) + { + Vec res; + for (int i=0; i::channels))); + if (weight < WEIGHT_THRESHOLD * fixed_point_mult) + weight = 0; + res[i] = weight; + } + return res; + } + }; + public: template static inline int calcDist(const T a, const T b) { @@ -237,62 +297,111 @@ public: return calcUpDownDist_::f(a_up, a_down, b_up, b_down); }; - template - static double calcWeight(double dist, double h) + template + static inline WT calcWeight(double dist, const float *h, int fixed_point_mult) { - return std::exp(-dist / (h * h * pixelInfo::channels)); + return calcWeight_::f(dist, h, fixed_point_mult); } template - static double maxDist() + static inline double maxDist() { return (int)pixelInfo::sampleMax() * (int)pixelInfo::sampleMax() * pixelInfo::channels; } }; -template struct incWithWeight_ +template struct incWithWeight_ { - static inline void f(IT* estimation, int weight, T p) + static inline void f(IT* estimation, IT* weights_sum, WT weight, T p) { estimation[0] += (IT)weight * p; + weights_sum[0] += (IT)weight; } }; -template struct incWithWeight_, IT> +template struct incWithWeight_, IT, int> { - static inline void f(IT* estimation, int weight, Vec p) + static inline void f(IT* estimation, IT* weights_sum, int weight, Vec p) { estimation[0] += (IT)weight * p[0]; estimation[1] += (IT)weight * p[1]; + weights_sum[0] += (IT)weight; + weights_sum[1] += (IT)weight; } }; -template struct incWithWeight_, IT> +template struct incWithWeight_, IT, int> { - static inline void f(IT* estimation, int weight, Vec p) + static inline void f(IT* estimation, IT* weights_sum, int weight, Vec p) { estimation[0] += (IT)weight * p[0]; estimation[1] += (IT)weight * p[1]; estimation[2] += (IT)weight * p[2]; + weights_sum[0] += (IT)weight; + weights_sum[1] += (IT)weight; + weights_sum[2] += (IT)weight; } }; -template struct incWithWeight_, IT> +template struct incWithWeight_, IT, int> { - static inline void f(IT* estimation, int weight, Vec p) + static inline void f(IT* estimation, IT* weights_sum, int weight, Vec p) { estimation[0] += (IT)weight * p[0]; estimation[1] += (IT)weight * p[1]; estimation[2] += (IT)weight * p[2]; estimation[3] += (IT)weight * p[3]; + weights_sum[0] += (IT)weight; + weights_sum[1] += (IT)weight; + weights_sum[2] += (IT)weight; + weights_sum[3] += (IT)weight; + } +}; + +template struct incWithWeight_, IT, Vec > +{ + static inline void f(IT* estimation, IT* weights_sum, Vec weight, Vec p) + { + estimation[0] += (IT)weight[0] * p[0]; + estimation[1] += (IT)weight[1] * p[1]; + weights_sum[0] += (IT)weight[0]; + weights_sum[1] += (IT)weight[1]; + } +}; + +template struct incWithWeight_, IT, Vec > +{ + static inline void f(IT* estimation, IT* weights_sum, Vec weight, Vec p) + { + estimation[0] += (IT)weight[0] * p[0]; + estimation[1] += (IT)weight[1] * p[1]; + estimation[2] += (IT)weight[2] * p[2]; + weights_sum[0] += (IT)weight[0]; + weights_sum[1] += (IT)weight[1]; + weights_sum[2] += (IT)weight[2]; + } +}; + +template struct incWithWeight_, IT, Vec > +{ + static inline void f(IT* estimation, IT* weights_sum, Vec weight, Vec p) + { + estimation[0] += (IT)weight[0] * p[0]; + estimation[1] += (IT)weight[1] * p[1]; + estimation[2] += (IT)weight[2] * p[2]; + estimation[3] += (IT)weight[3] * p[3]; + weights_sum[0] += (IT)weight[0]; + weights_sum[1] += (IT)weight[1]; + weights_sum[2] += (IT)weight[2]; + weights_sum[3] += (IT)weight[3]; } }; -template -static inline void incWithWeight(IT* estimation, IT weight, T p) +template +static inline void incWithWeight(IT* estimation, IT* weights_sum, IT weight, T p) { - return incWithWeight_::f(estimation, weight, p); + return incWithWeight_::f(estimation, weights_sum, weight, p); } template struct saturateCastFromArray_ diff --git a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp index f9c1264..489ee67 100644 --- a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp @@ -50,14 +50,14 @@ using namespace cv; -template +template struct FastNlMeansMultiDenoisingInvoker : ParallelLoopBody { public: FastNlMeansMultiDenoisingInvoker(const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, Mat& dst, int template_window_size, - int search_window_size, const float h); + int search_window_size, const float *h); void operator() (const Range& range) const; @@ -83,7 +83,7 @@ private: int fixed_point_mult_; int almost_template_window_size_sq_bin_shift; - std::vector almost_dist2weight; + std::vector almost_dist2weight; void calcDistSumsForFirstElementInRow(int i, Array3d& dist_sums, Array4d& col_dist_sums, @@ -94,15 +94,15 @@ private: Array4d& up_col_dist_sums) const; }; -template -FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( +template +FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, cv::Mat& dst, int template_window_size, int search_window_size, - const float h) : + const float *h) : dst_(dst), extended_srcs_(srcImgs.size()) { CV_Assert(srcImgs.size() > 0); @@ -144,25 +144,20 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoke int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1); almost_dist2weight.resize(almost_max_dist); - const double WEIGHT_THRESHOLD = 0.001; for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) { double dist = almost_dist * almost_dist2actual_dist_multiplier; - int weight = (int)round(fixed_point_mult_ * D::template calcWeight(dist, h)); - if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) - weight = 0; - - almost_dist2weight[almost_dist] = weight; + almost_dist2weight[almost_dist] = + D::template calcWeight(dist, h, fixed_point_mult_); } - CV_Assert(almost_dist2weight[0] == fixed_point_mult_); // additional optimization init end if (dst_.empty()) dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type()); } -template -void FastNlMeansMultiDenoisingInvoker::operator() (const Range& range) const +template +void FastNlMeansMultiDenoisingInvoker::operator() (const Range& range) const { int row_from = range.start; int row_to = range.end - 1; @@ -248,11 +243,9 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const Range& r } // calc weights - IT weights_sum = 0; - - IT estimation[pixelInfo::channels]; + IT estimation[pixelInfo::channels], weights_sum[pixelInfo::channels]; for (size_t channel_num = 0; channel_num < pixelInfo::channels; channel_num++) - estimation[channel_num] = 0; + estimation[channel_num] = weights_sum[channel_num] = 0; for (int d = 0; d < temporal_window_size_; d++) { @@ -268,25 +261,24 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const Range& r int almostAvgDist = dist_sums_row[x] >> almost_template_window_size_sq_bin_shift; int weight = almost_dist2weight[almostAvgDist]; - weights_sum += (IT)weight; - T p = cur_row_ptr[border_size_ + search_window_x + x]; - incWithWeight(estimation, weight, p); + incWithWeight(estimation, weights_sum, weight, p); } } } for (size_t channel_num = 0; channel_num < pixelInfo::channels; channel_num++) - estimation[channel_num] = (static_cast(estimation[channel_num]) + weights_sum / 2) / weights_sum; + estimation[channel_num] = + (static_cast(estimation[channel_num]) + weights_sum[channel_num] / 2) / + weights_sum[channel_num]; dst_.at(i,j) = saturateCastFromArray(estimation); - } } } -template -inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForFirstElementInRow( +template +inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForFirstElementInRow( int i, Array3d& dist_sums, Array4d& col_dist_sums, Array4d& up_col_dist_sums) const { int j = 0; @@ -326,8 +318,8 @@ inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForFirs } } -template -inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForElementInFirstRow( +template +inline void FastNlMeansMultiDenoisingInvoker::calcDistSumsForElementInFirstRow( int i, int j, int first_col_num, Array3d& dist_sums, Array4d& col_dist_sums, Array4d& up_col_dist_sums) const { -- 2.7.4