diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 0a42424cb..c651b9ee3 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -142,7 +142,8 @@ CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h with several computational optimizations. Noise expected to be a gaussian white noise -@param src Input 8-bit 1-channel, 2-channel, 3-channel or 4-channel image. +@param src Input 8-bit or 16-bit (only with NORM_L1) 1-channel, +2-channel, 3-channel or 4-channel image. @param dst Output image with the same size and type as src . @param templateWindowSize Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels @@ -153,7 +154,7 @@ denoising time. Recommended value 21 pixels parameter applied to all channels or one per channel in dst. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise -@param normType Type of norm used for weight calcluation. Can be either NORM_L2 or NORM_L1 +@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1 This function expected to be applied to grayscale images. For colored images look at fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored @@ -220,9 +221,9 @@ captured in small period of time. For example video. This version of the functio images or for manual manipulation with colorspaces. For more details see -@param srcImgs Input 8-bit 1-channel, 2-channel, 3-channel or -4-channel images sequence. All images should have the same type and -size. +@param srcImgs Input 8-bit or 16-bit (only with NORM_L1) 1-channel, +2-channel, 3-channel or 4-channel images sequence. All images should +have the same type and size. @param imgToDenoiseIndex Target image to denoise index in srcImgs sequence @param temporalWindowSize Number of surrounding images to use for target image denoising. Should be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to @@ -238,10 +239,13 @@ denoising time. Recommended value 21 pixels parameter applied to all channels or one per channel in dst. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise +@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1 */ CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - const std::vector& h , int templateWindowSize = 7, int searchWindowSize = 21); + int imgToDenoiseIndex, int temporalWindowSize, + const std::vector& h, + int templateWindowSize = 7, int searchWindowSize = 21, + int normType = NORM_L2); /** @brief Modification of fastNlMeansDenoisingMulti function for colored images sequences diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index 4e7922e40..c68d09b92 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -230,6 +230,64 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( } } +template +static void fastNlMeansDenoisingMulti_( const std::vector& srcImgs, Mat& dst, + int imgToDenoiseIndex, int temporalWindowSize, + const std::vector& h, + int templateWindowSize, int searchWindowSize) +{ + int hn = (int)h.size(); + + switch (srcImgs[0].type()) + { + case CV_8U: + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + break; + case CV_8UC2: + if (hn == 1) + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + else + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec2i>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + break; + case CV_8UC3: + if (hn == 1) + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + else + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec3i>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + break; + case CV_8UC4: + if (hn == 1) + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + else + parallel_for_(cv::Range(0, srcImgs[0].rows), + FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec4i>( + srcImgs, imgToDenoiseIndex, temporalWindowSize, + dst, templateWindowSize, searchWindowSize, &h[0])); + break; + default: + CV_Error(Error::StsBadArg, + "Unsupported image format! Only CV_8U, CV_8UC2, CV_8UC3 and CV_8UC4 are supported"); + } +} + void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize, int searchWindowSize) @@ -241,7 +299,7 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, const std::vector& h, - int templateWindowSize, int searchWindowSize) + int templateWindowSize, int searchWindowSize, int normType) { std::vector srcImgs; _srcImgs.getMatVector(srcImgs); @@ -251,58 +309,51 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds temporalWindowSize, templateWindowSize, searchWindowSize); int hn = (int)h.size(); - CV_Assert(hn == 1 || hn == CV_MAT_CN(srcImgs[0].type())); + int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + CV_Assert(hn == 1 || hn == cn); _dst.create(srcImgs[0].size(), srcImgs[0].type()); Mat dst = _dst.getMat(); - switch (srcImgs[0].type()) - { - case CV_8U: - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + switch (normType) { + case NORM_L2: + switch (depth) { + case CV_8U: + fastNlMeansDenoisingMulti_(srcImgs, dst, + imgToDenoiseIndex, temporalWindowSize, + h, + templateWindowSize, searchWindowSize); + break; + default: + CV_Error(Error::StsBadArg, + "Unsupported depth! Only CV_8U is supported for NORM_L2"); + } break; - case CV_8UC2: - if (hn == 1) - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); - else - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); - break; - case CV_8UC3: - if (hn == 1) - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); - else - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); - break; - case CV_8UC4: - if (hn == 1) - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); - else - parallel_for_(cv::Range(0, srcImgs[0].rows), - FastNlMeansMultiDenoisingInvoker( - srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + case NORM_L1: + switch (depth) { + case CV_8U: + fastNlMeansDenoisingMulti_(srcImgs, dst, + imgToDenoiseIndex, temporalWindowSize, + h, + templateWindowSize, searchWindowSize); + break; + case CV_16U: + fastNlMeansDenoisingMulti_(srcImgs, dst, + imgToDenoiseIndex, temporalWindowSize, + h, + templateWindowSize, searchWindowSize); + break; + default: + CV_Error(Error::StsBadArg, + "Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1"); + } break; default: CV_Error(Error::StsBadArg, - "Unsupported image format! Only CV_8U, CV_8UC2, CV_8UC3 and CV_8UC4 are supported"); + "Unsupported norm type! Only NORM_L2 and NORM_L1 are supported"); } }