diff --git a/modules/photo/include/opencv2/photo/photo.hpp b/modules/photo/include/opencv2/photo/photo.hpp index 07b27abc0..66973772e 100644 --- a/modules/photo/include/opencv2/photo/photo.hpp +++ b/modules/photo/include/opencv2/photo/photo.hpp @@ -68,20 +68,20 @@ CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); -CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, int h = 3, +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - int h = 3, int hColor = 3, + float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21); CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, - int h = 3, int templateWindowSize = 7, int searchWindowSize = 21); + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, - int h = 3, int hColor = 3, + float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21); } diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index f71c37cf4..770df13d0 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -45,7 +45,7 @@ #include "fast_nlmeans_denoising_invoker.hpp" #include "fast_nlmeans_multi_denoising_invoker.hpp" -void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, int h, +void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h, int templateWindowSize, int searchWindowSize) { Mat src = _src.getMat(); @@ -75,7 +75,7 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, int h, } void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, - int h, int hForColorComponents, + float h, float hForColorComponents, int templateWindowSize, int searchWindowSize) { Mat src = _src.getMat(); @@ -140,7 +140,7 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, - int h, int templateWindowSize, int searchWindowSize) + float h, int templateWindowSize, int searchWindowSize) { vector srcImgs; _srcImgs.getMatVector(srcImgs); @@ -179,7 +179,7 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, - int h, int hForColorComponents, + float h, float hForColorComponents, int templateWindowSize, int searchWindowSize) { vector srcImgs; diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp index 5f7d1fe59..1dcb6b3ec 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp @@ -58,7 +58,7 @@ template struct FastNlMeansDenoisingInvoker { public: FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, - int template_window_size, int search_window_size, const double h); + int template_window_size, int search_window_size, const float h); void operator() (const BlockedRange& range) const; @@ -109,7 +109,7 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( cv::Mat& dst, int template_window_size, int search_window_size, - const double h) : src_(src), dst_(dst) + const float h) : src_(src), dst_(dst) { CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b @@ -133,21 +133,21 @@ FastNlMeansDenoisingInvoker::FastNlMeansDenoisingInvoker( 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 max_dist = 255 * 255 * sizeof(T); 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 = cvRound(fixed_point_mult_ * std::exp(- dist / (h * h * src_.channels()))); + int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T)))); - if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) { + if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) weight = 0; - } almost_dist2weight_[almost_dist] = weight; } + CV_Assert(almost_dist2weight_[0] == fixed_point_mult_); // additional optimization init end if (dst_.empty()) { @@ -237,7 +237,7 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons int weights_sum = 0; int estimation[3]; - for (int channel_num = 0; channel_num < src_.channels(); channel_num++) { + for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) { estimation[channel_num] = 0; } @@ -256,15 +256,10 @@ void FastNlMeansDenoisingInvoker::operator() (const BlockedRange& range) cons } } - if (weights_sum > 0) { - for (int channel_num = 0; channel_num < src_.channels(); channel_num++) - estimation[channel_num] = (estimation[channel_num] + weights_sum/2) / weights_sum; + for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) + estimation[channel_num] = (estimation[channel_num] + weights_sum/2) / weights_sum; - dst_.at(i,j) = saturateCastFromArray(estimation); - - } else { // weights_sum == 0 - dst_.at(i,j) = src_.at(i,j); - } + dst_.at(i,j) = saturateCastFromArray(estimation); } } } diff --git a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp index 4151f320b..870760b48 100644 --- a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp @@ -59,18 +59,15 @@ struct FastNlMeansMultiDenoisingInvoker { public: FastNlMeansMultiDenoisingInvoker( const std::vector& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, - Mat& dst, int template_window_size, int search_window_size, const double h); + Mat& dst, int template_window_size, int search_window_size, const float h); void operator() (const BlockedRange& range) const; - void operator= (const FastNlMeansMultiDenoisingInvoker&) { - CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented"); - } - private: + void operator= (const FastNlMeansMultiDenoisingInvoker&); + int rows_; int cols_; - int channels_count_; Mat& dst_; @@ -113,14 +110,13 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( cv::Mat& dst, int template_window_size, int search_window_size, - const double h) : dst_(dst), extended_srcs_(srcImgs.size()) + const float h) : dst_(dst), extended_srcs_(srcImgs.size()) { CV_Assert(srcImgs.size() > 0); - CV_Assert(srcImgs[0].channels() <= 3); + CV_Assert(srcImgs[0].channels() == sizeof(T)); rows_ = srcImgs[0].rows; cols_ = srcImgs[0].cols; - channels_count_ = srcImgs[0].channels(); template_window_half_size_ = template_window_size / 2; search_window_half_size_ = search_window_size / 2; @@ -155,14 +151,14 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( double almost_dist2actual_dist_multiplier = ((double) almost_template_window_size_sq) / template_window_size_sq; - int max_dist = 256 * 256 * channels_count_; + int max_dist = 255 * 255 * sizeof(T); 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 = cvRound(fixed_point_mult_ * std::exp(- dist / (h * h * channels_count_))); + int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T)))); if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) { weight = 0; @@ -170,6 +166,7 @@ FastNlMeansMultiDenoisingInvoker::FastNlMeansMultiDenoisingInvoker( almost_dist2weight[almost_dist] = weight; } + CV_Assert(almost_dist2weight[0] == fixed_point_mult_); // additional optimization init end if (dst_.empty()) { @@ -266,7 +263,7 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) int weights_sum = 0; int estimation[3]; - for (int channel_num = 0; channel_num < channels_count_; channel_num++) { + for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) { estimation[channel_num] = 0; } for (int d = 0; d < temporal_window_size_; d++) { @@ -289,16 +286,11 @@ 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] + weights_sum / 2) / weights_sum; + for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) + estimation[channel_num] = (estimation[channel_num] + weights_sum / 2) / weights_sum; - dst_.at(i,j) = saturateCastFromArray(estimation); + dst_.at(i,j) = saturateCastFromArray(estimation); - } else { // weights_sum == 0 - const Mat& esrc = extended_srcs_[temporal_window_half_size_]; - dst_.at(i,j) = esrc.at(i,j); - } } } }