diff --git a/3rdparty/ffmpeg/opencv_ffmpeg.dll b/3rdparty/ffmpeg/opencv_ffmpeg.dll index a5e9e656ff..53cc411331 100644 Binary files a/3rdparty/ffmpeg/opencv_ffmpeg.dll and b/3rdparty/ffmpeg/opencv_ffmpeg.dll differ diff --git a/3rdparty/ffmpeg/opencv_ffmpeg_64.dll b/3rdparty/ffmpeg/opencv_ffmpeg_64.dll index 1cfdddec7b..70b353520e 100644 Binary files a/3rdparty/ffmpeg/opencv_ffmpeg_64.dll and b/3rdparty/ffmpeg/opencv_ffmpeg_64.dll differ diff --git a/modules/photo/include/opencv2/photo/photo.hpp b/modules/photo/include/opencv2/photo/photo.hpp index bae83bbb0e..07b27abc0f 100644 --- a/modules/photo/include/opencv2/photo/photo.hpp +++ b/modules/photo/include/opencv2/photo/photo.hpp @@ -68,26 +68,24 @@ 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 templateWindowSize, int searchWindowSize, int h); +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, int h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - int templateWindowSize, int searchWindowSize, - int h, int hForColorComponents); + int h = 3, int hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, +CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, - OutputArray dst, - int templateWindowSize, int searchWindowSize, int h); + int h = 3, int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, +CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, - OutputArray dst, - int templateWindowSize, int searchWindowSize, - int h, int hForColorComponents); + int h = 3, int hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); } -#endif +#endif //__cplusplus #endif diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index d3f1c09aaf..f71c37cf43 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -45,8 +45,8 @@ #include "fast_nlmeans_denoising_invoker.hpp" #include "fast_nlmeans_multi_denoising_invoker.hpp" -void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, - int templateWindowSize, int searchWindowSize, int h) +void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, int h, + int templateWindowSize, int searchWindowSize) { Mat src = _src.getMat(); _dst.create(src.size(), src.type()); @@ -75,8 +75,8 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, } void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, - int templateWindowSize, int searchWindowSize, - int h, int hForColorComponents) + int h, int hForColorComponents, + int templateWindowSize, int searchWindowSize) { Mat src = _src.getMat(); _dst.create(src.size(), src.type()); @@ -96,8 +96,8 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, 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); + fastNlMeansDenoising(l, l, h, templateWindowSize, searchWindowSize); + fastNlMeansDenoising(ab, ab, hForColorComponents, templateWindowSize, searchWindowSize); Mat l_ab_denoised[] = { l, ab }; Mat dst_lab(src.size(), src.type()); @@ -138,10 +138,9 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( } } -void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, +void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, - OutputArray _dst, - int templateWindowSize, int searchWindowSize, int h) + int h, int templateWindowSize, int searchWindowSize) { vector srcImgs; _srcImgs.getMatVector(srcImgs); @@ -178,11 +177,10 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, } } -void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, +void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, int imgToDenoiseIndex, int temporalWindowSize, - OutputArray _dst, - int templateWindowSize, int searchWindowSize, - int h, int hForColorComponents) + int h, int hForColorComponents, + int templateWindowSize, int searchWindowSize) { vector srcImgs; _srcImgs.getMatVector(srcImgs); @@ -222,12 +220,12 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, Mat dst_ab; fastNlMeansDenoisingMulti( - l, imgToDenoiseIndex, temporalWindowSize, - dst_l, templateWindowSize, searchWindowSize, h); + l, dst_l, imgToDenoiseIndex, temporalWindowSize, + h, templateWindowSize, searchWindowSize); fastNlMeansDenoisingMulti( - ab, imgToDenoiseIndex, temporalWindowSize, - dst_ab, templateWindowSize, searchWindowSize, hForColorComponents); + ab, dst_ab, imgToDenoiseIndex, temporalWindowSize, + hForColorComponents, templateWindowSize, searchWindowSize); Mat l_ab_denoised[] = { dst_l, dst_ab }; Mat dst_lab(srcImgs[0].size(), srcImgs[0].type()); diff --git a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp index 07159bba47..5f7d1fe59b 100644 --- a/modules/photo/src/fast_nlmeans_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_invoker.hpp @@ -257,10 +257,8 @@ 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] = - cvRound(((double)estimation[channel_num]) / weights_sum); - } + for (int channel_num = 0; channel_num < src_.channels(); channel_num++) + estimation[channel_num] = (estimation[channel_num] + weights_sum/2) / weights_sum; 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 b9b8e7f0f7..4151f320ba 100644 --- a/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp +++ b/modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp @@ -290,10 +290,8 @@ void FastNlMeansMultiDenoisingInvoker::operator() (const BlockedRange& range) } if (weights_sum > 0) { - for (int channel_num = 0; channel_num < channels_count_; channel_num++) { - estimation[channel_num] = - cvRound(((double)estimation[channel_num]) / weights_sum); - } + for (int channel_num = 0; channel_num < channels_count_; channel_num++) + estimation[channel_num] = (estimation[channel_num] + weights_sum / 2) / weights_sum; dst_.at(i,j) = saturateCastFromArray(estimation); diff --git a/modules/photo/test/test_denoising.cpp b/modules/photo/test/test_denoising.cpp index 6b202f133a..d52d8b40f2 100644 --- a/modules/photo/test/test_denoising.cpp +++ b/modules/photo/test/test_denoising.cpp @@ -47,167 +47,102 @@ using namespace cv; using namespace std; -class CV_DenoisingGrayscaleTest : public cvtest::BaseTest -{ -public: - CV_DenoisingGrayscaleTest(); - ~CV_DenoisingGrayscaleTest(); -protected: - void run(int); -}; +//#define DUMP_RESULTS + +#ifdef DUMP_RESULTS +# define DUMP(image, path) imwrite(path, image) +#else +# define FUMP(image, path) +#endif -CV_DenoisingGrayscaleTest::CV_DenoisingGrayscaleTest() {} -CV_DenoisingGrayscaleTest::~CV_DenoisingGrayscaleTest() {} -void CV_DenoisingGrayscaleTest::run( int ) +TEST(Imgproc_DenoisingGrayscale, regression) { - string folder = string(ts->get_data_path()) + "denoising/"; - Mat orig = imread(folder + "lena_noised_gaussian_sigma=10.png", 0); - Mat exp = imread(folder + "lena_noised_denoised_grayscale_tw=7_sw=21_h=10.png", 0); + string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/"; + string original_path = folder + "lena_noised_gaussian_sigma=10.png"; + string expected_path = folder + "lena_noised_denoised_grayscale_tw=7_sw=21_h=10.png"; - if (orig.empty() || exp.empty()) - { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); - return; - } + Mat original = imread(original_path, CV_LOAD_IMAGE_GRAYSCALE); + Mat expected = imread(expected_path, CV_LOAD_IMAGE_GRAYSCALE); - Mat res; - fastNlMeansDenoising(orig, res, 7, 21, 10); + ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; - if (norm(res - exp) > 0) { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - } else { - ts->set_failed_test_info(cvtest::TS::OK); - } + Mat result; + fastNlMeansDenoising(original, result, 10); + + DUMP(result, expected_path + ".res.png"); + + ASSERT_EQ(0, norm(result != expected)); } -class CV_DenoisingColoredTest : public cvtest::BaseTest +TEST(Imgproc_DenoisingColored, regression) { -public: - CV_DenoisingColoredTest(); - ~CV_DenoisingColoredTest(); -protected: - void run(int); -}; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/"; + string original_path = folder + "lena_noised_gaussian_sigma=10.png"; + string expected_path = folder + "lena_noised_denoised_lab12_tw=7_sw=21_h=10_h2=10.png"; -CV_DenoisingColoredTest::CV_DenoisingColoredTest() {} -CV_DenoisingColoredTest::~CV_DenoisingColoredTest() {} + Mat original = imread(original_path, CV_LOAD_IMAGE_COLOR); + Mat expected = imread(expected_path, CV_LOAD_IMAGE_COLOR); -void CV_DenoisingColoredTest::run( int ) -{ - string folder = string(ts->get_data_path()) + "denoising/"; - Mat orig = imread(folder + "lena_noised_gaussian_sigma=10.png", 1); - Mat exp = imread(folder + "lena_noised_denoised_lab12_tw=7_sw=21_h=10_h2=10.png", 1); + ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; - if (orig.empty() || exp.empty()) - { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); - return; - } + Mat result; + fastNlMeansDenoisingColored(original, result, 10, 10); - Mat res; - fastNlMeansDenoisingColored(orig, res, 7, 21, 10, 10); + DUMP(result, expected_path + ".res.png"); - if (norm(res - exp) > 0) { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - } else { - ts->set_failed_test_info(cvtest::TS::OK); - } + ASSERT_EQ(0, norm(result != expected)); } -class CV_DenoisingGrayscaleMultiTest : public cvtest::BaseTest +TEST(Imgproc_DenoisingGrayscaleMulti, regression) { -public: - CV_DenoisingGrayscaleMultiTest(); - ~CV_DenoisingGrayscaleMultiTest(); -protected: - void run(int); -}; - -CV_DenoisingGrayscaleMultiTest::CV_DenoisingGrayscaleMultiTest() {} -CV_DenoisingGrayscaleMultiTest::~CV_DenoisingGrayscaleMultiTest() {} - -void CV_DenoisingGrayscaleMultiTest::run( int ) -{ - string folder = string(ts->get_data_path()) + "denoising/"; - const int imgs_count = 3; - vector src_imgs(imgs_count); - src_imgs[0] = imread(folder + "lena_noised_gaussian_sigma=20_multi_0.png", 0); - src_imgs[1] = imread(folder + "lena_noised_gaussian_sigma=20_multi_1.png", 0); - src_imgs[2] = imread(folder + "lena_noised_gaussian_sigma=20_multi_2.png", 0); - - Mat exp = imread(folder + "lena_noised_denoised_multi_tw=7_sw=21_h=15.png", 0); - - bool have_empty_src = false; - for (int i = 0; i < imgs_count; i++) { - have_empty_src |= src_imgs[i].empty(); - } + string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/"; + + string expected_path = folder + "lena_noised_denoised_multi_tw=7_sw=21_h=15.png"; + Mat expected = imread(expected_path, CV_LOAD_IMAGE_GRAYSCALE); + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; - if (have_empty_src || exp.empty()) + vector original(imgs_count); + for (int i = 0; i < imgs_count; i++) { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); - return; + string original_path = format("%slena_noised_gaussian_sigma=20_multi_%d.png", folder.c_str(), i); + original[i] = imread(original_path, CV_LOAD_IMAGE_GRAYSCALE); + ASSERT_FALSE(original[i].empty()) << "Could not load input image " << original_path; } - Mat res; - fastNlMeansDenoisingMulti(src_imgs, imgs_count / 2, imgs_count, res, 7, 21, 15); + Mat result; + fastNlMeansDenoisingMulti(original, result, imgs_count / 2, imgs_count, 15); - if (norm(res - exp) > 0) { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - } else { - ts->set_failed_test_info(cvtest::TS::OK); - } + DUMP(result, expected_path + ".res.png"); + + ASSERT_EQ(0, norm(result != expected)); } -class CV_DenoisingColoredMultiTest : public cvtest::BaseTest +TEST(Imgproc_DenoisingColoredMulti, regression) { -public: - CV_DenoisingColoredMultiTest(); - ~CV_DenoisingColoredMultiTest(); -protected: - void run(int); -}; - -CV_DenoisingColoredMultiTest::CV_DenoisingColoredMultiTest() {} -CV_DenoisingColoredMultiTest::~CV_DenoisingColoredMultiTest() {} - -void CV_DenoisingColoredMultiTest::run( int ) -{ - string folder = string(ts->get_data_path()) + "denoising/"; - const int imgs_count = 3; - vector src_imgs(imgs_count); - src_imgs[0] = imread(folder + "lena_noised_gaussian_sigma=20_multi_0.png", 1); - src_imgs[1] = imread(folder + "lena_noised_gaussian_sigma=20_multi_1.png", 1); - src_imgs[2] = imread(folder + "lena_noised_gaussian_sigma=20_multi_2.png", 1); - - Mat exp = imread(folder + "lena_noised_denoised_multi_lab12_tw=7_sw=21_h=10_h2=15.png", 1); - - bool have_empty_src = false; - for (int i = 0; i < imgs_count; i++) { - have_empty_src |= src_imgs[i].empty(); - } + string folder = string(cvtest::TS::ptr()->get_data_path()) + "denoising/"; + + string expected_path = folder + "lena_noised_denoised_multi_lab12_tw=7_sw=21_h=10_h2=15.png"; + Mat expected = imread(expected_path, CV_LOAD_IMAGE_COLOR); + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; - if (have_empty_src || exp.empty()) + vector original(imgs_count); + for (int i = 0; i < imgs_count; i++) { - ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); - return; + string original_path = format("%slena_noised_gaussian_sigma=20_multi_%d.png", folder.c_str(), i); + original[i] = imread(original_path, CV_LOAD_IMAGE_COLOR); + ASSERT_FALSE(original[i].empty()) << "Could not load input image " << original_path; } - Mat res; - fastNlMeansDenoisingColoredMulti(src_imgs, imgs_count / 2, imgs_count, res, 7, 21, 10, 15); - - if (norm(res - exp) > 0) { - ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); - } else { - ts->set_failed_test_info(cvtest::TS::OK); - } -} + Mat result; + fastNlMeansDenoisingColoredMulti(original, result, imgs_count / 2, imgs_count, 10, 15); + DUMP(result, expected_path + ".res.png"); -TEST(Imgproc_DenoisingGrayscale, regression) { CV_DenoisingGrayscaleTest test; test.safe_run(); } -TEST(Imgproc_DenoisingColored, regression) { CV_DenoisingColoredTest test; test.safe_run(); } -TEST(Imgproc_DenoisingGrayscaleMulti, regression) { CV_DenoisingGrayscaleMultiTest test; test.safe_run(); } -TEST(Imgproc_DenoisingColoredMulti, regression) { CV_DenoisingColoredMultiTest test; test.safe_run(); } + ASSERT_EQ(0, norm(result != expected)); +}