vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(xphoto_dctimagedenoising, regression)
|
||||
{
|
||||
cv::String subfolder = "cv/xphoto/";
|
||||
cv::String dir = cvtest::TS::ptr()->get_data_path() + subfolder + "dct_image_denoising/";
|
||||
int nTests = 1;
|
||||
|
||||
double thresholds[] = {0.2};
|
||||
|
||||
int psize[] = {8};
|
||||
double sigma[] = {9.0};
|
||||
|
||||
for (int i = 0; i < nTests; ++i)
|
||||
{
|
||||
cv::String srcName = dir + cv::format( "sources/%02d.png", i + 1);
|
||||
cv::Mat src = cv::imread( srcName, 1 );
|
||||
ASSERT_TRUE(!src.empty());
|
||||
|
||||
cv::String previousResultName = dir + cv::format( "results/%02d.png", i + 1 );
|
||||
cv::Mat previousResult = cv::imread( previousResultName, 1 );
|
||||
ASSERT_TRUE(!src.empty());
|
||||
|
||||
cv::Mat currentResult;
|
||||
|
||||
cv::xphoto::dctDenoising(src, currentResult, sigma[i], psize[i]);
|
||||
|
||||
cv::Mat sqrError = ( currentResult - previousResult )
|
||||
.mul( currentResult - previousResult );
|
||||
cv::Scalar mse = cv::sum(sqrError) / cv::Scalar::all( double(sqrError.total()*sqrError.channels()) );
|
||||
|
||||
EXPECT_LE( mse[0] + mse[1] + mse[2] + mse[3], thresholds[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,273 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_max_value)
|
||||
{
|
||||
const uchar oldMax = 120, newMax = 255;
|
||||
|
||||
Mat test = Mat::zeros(3,3,CV_8UC1);
|
||||
test.at<uchar>(0, 0) = oldMax;
|
||||
test.at<uchar>(0, 1) = oldMax / 2;
|
||||
test.at<uchar>(0, 2) = oldMax / 4;
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(0);
|
||||
wb->setInputMax(oldMax);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(newMax);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double minDst, maxDst;
|
||||
cv::minMaxIdx(test, &minDst, &maxDst);
|
||||
|
||||
ASSERT_NEAR(maxDst, newMax, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_min_value)
|
||||
{
|
||||
const uchar oldMin = 120, newMin = 0;
|
||||
|
||||
Mat test = Mat::zeros(1,3,CV_8UC1);
|
||||
test.at<uchar>(0, 0) = oldMin;
|
||||
test.at<uchar>(0, 1) = (256 + oldMin) / 2;
|
||||
test.at<uchar>(0, 2) = 255;
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(oldMin);
|
||||
wb->setInputMax(255);
|
||||
wb->setOutputMin(newMin);
|
||||
wb->setOutputMax(255);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double minDst, maxDst;
|
||||
cv::minMaxIdx(test, &minDst, &maxDst);
|
||||
|
||||
ASSERT_NEAR(minDst, newMin, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_equal_range)
|
||||
{
|
||||
const int N = 4;
|
||||
uchar data[N] = {0, 1, 16, 255};
|
||||
Mat test = Mat(1, N, CV_8UC1, data);
|
||||
Mat result = Mat(1, N, CV_8UC1, data);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(0);
|
||||
wb->setInputMax(255);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(255);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_single_value)
|
||||
{
|
||||
const int N = 4;
|
||||
uchar data0[N] = {51, 51, 51, 51};
|
||||
uchar data1[N] = {33, 33, 33, 33};
|
||||
Mat test = Mat(1, N, CV_8UC1, data0);
|
||||
Mat result = Mat(1, N, CV_8UC1, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(51);
|
||||
wb->setInputMax(51);
|
||||
wb->setOutputMin(33);
|
||||
wb->setOutputMax(200);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_p)
|
||||
{
|
||||
const int N = 5;
|
||||
uchar data0[N] = {10, 55, 102, 188, 233};
|
||||
uchar data1[N] = {0, 1, 90, 254, 255};
|
||||
Mat test = Mat(1, N, CV_8UC1, data0);
|
||||
Mat result = Mat(1, N, CV_8UC1, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(10);
|
||||
wb->setInputMax(233);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(255);
|
||||
wb->setP(21);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, uchar_c3)
|
||||
{
|
||||
const int N = 15;
|
||||
uchar data0[N] = {10, 55, 102, 55, 102, 188, 102, 188, 233, 188, 233, 10, 233, 10, 55};
|
||||
uchar data1[N] = {0, 1, 90, 1, 90, 254, 90, 254, 255, 254, 255, 0, 255, 0, 1};
|
||||
Mat test = Mat(1, N / 3, CV_8UC3, data0);
|
||||
Mat result = Mat(1, N / 3, CV_8UC3, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(10);
|
||||
wb->setInputMax(233);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(255);
|
||||
wb->setP(21);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_max_value)
|
||||
{
|
||||
const float oldMax = 24000.f, newMax = 65536.f;
|
||||
|
||||
Mat test = Mat::zeros(3,3,CV_32FC1);
|
||||
test.at<float>(0, 0) = oldMax;
|
||||
test.at<float>(0, 1) = oldMax / 2;
|
||||
test.at<float>(0, 2) = oldMax / 4;
|
||||
|
||||
double minSrc, maxSrc;
|
||||
cv::minMaxIdx(test, &minSrc, &maxSrc);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin((float)minSrc);
|
||||
wb->setInputMax((float)maxSrc);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(newMax);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double minDst, maxDst;
|
||||
cv::minMaxIdx(test, &minDst, &maxDst);
|
||||
|
||||
ASSERT_NEAR(maxDst, newMax, newMax*1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_min_value)
|
||||
{
|
||||
const float oldMin = 24000.f, newMin = 0.f;
|
||||
|
||||
Mat test = Mat::zeros(1,3,CV_32FC1);
|
||||
test.at<float>(0, 0) = oldMin;
|
||||
test.at<float>(0, 1) = (65536.f + oldMin) / 2;
|
||||
test.at<float>(0, 2) = 65536.f;
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(oldMin);
|
||||
wb->setInputMax(65536.f);
|
||||
wb->setOutputMin(newMin);
|
||||
wb->setOutputMax(65536.f);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double minDst, maxDst;
|
||||
cv::minMaxIdx(test, &minDst, &maxDst);
|
||||
|
||||
ASSERT_NEAR(minDst, newMin, 65536*1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_equal_range)
|
||||
{
|
||||
const int N = 5;
|
||||
float data[N] = {0.f, 1.f, 16.2f, 256.3f, 4096.f};
|
||||
Mat test = Mat(1, N, CV_32FC1, data);
|
||||
Mat result = Mat(1, N, CV_32FC1, data);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(0);
|
||||
wb->setInputMax(4096);
|
||||
wb->setOutputMin(0);
|
||||
wb->setOutputMax(4096);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_single_value)
|
||||
{
|
||||
const int N = 4;
|
||||
float data0[N] = {24000.5f, 24000.5f, 24000.5f, 24000.5f};
|
||||
float data1[N] = {52000.25f, 52000.25f, 52000.25f, 52000.25f};
|
||||
Mat test = Mat(1, N, CV_32FC1, data0);
|
||||
Mat result = Mat(1, N, CV_32FC1, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(24000.5f);
|
||||
wb->setInputMax(24000.5f);
|
||||
wb->setOutputMin(52000.25f);
|
||||
wb->setOutputMax(65536.f);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 65536*1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_p)
|
||||
{
|
||||
const int N = 5;
|
||||
float data0[N] = {16000.f, 20000.5f, 24000.f, 36000.5f, 48000.f};
|
||||
float data1[N] = {-16381.952f, 0.f, 16381.952f, 65536.f, 114685.952f};
|
||||
Mat test = Mat(1, N, CV_32FC1, data0);
|
||||
Mat result = Mat(1, N, CV_32FC1, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(16000.f);
|
||||
wb->setInputMax(48000.f);
|
||||
wb->setOutputMin(0.f);
|
||||
wb->setOutputMax(65536.f);
|
||||
wb->setP(21);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 65536*1e-4);
|
||||
}
|
||||
|
||||
TEST(xphoto_simplecolorbalance, float_c3)
|
||||
{
|
||||
const int N = 15;
|
||||
float data0[N] = {16000.f, 20000.5f, 24000.f, 20000.5f, 24000.f, 36000.5f, 24000.f, 36000.5f, 48000.f, 36000.5f, 48000.f, 16000.f, 48000.f, 16000.f, 20000.5f};
|
||||
float data1[N] = {-16381.952f, 0.f, 16381.952f, 0.f, 16381.952f, 65536.f, 16381.952f, 65536.f, 114685.952f, 65536.f, 114685.952f, -16381.952f, 114685.952f, -16381.952f, 0.f};
|
||||
Mat test = Mat(1, N / 3, CV_32FC3, data0);
|
||||
Mat result = Mat(1, N / 3, CV_32FC3, data1);
|
||||
|
||||
cv::Ptr<cv::xphoto::SimpleWB> wb = cv::xphoto::createSimpleWB();
|
||||
wb->setInputMin(16000.f);
|
||||
wb->setInputMax(48000.f);
|
||||
wb->setOutputMin(0.f);
|
||||
wb->setOutputMax(65536.f);
|
||||
wb->setP(21);
|
||||
|
||||
wb->balanceWhite(test, test);
|
||||
|
||||
double err;
|
||||
cv::minMaxIdx(cv::abs(test - result), NULL, &err);
|
||||
ASSERT_LE(err, 65536*1e-4);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,464 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
//#define DUMP_RESULTS
|
||||
//#define TEST_TRANSFORMS
|
||||
|
||||
#ifdef TEST_TRANSFORMS
|
||||
#include "..\..\xphoto\src\bm3d_denoising_invoker_commons.hpp"
|
||||
#include "..\..\xphoto\src\bm3d_denoising_transforms.hpp"
|
||||
#include "..\..\xphoto\src\kaiser_window.hpp"
|
||||
using namespace cv::xphoto;
|
||||
#endif
|
||||
|
||||
#ifdef DUMP_RESULTS
|
||||
# define DUMP(image, path) imwrite(path, image)
|
||||
#else
|
||||
# define DUMP(image, path)
|
||||
#endif
|
||||
|
||||
#ifdef OPENCV_ENABLE_NONFREE
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(xphoto_DenoisingBm3dGrayscale, regression_L2)
|
||||
{
|
||||
std::string folder = std::string(cvtest::TS::ptr()->get_data_path()) + "cv/xphoto/bm3d_image_denoising/";
|
||||
std::string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
std::string expected_path = folder + "lena_noised_denoised_bm3d_wiener_grayscale_l2_tw=4_sw=16_h=10_bm=400.png";
|
||||
|
||||
cv::Mat original = cv::imread(original_path, cv::IMREAD_GRAYSCALE);
|
||||
cv::Mat expected = cv::imread(expected_path, cv::IMREAD_GRAYSCALE);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
// BM3D: two different calls doing exactly the same thing
|
||||
cv::Mat result, resultSec;
|
||||
cv::xphoto::bm3dDenoising(original, noArray(), resultSec, 10, 4, 16, 2500, 400, 8, 1, 0.0f, cv::NORM_L2, cv::xphoto::BM3D_STEPALL);
|
||||
cv::xphoto::bm3dDenoising(original, result, 10, 4, 16, 2500, 400, 8, 1, 0.0f, cv::NORM_L2, cv::xphoto::BM3D_STEPALL);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_EQ(cvtest::norm(result, resultSec, cv::NORM_L2), 0);
|
||||
ASSERT_LT(cvtest::norm(result, expected, cv::NORM_L2), 200);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dGrayscale, regression_L2_separate)
|
||||
{
|
||||
std::string folder = std::string(cvtest::TS::ptr()->get_data_path()) + "cv/xphoto/bm3d_image_denoising/";
|
||||
std::string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
std::string expected_basic_path = folder + "lena_noised_denoised_bm3d_grayscale_l2_tw=4_sw=16_h=10_bm=2500.png";
|
||||
std::string expected_path = folder + "lena_noised_denoised_bm3d_wiener_grayscale_l2_tw=4_sw=16_h=10_bm=400.png";
|
||||
|
||||
cv::Mat original = cv::imread(original_path, cv::IMREAD_GRAYSCALE);
|
||||
cv::Mat expected_basic = cv::imread(expected_basic_path, cv::IMREAD_GRAYSCALE);
|
||||
cv::Mat expected = cv::imread(expected_path, cv::IMREAD_GRAYSCALE);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected_basic.empty()) << "Could not load reference image " << expected_basic_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load input image " << expected_path;
|
||||
|
||||
cv::Mat basic, result;
|
||||
|
||||
// BM3D step 1
|
||||
cv::xphoto::bm3dDenoising(original, basic, 10, 4, 16, 2500, -1, 8, 1, 0.0f, cv::NORM_L2, cv::xphoto::BM3D_STEP1);
|
||||
ASSERT_LT(cvtest::norm(basic, expected_basic, cv::NORM_L2), 200);
|
||||
DUMP(basic, expected_basic_path + ".res.basic.png");
|
||||
|
||||
// BM3D step 2
|
||||
cv::xphoto::bm3dDenoising(original, basic, result, 10, 4, 16, 2500, 400, 8, 1, 0.0f, cv::NORM_L2, cv::xphoto::BM3D_STEP2);
|
||||
ASSERT_LT(cvtest::norm(basic, expected_basic, cv::NORM_L2), 200);
|
||||
DUMP(basic, expected_basic_path + ".res.basic2.png");
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_LT(cvtest::norm(result, expected, cv::NORM_L2), 200);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dGrayscale, regression_L1)
|
||||
{
|
||||
std::string folder = std::string(cvtest::TS::ptr()->get_data_path()) + "cv/xphoto/bm3d_image_denoising/";
|
||||
std::string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
std::string expected_path = folder + "lena_noised_denoised_bm3d_grayscale_l1_tw=4_sw=16_h=10_bm=2500.png";
|
||||
|
||||
cv::Mat original = cv::imread(original_path, cv::IMREAD_GRAYSCALE);
|
||||
cv::Mat expected = cv::imread(expected_path, cv::IMREAD_GRAYSCALE);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
cv::Mat result;
|
||||
cv::xphoto::bm3dDenoising(original, result, 10, 4, 16, 2500, -1, 8, 1, 0.0f, cv::NORM_L1, cv::xphoto::BM3D_STEP1);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_LT(cvtest::norm(result, expected, cv::NORM_L2), 200);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dGrayscale, regression_L2_8x8)
|
||||
{
|
||||
std::string folder = std::string(cvtest::TS::ptr()->get_data_path()) + "cv/xphoto/bm3d_image_denoising/";
|
||||
std::string original_path = folder + "lena_noised_gaussian_sigma=10.png";
|
||||
std::string expected_path = folder + "lena_noised_denoised_bm3d_grayscale_l2_tw=8_sw=16_h=10_bm=2500.png";
|
||||
|
||||
cv::Mat original = cv::imread(original_path, cv::IMREAD_GRAYSCALE);
|
||||
cv::Mat expected = cv::imread(expected_path, cv::IMREAD_GRAYSCALE);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path;
|
||||
|
||||
cv::Mat result;
|
||||
cv::xphoto::bm3dDenoising(original, result, 10, 8, 16, 2500, -1, 8, 1, 0.0f, cv::NORM_L2, cv::xphoto::BM3D_STEP1);
|
||||
|
||||
DUMP(result, expected_path + ".res.png");
|
||||
|
||||
ASSERT_LT(cvtest::norm(result, expected, cv::NORM_L2), 200);
|
||||
}
|
||||
|
||||
#ifdef TEST_TRANSFORMS
|
||||
|
||||
TEST(xphoto_DenoisingBm3dKaiserWindow, regression_4)
|
||||
{
|
||||
float beta = 2.0f;
|
||||
int N = 4;
|
||||
|
||||
cv::Mat kaiserWindow;
|
||||
calcKaiserWindow1D(kaiserWindow, N, beta);
|
||||
|
||||
float kaiser4[] = {
|
||||
0.43869004f,
|
||||
0.92432547f,
|
||||
0.92432547f,
|
||||
0.43869004f
|
||||
};
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
ASSERT_FLOAT_EQ(kaiser4[i], kaiserWindow.at<float>(i));
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dKaiserWindow, regression_8)
|
||||
{
|
||||
float beta = 2.0f;
|
||||
int N = 8;
|
||||
|
||||
cv::Mat kaiserWindow;
|
||||
calcKaiserWindow1D(kaiserWindow, N, beta);
|
||||
|
||||
float kaiser8[] = {
|
||||
0.43869004f,
|
||||
0.68134475f,
|
||||
0.87685609f,
|
||||
0.98582518f,
|
||||
0.98582518f,
|
||||
0.87685609f,
|
||||
0.68134463f,
|
||||
0.43869004f
|
||||
};
|
||||
|
||||
for (int i = 0; i < N; ++i)
|
||||
ASSERT_FLOAT_EQ(kaiser8[i], kaiserWindow.at<float>(i));
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_2D_generic)
|
||||
{
|
||||
const int templateWindowSize = 8;
|
||||
const int templateWindowSizeSq = templateWindowSize * templateWindowSize;
|
||||
|
||||
uchar src[templateWindowSizeSq];
|
||||
short dst[templateWindowSizeSq];
|
||||
short dstSec[templateWindowSizeSq];
|
||||
|
||||
// Initialize array
|
||||
for (uchar i = 0; i < templateWindowSizeSq; ++i)
|
||||
src[i] = (i % 10) * 10;
|
||||
|
||||
// Use tailored transforms
|
||||
HaarTransform<uchar, short>::RegisterTransforms2D(templateWindowSize);
|
||||
HaarTransform<uchar, short>::forwardTransform2D(src, dst, templateWindowSize, templateWindowSize);
|
||||
HaarTransform<uchar, short>::inverseTransform2D(dst, templateWindowSize);
|
||||
|
||||
// Use generic transforms
|
||||
HaarTransform2D::ForwardTransformXxX<uchar, short, templateWindowSize>(src, dstSec, templateWindowSize, templateWindowSize);
|
||||
HaarTransform2D::InverseTransformXxX<short, templateWindowSize>(dstSec, templateWindowSize);
|
||||
|
||||
for (unsigned i = 0; i < templateWindowSizeSq; ++i)
|
||||
ASSERT_EQ(dst[i], dstSec[i]);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_2D_4x4)
|
||||
{
|
||||
const int templateWindowSize = 4;
|
||||
const int templateWindowSizeSq = templateWindowSize * templateWindowSize;
|
||||
|
||||
uchar src[templateWindowSizeSq];
|
||||
short dst[templateWindowSizeSq];
|
||||
|
||||
// Initialize array
|
||||
for (uchar i = 0; i < templateWindowSizeSq; ++i)
|
||||
{
|
||||
src[i] = i;
|
||||
}
|
||||
|
||||
HaarTransform2D::ForwardTransform4x4(src, dst, templateWindowSize, templateWindowSize);
|
||||
HaarTransform2D::InverseTransform4x4(dst, templateWindowSize);
|
||||
|
||||
for (uchar i = 0; i < templateWindowSizeSq; ++i)
|
||||
ASSERT_EQ(static_cast<short>(src[i]), dst[i]);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_2D_8x8)
|
||||
{
|
||||
const int templateWindowSize = 8;
|
||||
const int templateWindowSizeSq = templateWindowSize * templateWindowSize;
|
||||
|
||||
uchar src[templateWindowSizeSq];
|
||||
short dst[templateWindowSizeSq];
|
||||
|
||||
// Initialize array
|
||||
for (uchar i = 0; i < templateWindowSizeSq; ++i)
|
||||
{
|
||||
src[i] = i;
|
||||
}
|
||||
|
||||
HaarTransform2D::ForwardTransform8x8(src, dst, templateWindowSize, templateWindowSize);
|
||||
HaarTransform2D::InverseTransform8x8(dst, templateWindowSize);
|
||||
|
||||
for (uchar i = 0; i < templateWindowSizeSq; ++i)
|
||||
ASSERT_EQ(static_cast<short>(src[i]), dst[i]);
|
||||
}
|
||||
|
||||
template <typename T, typename DT, typename CT>
|
||||
static void Test1dTransform(
|
||||
T *thrMap,
|
||||
int groupSize,
|
||||
int templateWindowSizeSq,
|
||||
BlockMatch<T, DT, CT> *bm,
|
||||
BlockMatch<T, DT, CT> *bmOrig,
|
||||
int expectedNonZeroCount = -1)
|
||||
{
|
||||
if (expectedNonZeroCount < 0)
|
||||
expectedNonZeroCount = groupSize * templateWindowSizeSq;
|
||||
|
||||
// Test group size
|
||||
short sumNonZero = 0;
|
||||
T *thrMapPtr1D = thrMap + (groupSize - 1) * templateWindowSizeSq;
|
||||
for (int n = 0; n < templateWindowSizeSq; n++)
|
||||
{
|
||||
switch (groupSize)
|
||||
{
|
||||
case 16:
|
||||
HaarTransform1D::ForwardTransform16(bm, n);
|
||||
sumNonZero += HardThreshold<16>(bm, n, thrMapPtr1D);
|
||||
HaarTransform1D::InverseTransform16(bm, n);
|
||||
break;
|
||||
case 8:
|
||||
HaarTransform1D::ForwardTransform8(bm, n);
|
||||
sumNonZero += HardThreshold<8>(bm, n, thrMapPtr1D);
|
||||
HaarTransform1D::InverseTransform8(bm, n);
|
||||
break;
|
||||
case 4:
|
||||
HaarTransform1D::ForwardTransform4(bm, n);
|
||||
sumNonZero += HardThreshold<4>(bm, n, thrMapPtr1D);
|
||||
HaarTransform1D::InverseTransform4(bm, n);
|
||||
break;
|
||||
case 2:
|
||||
HaarTransform1D::ForwardTransform2(bm, n);
|
||||
sumNonZero += HardThreshold<2>(bm, n, thrMapPtr1D);
|
||||
HaarTransform1D::InverseTransform2(bm, n);
|
||||
break;
|
||||
default:
|
||||
HaarTransform1D::ForwardTransformN(bm, n, groupSize);
|
||||
sumNonZero += HardThreshold(bm, n, thrMapPtr1D, groupSize);
|
||||
HaarTransform1D::InverseTransformN(bm, n, groupSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Assert transform
|
||||
if (expectedNonZeroCount == groupSize * templateWindowSizeSq)
|
||||
{
|
||||
for (int i = 0; i < groupSize; ++i)
|
||||
for (int j = 0; j < templateWindowSizeSq; ++j)
|
||||
ASSERT_EQ(bm[i][j], bmOrig[i][j]);
|
||||
}
|
||||
|
||||
// Assert shrinkage
|
||||
ASSERT_EQ(sumNonZero, expectedNonZeroCount);
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_1D_transform)
|
||||
{
|
||||
const int templateWindowSize = 4;
|
||||
const int templateWindowSizeSq = templateWindowSize * templateWindowSize;
|
||||
const int searchWindowSize = 16;
|
||||
const int searchWindowSizeSq = searchWindowSize * searchWindowSize;
|
||||
const float h = 10;
|
||||
int maxGroupSize = 64;
|
||||
|
||||
// Precompute separate maps for transform and shrinkage verification
|
||||
short *thrMapTransform = NULL;
|
||||
short *thrMapShrinkage = NULL;
|
||||
HaarTransform<short, short>::calcThresholdMap3D(thrMapTransform, 0, templateWindowSize, maxGroupSize);
|
||||
HaarTransform<short, short>::calcThresholdMap3D(thrMapShrinkage, h, templateWindowSize, maxGroupSize);
|
||||
|
||||
// Generate some data
|
||||
BlockMatch<short, int, short> *bm = new BlockMatch<short, int, short>[maxGroupSize];
|
||||
BlockMatch<short, int, short> *bmOrig = new BlockMatch<short, int, short>[maxGroupSize];
|
||||
for (int i = 0; i < maxGroupSize; ++i)
|
||||
{
|
||||
bm[i].init(templateWindowSizeSq);
|
||||
bmOrig[i].init(templateWindowSizeSq);
|
||||
}
|
||||
|
||||
for (short i = 0; i < maxGroupSize; ++i)
|
||||
{
|
||||
for (short j = 0; j < templateWindowSizeSq; ++j)
|
||||
{
|
||||
bm[i][j] = (j + 1);
|
||||
bmOrig[i][j] = bm[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// Verify transforms
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 2, templateWindowSizeSq, bm, bmOrig);
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 4, templateWindowSizeSq, bm, bmOrig);
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 8, templateWindowSizeSq, bm, bmOrig);
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 16, templateWindowSizeSq, bm, bmOrig);
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 32, templateWindowSizeSq, bm, bmOrig);
|
||||
Test1dTransform<short, int, short>(thrMapTransform, 64, templateWindowSizeSq, bm, bmOrig);
|
||||
|
||||
// Verify shrinkage
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 2, templateWindowSizeSq, bm, bmOrig, 6);
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 4, templateWindowSizeSq, bm, bmOrig, 6);
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 8, templateWindowSizeSq, bm, bmOrig, 6);
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 16, templateWindowSizeSq, bm, bmOrig, 6);
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 32, templateWindowSizeSq, bm, bmOrig, 6);
|
||||
Test1dTransform<short, int, short>(thrMapShrinkage, 64, templateWindowSizeSq, bm, bmOrig, 14);
|
||||
}
|
||||
|
||||
const float sqrt2 = std::sqrt(2.0f);
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_1D_generate)
|
||||
{
|
||||
const int numberOfElements = 8;
|
||||
const int arrSize = (numberOfElements << 1) - 1;
|
||||
float *thrMap1D = NULL;
|
||||
HaarTransform<short, short>::calcThresholdMap1D(thrMap1D, numberOfElements);
|
||||
|
||||
// Expected array
|
||||
const float kThrMap1D[arrSize] = {
|
||||
1.0f, // 1 element
|
||||
sqrt2 / 2.0f, sqrt2, // 2 elements
|
||||
0.5f, 1.0f, sqrt2, sqrt2, // 4 elements
|
||||
sqrt2 / 4.0f, sqrt2 / 2.0f, 1.0f, 1.0f, sqrt2, sqrt2, sqrt2, sqrt2 // 8 elements
|
||||
};
|
||||
|
||||
for (int j = 0; j < arrSize; ++j)
|
||||
ASSERT_EQ(thrMap1D[j], kThrMap1D[j]);
|
||||
|
||||
delete[] thrMap1D;
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_2D_generate_4x4)
|
||||
{
|
||||
const int templateWindowSize = 4;
|
||||
float *thrMap2D = NULL;
|
||||
HaarTransform<short, short>::calcThresholdMap2D(thrMap2D, templateWindowSize);
|
||||
|
||||
// Expected array
|
||||
const float kThrMap4x4[templateWindowSize * templateWindowSize] = {
|
||||
0.25f, 0.5f, sqrt2 / 2.0f, sqrt2 / 2.0f,
|
||||
0.5f, 1.0f, sqrt2, sqrt2,
|
||||
sqrt2 / 2.0f, sqrt2, 2.0f, 2.0f,
|
||||
sqrt2 / 2.0f, sqrt2, 2.0f, 2.0f
|
||||
};
|
||||
|
||||
for (int j = 0; j < templateWindowSize * templateWindowSize; ++j)
|
||||
ASSERT_EQ(thrMap2D[j], kThrMap4x4[j]);
|
||||
|
||||
delete[] thrMap2D;
|
||||
}
|
||||
|
||||
TEST(xphoto_DenoisingBm3dTransforms, regression_2D_generate_8x8)
|
||||
{
|
||||
const int templateWindowSize = 8;
|
||||
float *thrMap2D = NULL;
|
||||
HaarTransform<short, short>::calcThresholdMap2D(thrMap2D, templateWindowSize);
|
||||
|
||||
// Expected array
|
||||
const float kThrMap8x8[templateWindowSize * templateWindowSize] = {
|
||||
0.125f, 0.25f, sqrt2 / 4.0f, sqrt2 / 4.0f, 0.5f, 0.5f, 0.5f, 0.5f,
|
||||
0.25f, 0.5f, sqrt2 / 2.0f, sqrt2 / 2.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
sqrt2 / 4.0f, sqrt2 / 2.0f, 1.0f, 1.0f, sqrt2, sqrt2, sqrt2, sqrt2,
|
||||
sqrt2 / 4.0f, sqrt2 / 2.0f, 1.0f, 1.0f, sqrt2, sqrt2, sqrt2, sqrt2,
|
||||
0.5f, 1.0f, sqrt2, sqrt2, 2.0f, 2.0f, 2.0f, 2.0f,
|
||||
0.5f, 1.0f, sqrt2, sqrt2, 2.0f, 2.0f, 2.0f, 2.0f,
|
||||
0.5f, 1.0f, sqrt2, sqrt2, 2.0f, 2.0f, 2.0f, 2.0f,
|
||||
0.5f, 1.0f, sqrt2, sqrt2, 2.0f, 2.0f, 2.0f, 2.0f
|
||||
};
|
||||
|
||||
for (int j = 0; j < templateWindowSize * templateWindowSize; ++j)
|
||||
ASSERT_EQ(thrMap2D[j], kThrMap8x8[j]);
|
||||
|
||||
delete[] thrMap2D;
|
||||
}
|
||||
|
||||
TEST(xphoto_Bm3dDenoising, powerOf2)
|
||||
{
|
||||
ASSERT_EQ(8, getLargestPowerOf2SmallerThan(9));
|
||||
ASSERT_EQ(16, getLargestPowerOf2SmallerThan(21));
|
||||
ASSERT_EQ(4, getLargestPowerOf2SmallerThan(7));
|
||||
ASSERT_EQ(8, getLargestPowerOf2SmallerThan(8));
|
||||
ASSERT_EQ(4, getLargestPowerOf2SmallerThan(5));
|
||||
ASSERT_EQ(4, getLargestPowerOf2SmallerThan(4));
|
||||
ASSERT_EQ(2, getLargestPowerOf2SmallerThan(3));
|
||||
ASSERT_EQ(1, getLargestPowerOf2SmallerThan(1));
|
||||
ASSERT_EQ(0, getLargestPowerOf2SmallerThan(0));
|
||||
}
|
||||
|
||||
#endif // TEST_TRANSFORMS
|
||||
|
||||
}} // namespace
|
||||
|
||||
#endif // OPENCV_ENABLE_NONFREE
|
||||
@@ -0,0 +1,99 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
void ref_autowbGrayworld(InputArray _src, OutputArray _dst, float thresh)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int width = src.cols,
|
||||
height = src.rows,
|
||||
N = width*height,
|
||||
N3 = N*3;
|
||||
|
||||
// Calculate sum of pixel values of each channel
|
||||
const uchar* src_data = src.ptr<uchar>(0);
|
||||
unsigned long sum1 = 0, sum2 = 0, sum3 = 0;
|
||||
int i = 0;
|
||||
unsigned int minRGB, maxRGB, thresh255 = cvRound(thresh * 255);
|
||||
for ( ; i < N3; i += 3 )
|
||||
{
|
||||
minRGB = std::min(src_data[i], std::min(src_data[i + 1], src_data[i + 2]));
|
||||
maxRGB = std::max(src_data[i], std::max(src_data[i + 1], src_data[i + 2]));
|
||||
if ( (maxRGB - minRGB) * 255 > thresh255 * maxRGB ) continue;
|
||||
sum1 += src_data[i];
|
||||
sum2 += src_data[i + 1];
|
||||
sum3 += src_data[i + 2];
|
||||
}
|
||||
|
||||
// Find inverse of averages
|
||||
double inv1 = sum1 == 0 ? 0.f : (double)N / (double)sum1,
|
||||
inv2 = sum2 == 0 ? 0.f : (double)N / (double)sum2,
|
||||
inv3 = sum3 == 0 ? 0.f : (double)N / (double)sum3;
|
||||
|
||||
// Find maximum
|
||||
double inv_max = std::max(std::max(inv1, inv2), inv3);
|
||||
|
||||
// Scale by maximum
|
||||
if ( inv_max > 0 )
|
||||
{
|
||||
inv1 = (double) inv1 / inv_max;
|
||||
inv2 = (double) inv2 / inv_max;
|
||||
inv3 = (double) inv3 / inv_max;
|
||||
}
|
||||
|
||||
// Fixed point arithmetic, mul by 2^8 then shift back 8 bits
|
||||
int i_inv1 = cvRound(inv1 * (1 << 8)),
|
||||
i_inv2 = cvRound(inv2 * (1 << 8)),
|
||||
i_inv3 = cvRound(inv3 * (1 << 8));
|
||||
|
||||
// Scale input pixel values
|
||||
uchar* dst_data = dst.ptr<uchar>(0);
|
||||
i = 0;
|
||||
for ( ; i < N3; i += 3 )
|
||||
{
|
||||
dst_data[i] = (uchar)((src_data[i] * i_inv1) >> 8);
|
||||
dst_data[i + 1] = (uchar)((src_data[i + 1] * i_inv2) >> 8);
|
||||
dst_data[i + 2] = (uchar)((src_data[i + 2] * i_inv3) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(xphoto_grayworld_white_balance, regression)
|
||||
{
|
||||
String dir = cvtest::TS::ptr()->get_data_path() + "cv/xphoto/simple_white_balance/";
|
||||
const int nTests = 8;
|
||||
const float wb_thresh = 0.5f;
|
||||
const float acc_thresh = 2.f;
|
||||
Ptr<xphoto::GrayworldWB> wb = xphoto::createGrayworldWB();
|
||||
wb->setSaturationThreshold(wb_thresh);
|
||||
|
||||
for ( int i = 0; i < nTests; ++i )
|
||||
{
|
||||
String srcName = dir + format("sources/%02d.png", i + 1);
|
||||
Mat src = imread(srcName, IMREAD_COLOR);
|
||||
ASSERT_TRUE(!src.empty());
|
||||
|
||||
Mat referenceResult;
|
||||
ref_autowbGrayworld(src, referenceResult, wb_thresh);
|
||||
|
||||
Mat currentResult;
|
||||
wb->balanceWhite(src, currentResult);
|
||||
ASSERT_LE(cv::norm(currentResult, referenceResult, NORM_INF), acc_thresh);
|
||||
|
||||
// test the 16-bit depth:
|
||||
Mat currentResult_16U, src_16U;
|
||||
src.convertTo(src_16U, CV_16UC3, 256.0);
|
||||
wb->balanceWhite(src_16U, currentResult_16U);
|
||||
currentResult_16U.convertTo(currentResult, CV_8UC3, 1/256.0);
|
||||
ASSERT_LE(cv::norm(currentResult, referenceResult, NORM_INF), acc_thresh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,71 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
using namespace cv::xphoto;
|
||||
|
||||
#ifdef OPENCV_ENABLE_NONFREE
|
||||
|
||||
void loadImage(string path, Mat &img)
|
||||
{
|
||||
img = imread(path, -1);
|
||||
ASSERT_FALSE(img.empty()) << "Could not load input image " << path;
|
||||
}
|
||||
|
||||
void checkEqual(Mat img0, Mat img1, double threshold, const string& name)
|
||||
{
|
||||
double max = 1.0;
|
||||
minMaxLoc(abs(img0 - img1), NULL, &max);
|
||||
ASSERT_FALSE(max > threshold) << "max=" << max << " threshold=" << threshold << " method=" << name;
|
||||
}
|
||||
|
||||
TEST(Photo_Tonemap, Durand_regression)
|
||||
{
|
||||
string test_path = string(cvtest::TS::ptr()->get_data_path()) + "cv/hdr/tonemap/";
|
||||
|
||||
Mat img, expected, result;
|
||||
loadImage(test_path + "image.hdr", img);
|
||||
float gamma = 2.2f;
|
||||
|
||||
Ptr<TonemapDurand> durand = createTonemapDurand(gamma);
|
||||
durand->process(img, result);
|
||||
loadImage(test_path + "durand.png", expected);
|
||||
result.convertTo(result, CV_8UC3, 255);
|
||||
checkEqual(result, expected, 3, "Durand");
|
||||
}
|
||||
|
||||
TEST(Photo_Tonemap, Durand_property_regression)
|
||||
{
|
||||
const float gamma = 1.0f;
|
||||
const float contrast = 2.0f;
|
||||
const float saturation = 3.0f;
|
||||
const float sigma_color = 4.0f;
|
||||
const float sigma_space = 5.0f;
|
||||
|
||||
const Ptr<TonemapDurand> durand1 = createTonemapDurand(gamma, contrast, saturation, sigma_color, sigma_space);
|
||||
ASSERT_EQ(gamma, durand1->getGamma());
|
||||
ASSERT_EQ(contrast, durand1->getContrast());
|
||||
ASSERT_EQ(saturation, durand1->getSaturation());
|
||||
ASSERT_EQ(sigma_space, durand1->getSigmaSpace());
|
||||
ASSERT_EQ(sigma_color, durand1->getSigmaColor());
|
||||
|
||||
const Ptr<TonemapDurand> durand2 = createTonemapDurand();
|
||||
durand2->setGamma(gamma);
|
||||
durand2->setContrast(contrast);
|
||||
durand2->setSaturation(saturation);
|
||||
durand2->setSigmaColor(sigma_color);
|
||||
durand2->setSigmaSpace(sigma_space);
|
||||
ASSERT_EQ(gamma, durand2->getGamma());
|
||||
ASSERT_EQ(contrast, durand2->getContrast());
|
||||
ASSERT_EQ(saturation, durand2->getSaturation());
|
||||
ASSERT_EQ(sigma_color, durand2->getSigmaColor());
|
||||
ASSERT_EQ(sigma_space, durand2->getSigmaSpace());
|
||||
}
|
||||
|
||||
#endif // OPENCV_ENABLE_NONFREE
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,75 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
using namespace xphoto;
|
||||
|
||||
|
||||
static void test_inpainting(const Size inputSize, InpaintTypes mode, double expected_psnr, ImreadModes inputMode = IMREAD_COLOR)
|
||||
{
|
||||
string original_path = cvtest::findDataFile("cv/shared/lena.png");
|
||||
string mask_path = cvtest::findDataFile("cv/inpaint/mask.png");
|
||||
|
||||
Mat original_ = imread(original_path, inputMode);
|
||||
ASSERT_FALSE(original_.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat mask_ = imread(mask_path, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(mask_.empty()) << "Could not load error mask " << mask_path;
|
||||
|
||||
Mat original, mask;
|
||||
resize(original_, original, inputSize, 0.0, 0.0, INTER_AREA);
|
||||
resize(mask_, mask, inputSize, 0.0, 0.0, INTER_NEAREST);
|
||||
|
||||
Mat mask_valid = (mask == 0);
|
||||
Mat im_distorted(inputSize, original.type(), Scalar::all(0));
|
||||
original.copyTo(im_distorted, mask_valid);
|
||||
|
||||
Mat reconstructed;
|
||||
xphoto::inpaint(im_distorted, mask_valid, reconstructed, mode);
|
||||
|
||||
double adiff_psnr = cvtest::PSNR(original, reconstructed);
|
||||
EXPECT_LE(expected_psnr, adiff_psnr);
|
||||
|
||||
#if 0
|
||||
imshow("original", original);
|
||||
imshow("im_distorted", im_distorted);
|
||||
imshow("reconstructed", reconstructed);
|
||||
std::cout << "adiff_psnr=" << adiff_psnr << std::endl;
|
||||
waitKey();
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(xphoto_inpaint, smoke_FSR_FAST) // fast smoke test, input doesn't fit well for tested algorithm
|
||||
{
|
||||
test_inpainting(Size(128, 128), INPAINT_FSR_FAST, 30);
|
||||
}
|
||||
TEST(xphoto_inpaint, smoke_FSR_BEST) // fast smoke test, input doesn't fit well for tested algorithm
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_LONG);
|
||||
test_inpainting(Size(128, 128), INPAINT_FSR_BEST, 30);
|
||||
}
|
||||
|
||||
TEST(xphoto_inpaint, smoke_grayscale_FSR_FAST) // fast smoke test, input doesn't fit well for tested algorithm
|
||||
{
|
||||
test_inpainting(Size(128, 128), INPAINT_FSR_FAST, 30, IMREAD_GRAYSCALE);
|
||||
}
|
||||
TEST(xphoto_inpaint, smoke_grayscale_FSR_BEST) // fast smoke test, input doesn't fit well for tested algorithm
|
||||
{
|
||||
test_inpainting(Size(128, 128), INPAINT_FSR_BEST, 30, IMREAD_GRAYSCALE);
|
||||
}
|
||||
|
||||
|
||||
TEST(xphoto_inpaint, regression_FSR_FAST)
|
||||
{
|
||||
test_inpainting(Size(512, 512), INPAINT_FSR_FAST, 39.5);
|
||||
}
|
||||
TEST(xphoto_inpaint, regression_FSR_BEST)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_VERYLONG); // add --test_tag_enable=verylong to run this test
|
||||
test_inpainting(Size(512, 512), INPAINT_FSR_BEST, 39.6);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,47 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(xphoto_simplefeatures, regression)
|
||||
{
|
||||
float acc_thresh = 0.01f;
|
||||
|
||||
// Generate a test image:
|
||||
Mat test_im(1000, 1000, CV_8UC3);
|
||||
RNG rng(1234);
|
||||
rng.fill(test_im, RNG::NORMAL, Scalar(64, 100, 128), Scalar(10, 10, 10));
|
||||
cvtest::threshold(test_im, test_im, 200.0, 255.0, THRESH_TRUNC);
|
||||
test_im.at<Vec3b>(0, 0) = Vec3b(240, 220, 200);
|
||||
|
||||
// Which should have the following features:
|
||||
Vec2f ref1(128.0f / (64 + 100 + 128), 100.0f / (64 + 100 + 128));
|
||||
Vec2f ref2(200.0f / (240 + 220 + 200), 220.0f / (240 + 220 + 200));
|
||||
|
||||
vector<Vec2f> dst_features;
|
||||
Ptr<xphoto::LearningBasedWB> wb = xphoto::createLearningBasedWB();
|
||||
wb->setRangeMaxVal(255);
|
||||
wb->setSaturationThreshold(0.98f);
|
||||
wb->setHistBinNum(64);
|
||||
wb->extractSimpleFeatures(test_im, dst_features);
|
||||
ASSERT_LE(cv::norm(dst_features[0], ref1, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[1], ref2, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[2], ref1, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[3], ref1, NORM_INF), acc_thresh);
|
||||
|
||||
// check 16 bit depth:
|
||||
test_im.convertTo(test_im, CV_16U, 256.0);
|
||||
wb->setRangeMaxVal(65535);
|
||||
wb->setSaturationThreshold(0.98f);
|
||||
wb->setHistBinNum(128);
|
||||
wb->extractSimpleFeatures(test_im, dst_features);
|
||||
ASSERT_LE(cv::norm(dst_features[0], ref1, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[1], ref2, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[2], ref1, NORM_INF), acc_thresh);
|
||||
ASSERT_LE(cv::norm(dst_features[3], ref1, NORM_INF), acc_thresh);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,6 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("")
|
||||
@@ -0,0 +1,109 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
Mat testOilPainting(Mat imgSrc, int halfSize, int dynRatio, int colorSpace)
|
||||
{
|
||||
vector<int> histogramme;
|
||||
vector<Vec3f> moyenneRGB;
|
||||
Mat dst(imgSrc.size(), imgSrc.type());
|
||||
Mat lum;
|
||||
if (imgSrc.channels() != 1)
|
||||
{
|
||||
cvtColor(imgSrc, lum, colorSpace);
|
||||
if (lum.channels() > 1)
|
||||
{
|
||||
extractChannel(lum, lum, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
lum = imgSrc.clone();
|
||||
lum = lum / dynRatio;
|
||||
if (dst.channels() == 3)
|
||||
for (int y = 0; y < imgSrc.rows; y++)
|
||||
{
|
||||
Vec3b *vDst = dst.ptr<Vec3b>(y);
|
||||
for (int x = 0; x < imgSrc.cols; x++, vDst++) //for each pixel
|
||||
{
|
||||
Mat mask(lum.size(), CV_8UC1, Scalar::all(0));
|
||||
Rect r(Point(x - halfSize, y - halfSize), Size(2 * halfSize + 1, 2 * halfSize + 1));
|
||||
r = r & Rect(Point(0, 0), lum.size());
|
||||
mask(r).setTo(255);
|
||||
int histSize[] = { 256 };
|
||||
float hranges[] = { 0, 256 };
|
||||
const float* ranges[] = { hranges };
|
||||
Mat hist;
|
||||
int channels[] = { 0 };
|
||||
calcHist(&lum, 1, channels, mask, hist, 1, histSize, ranges, true, false);
|
||||
double maxVal = 0;
|
||||
Point pMin, pMax;
|
||||
minMaxLoc(hist, 0, &maxVal, &pMin, &pMax);
|
||||
mask.setTo(0, lum != static_cast<int>(pMax.x));
|
||||
Scalar v = mean(imgSrc, mask);
|
||||
*vDst = Vec3b(static_cast<uchar>(v[0]), static_cast<uchar>(v[1]), static_cast<uchar>(v[2]));
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int y = 0; y < imgSrc.rows; y++)
|
||||
{
|
||||
uchar *vDst = dst.ptr<uchar>(y);
|
||||
for (int x = 0; x < imgSrc.cols; x++, vDst++) //for each pixel
|
||||
{
|
||||
Mat mask(lum.size(), CV_8UC1, Scalar::all(0));
|
||||
Rect r(Point(x - halfSize, y - halfSize), Size(2 * halfSize + 1, 2 * halfSize + 1));
|
||||
r = r & Rect(Point(0, 0), lum.size());
|
||||
mask(r).setTo(255);
|
||||
int histSize[] = { 256 };
|
||||
float hranges[] = { 0, 256 };
|
||||
const float* ranges[] = { hranges };
|
||||
Mat hist;
|
||||
int channels[] = { 0 };
|
||||
calcHist(&lum, 1, channels, mask, hist, 1, histSize, ranges, true, false);
|
||||
double maxVal = 0;
|
||||
Point pMin, pMax;
|
||||
minMaxLoc(hist, 0, &maxVal, &pMin, &pMax);
|
||||
mask.setTo(0, lum != static_cast<int>(pMax.x));
|
||||
Scalar v = mean(imgSrc, mask);
|
||||
*vDst = static_cast<uchar>(v[0]);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
TEST(xphoto_oil_painting, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cv/inpaint/";
|
||||
Mat orig = imread(folder+"exp1.png", IMREAD_COLOR);
|
||||
ASSERT_TRUE(!orig.empty());
|
||||
resize(orig, orig, Size(100, 100));
|
||||
Mat dst1, dst2, dd;
|
||||
xphoto::oilPainting(orig, dst1, 3, 5, COLOR_BGR2GRAY);
|
||||
dst2 = testOilPainting(orig, 3, 5, COLOR_BGR2GRAY);
|
||||
absdiff(dst1, dst2, dd);
|
||||
vector<Mat> plane;
|
||||
split(dd, plane);
|
||||
for (auto p : plane)
|
||||
{
|
||||
double maxVal;
|
||||
Point pIdx;
|
||||
minMaxLoc(p, NULL, &maxVal, NULL, &pIdx);
|
||||
int v = p.at<uchar>(pIdx);
|
||||
ASSERT_LE(v, 2);
|
||||
}
|
||||
Mat orig2 = imread(folder + "exp1.png",IMREAD_GRAYSCALE);
|
||||
ASSERT_TRUE(!orig2.empty());
|
||||
resize(orig2, orig2, Size(100, 100));
|
||||
Mat dst3, dst4, ddd;
|
||||
xphoto::oilPainting(orig2, dst3, 3, 5, COLOR_BGR2GRAY);
|
||||
dst4 = testOilPainting(orig2, 3, 5, COLOR_BGR2GRAY);
|
||||
absdiff(dst3, dst4, ddd);
|
||||
double maxVal;
|
||||
Point pIdx;
|
||||
minMaxLoc(ddd, NULL, &maxVal, NULL, &pIdx);
|
||||
ASSERT_LE(ddd.at<uchar>(pIdx), 2);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,10 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/xphoto.hpp"
|
||||
#include "opencv2/ts.hpp"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user