diff --git a/modules/gpu/test/CMakeLists.txt b/modules/gpu/test/CMakeLists.txt index 744f151718..32d08eef25 100644 --- a/modules/gpu/test/CMakeLists.txt +++ b/modules/gpu/test/CMakeLists.txt @@ -5,7 +5,7 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include" "${CMAKE_CURRENT_SOURCE_DIR}/.." "${CMAKE_CURRENT_BINARY_DIR}") -set(test_deps opencv_${name} opencv_ts opencv_highgui ${DEPS}) +set(test_deps opencv_${name} opencv_ts opencv_highgui opencv_calib3d ${DEPS}) foreach(d ${test_deps}) if(${d} MATCHES "opencv_") if(${d} MATCHES "opencv_lapack") @@ -50,4 +50,4 @@ add_test(${the_target} "${LOC}") if(WIN32) install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) -endif() \ No newline at end of file +endif() diff --git a/modules/gpu/test/test_arithm.cpp b/modules/gpu/test/test_arithm.cpp new file mode 100644 index 0000000000..c7c32c12ee --- /dev/null +++ b/modules/gpu/test/test_arithm.cpp @@ -0,0 +1,1064 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 +#include +#include +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; +using namespace gpu; + +#define CHECK(pred, err) if (!(pred)) { \ + ts->printf(cvtest::TS::CONSOLE, "Fail: \"%s\" at line: %d\n", #pred, __LINE__); \ + ts->set_failed_test_info(err); \ + return; } + +class CV_GpuArithmTest : public cvtest::BaseTest +{ +public: + CV_GpuArithmTest(const char* test_name, const char* test_funcs){} + virtual ~CV_GpuArithmTest() {} + +protected: + void run(int); + + int test(int type); + + virtual int test(const Mat& mat1, const Mat& mat2) = 0; + + int CheckNorm(const Mat& m1, const Mat& m2, double eps = 1e-5); + int CheckNorm(const Scalar& s1, const Scalar& s2, double eps = 1e-5); + int CheckNorm(double d1, double d2, double eps = 1e-5); +}; + +int CV_GpuArithmTest::test(int type) +{ + cv::Size sz(200, 200); + cv::Mat mat1(sz, type), mat2(sz, type); + + cv::RNG& rng = ts->get_rng(); + + if (type != CV_32FC1) + { + rng.fill(mat1, cv::RNG::UNIFORM, cv::Scalar::all(1), cv::Scalar::all(20)); + rng.fill(mat2, cv::RNG::UNIFORM, cv::Scalar::all(1), cv::Scalar::all(20)); + } + else + { + rng.fill(mat1, cv::RNG::UNIFORM, cv::Scalar::all(0.1), cv::Scalar::all(1.0)); + rng.fill(mat2, cv::RNG::UNIFORM, cv::Scalar::all(0.1), cv::Scalar::all(1.0)); + } + + return test(mat1, mat2); +} + +int CV_GpuArithmTest::CheckNorm(const Mat& m1, const Mat& m2, double eps) +{ + double ret = norm(m1, m2, NORM_INF); + + if (ret < eps) + return cvtest::TS::OK; + + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return cvtest::TS::FAIL_GENERIC; +} + +int CV_GpuArithmTest::CheckNorm(const Scalar& s1, const Scalar& s2, double eps) +{ + int ret0 = CheckNorm(s1[0], s2[0], eps), + ret1 = CheckNorm(s1[1], s2[1], eps), + ret2 = CheckNorm(s1[2], s2[2], eps), + ret3 = CheckNorm(s1[3], s2[3], eps); + + return (ret0 == cvtest::TS::OK && ret1 == cvtest::TS::OK && ret2 == cvtest::TS::OK && ret3 == cvtest::TS::OK) ? cvtest::TS::OK : cvtest::TS::FAIL_GENERIC; +} + +int CV_GpuArithmTest::CheckNorm(double d1, double d2, double eps) +{ + double ret = ::fabs(d1 - d2); + + if (ret < eps) + return cvtest::TS::OK; + + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return cvtest::TS::FAIL_GENERIC; +} + +void CV_GpuArithmTest::run( int ) +{ + int testResult = cvtest::TS::OK; + + const int types[] = {CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1}; + const char* type_names[] = {"CV_8UC1 ", "CV_8UC3 ", "CV_8UC4 ", "CV_32FC1"}; + const int type_count = sizeof(types)/sizeof(types[0]); + + //run tests + for (int t = 0; t < type_count; ++t) + { + ts->printf(cvtest::TS::LOG, "Start testing %s", type_names[t]); + + if (cvtest::TS::OK == test(types[t])) + ts->printf(cvtest::TS::LOG, "SUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "FAIL\n"); + testResult = cvtest::TS::FAIL_MISMATCH; + } + } + + ts->set_failed_test_info(testResult); +} + +//////////////////////////////////////////////////////////////////////////////// +// Add + +struct CV_GpuNppImageAddTest : public CV_GpuArithmTest +{ + CV_GpuNppImageAddTest() : CV_GpuArithmTest( "GPU-NppImageAdd", "add" ) {} + + virtual int test(const Mat& mat1, const Mat& mat2) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::add(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::add(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Sub +struct CV_GpuNppImageSubtractTest : public CV_GpuArithmTest +{ + CV_GpuNppImageSubtractTest() : CV_GpuArithmTest( "GPU-NppImageSubtract", "subtract" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::subtract(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::subtract(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// multiply +struct CV_GpuNppImageMultiplyTest : public CV_GpuArithmTest +{ + CV_GpuNppImageMultiplyTest() : CV_GpuArithmTest( "GPU-NppImageMultiply", "multiply" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::multiply(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::multiply(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// divide +struct CV_GpuNppImageDivideTest : public CV_GpuArithmTest +{ + CV_GpuNppImageDivideTest() : CV_GpuArithmTest( "GPU-NppImageDivide", "divide" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::divide(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::divide(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes, 1.01f); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// transpose +struct CV_GpuNppImageTransposeTest : public CV_GpuArithmTest +{ + CV_GpuNppImageTransposeTest() : CV_GpuArithmTest( "GPU-NppImageTranspose", "transpose" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::transpose(mat1, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpuRes; + cv::gpu::transpose(gpu1, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// absdiff +struct CV_GpuNppImageAbsdiffTest : public CV_GpuArithmTest +{ + CV_GpuNppImageAbsdiffTest() : CV_GpuArithmTest( "GPU-NppImageAbsdiff", "absdiff" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4 && mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::absdiff(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::absdiff(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// compare +struct CV_GpuNppImageCompareTest : public CV_GpuArithmTest +{ + CV_GpuNppImageCompareTest() : CV_GpuArithmTest( "GPU-NppImageCompare", "compare" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + int cmp_codes[] = {CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE}; + const char* cmp_str[] = {"CMP_EQ", "CMP_GT", "CMP_GE", "CMP_LT", "CMP_LE", "CMP_NE"}; + int cmp_num = sizeof(cmp_codes) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < cmp_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nCompare operation: %s\n", cmp_str[i]); + + cv::Mat cpuRes; + cv::compare(mat1, mat2, cpuRes, cmp_codes[i]); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::compare(gpu1, gpu2, gpuRes, cmp_codes[i]); + + if (CheckNorm(cpuRes, gpuRes) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// meanStdDev +struct CV_GpuNppImageMeanStdDevTest : public CV_GpuArithmTest +{ + CV_GpuNppImageMeanStdDevTest() : CV_GpuArithmTest( "GPU-NppImageMeanStdDev", "meanStdDev" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_8UC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + Scalar cpumean; + Scalar cpustddev; + cv::meanStdDev(mat1, cpumean, cpustddev); + + GpuMat gpu1(mat1); + Scalar gpumean; + Scalar gpustddev; + cv::gpu::meanStdDev(gpu1, gpumean, gpustddev); + + int test_res = cvtest::TS::OK; + + if (CheckNorm(cpumean, gpumean) != cvtest::TS::OK) + { + ts->printf(cvtest::TS::LOG, "\nMean FAILED\n"); + test_res = cvtest::TS::FAIL_GENERIC; + } + + if (CheckNorm(cpustddev, gpustddev) != cvtest::TS::OK) + { + ts->printf(cvtest::TS::LOG, "\nStdDev FAILED\n"); + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// norm +struct CV_GpuNppImageNormTest : public CV_GpuArithmTest +{ + CV_GpuNppImageNormTest() : CV_GpuArithmTest( "GPU-NppImageNorm", "norm" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_8UC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + int norms[] = {NORM_INF, NORM_L1, NORM_L2}; + const char* norms_str[] = {"NORM_INF", "NORM_L1", "NORM_L2"}; + int norms_num = sizeof(norms) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < norms_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nNorm type: %s\n", norms_str[i]); + + double cpu_norm = cv::norm(mat1, mat2, norms[i]); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + double gpu_norm = cv::gpu::norm(gpu1, gpu2, norms[i]); + + if (CheckNorm(cpu_norm, gpu_norm) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// flip +struct CV_GpuNppImageFlipTest : public CV_GpuArithmTest +{ + CV_GpuNppImageFlipTest() : CV_GpuArithmTest( "GPU-NppImageFlip", "flip" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC4) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + int flip_codes[] = {0, 1, -1}; + const char* flip_axis[] = {"X", "Y", "Both"}; + int flip_codes_num = sizeof(flip_codes) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < flip_codes_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nFlip Axis: %s\n", flip_axis[i]); + + Mat cpu_res; + cv::flip(mat1, cpu_res, flip_codes[i]); + + GpuMat gpu1(mat1); + GpuMat gpu_res; + cv::gpu::flip(gpu1, gpu_res, flip_codes[i]); + + if (CheckNorm(cpu_res, gpu_res) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// LUT +struct CV_GpuNppImageLUTTest : public CV_GpuArithmTest +{ + CV_GpuNppImageLUTTest() : CV_GpuArithmTest( "GPU-NppImageLUT", "LUT" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_8UC1 && mat1.type() != CV_8UC3) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat lut(1, 256, CV_8UC1); + cv::RNG& rng = ts->get_rng(); + rng.fill(lut, cv::RNG::UNIFORM, cv::Scalar::all(100), cv::Scalar::all(200)); + + cv::Mat cpuRes; + cv::LUT(mat1, lut, cpuRes); + + cv::gpu::GpuMat gpuRes; + cv::gpu::LUT(GpuMat(mat1), lut, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// exp +struct CV_GpuNppImageExpTest : public CV_GpuArithmTest +{ + CV_GpuNppImageExpTest() : CV_GpuArithmTest( "GPU-NppImageExp", "exp" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::exp(mat1, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpuRes; + cv::gpu::exp(gpu1, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// log +struct CV_GpuNppImageLogTest : public CV_GpuArithmTest +{ + CV_GpuNppImageLogTest() : CV_GpuArithmTest( "GPU-NppImageLog", "log" ) {} + + int test( const Mat& mat1, const Mat& ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::log(mat1, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpuRes; + cv::gpu::log(gpu1, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// magnitude +struct CV_GpuNppImageMagnitudeTest : public CV_GpuArithmTest +{ + CV_GpuNppImageMagnitudeTest() : CV_GpuArithmTest( "GPU-NppImageMagnitude", "magnitude" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::magnitude(mat1, mat2, cpuRes); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::magnitude(gpu1, gpu2, gpuRes); + + return CheckNorm(cpuRes, gpuRes); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// phase +struct CV_GpuNppImagePhaseTest : public CV_GpuArithmTest +{ + CV_GpuNppImagePhaseTest() : CV_GpuArithmTest( "GPU-NppImagePhase", "phase" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuRes; + cv::phase(mat1, mat2, cpuRes, true); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuRes; + cv::gpu::phase(gpu1, gpu2, gpuRes, true); + + return CheckNorm(cpuRes, gpuRes, 0.3f); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// cartToPolar +struct CV_GpuNppImageCartToPolarTest : public CV_GpuArithmTest +{ + CV_GpuNppImageCartToPolarTest() : CV_GpuArithmTest( "GPU-NppImageCartToPolar", "cartToPolar" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuMag, cpuAngle; + cv::cartToPolar(mat1, mat2, cpuMag, cpuAngle); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuMag, gpuAngle; + cv::gpu::cartToPolar(gpu1, gpu2, gpuMag, gpuAngle); + + int magRes = CheckNorm(cpuMag, gpuMag); + int angleRes = CheckNorm(cpuAngle, gpuAngle, 0.005f); + + return magRes == cvtest::TS::OK && angleRes == cvtest::TS::OK ? cvtest::TS::OK : cvtest::TS::FAIL_GENERIC; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// polarToCart +struct CV_GpuNppImagePolarToCartTest : public CV_GpuArithmTest +{ + CV_GpuNppImagePolarToCartTest() : CV_GpuArithmTest( "GPU-NppImagePolarToCart", "polarToCart" ) {} + + int test( const Mat& mat1, const Mat& mat2 ) + { + if (mat1.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\tUnsupported type\t"); + return cvtest::TS::OK; + } + + cv::Mat cpuX, cpuY; + cv::polarToCart(mat1, mat2, cpuX, cpuY); + + GpuMat gpu1(mat1); + GpuMat gpu2(mat2); + GpuMat gpuX, gpuY; + cv::gpu::polarToCart(gpu1, gpu2, gpuX, gpuY); + + int xRes = CheckNorm(cpuX, gpuX); + int yRes = CheckNorm(cpuY, gpuY); + + return xRes == cvtest::TS::OK && yRes == cvtest::TS::OK ? cvtest::TS::OK : cvtest::TS::FAIL_GENERIC; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Min max + +struct CV_GpuMinMaxTest: public cvtest::BaseTest +{ + CV_GpuMinMaxTest() {} + + cv::gpu::GpuMat buf; + + void run(int) + { + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + int depth_end = double_ok ? CV_64F : CV_32F; + + for (int depth = CV_8U; depth <= depth_end; ++depth) + { + for (int i = 0; i < 3; ++i) + { + int rows = 1 + rand() % 1000; + int cols = 1 + rand() % 1000; + test(rows, cols, 1, depth); + test_masked(rows, cols, 1, depth); + } + } + } + + void test(int rows, int cols, int cn, int depth) + { + cv::Mat src(rows, cols, CV_MAKE_TYPE(depth, cn)); + cv::RNG& rng = ts->get_rng(); + rng.fill(src, RNG::UNIFORM, Scalar(0), Scalar(255)); + + double minVal, maxVal; + cv::Point minLoc, maxLoc; + + if (depth != CV_8S) + { + cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc); + } + else + { + minVal = std::numeric_limits::max(); + maxVal = -std::numeric_limits::max(); + for (int i = 0; i < src.rows; ++i) + for (int j = 0; j < src.cols; ++j) + { + signed char val = src.at(i, j); + if (val < minVal) minVal = val; + if (val > maxVal) maxVal = val; + } + } + + double minVal_, maxVal_; + cv::gpu::minMax(cv::gpu::GpuMat(src), &minVal_, &maxVal_, cv::gpu::GpuMat(), buf); + + if (abs(minVal - minVal_) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "\nfail: minVal=%f minVal_=%f rows=%d cols=%d depth=%d cn=%d\n", minVal, minVal_, rows, cols, depth, cn); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + if (abs(maxVal - maxVal_) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "\nfail: maxVal=%f maxVal_=%f rows=%d cols=%d depth=%d cn=%d\n", maxVal, maxVal_, rows, cols, depth, cn); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + } + + void test_masked(int rows, int cols, int cn, int depth) + { + cv::Mat src(rows, cols, CV_MAKE_TYPE(depth, cn)); + cv::RNG& rng = ts->get_rng(); + rng.fill(src, RNG::UNIFORM, Scalar(0), Scalar(255)); + + cv::Mat mask(src.size(), CV_8U); + rng.fill(mask, RNG::UNIFORM, Scalar(0), Scalar(2)); + + double minVal, maxVal; + cv::Point minLoc, maxLoc; + + Mat src_ = src.reshape(1); + if (depth != CV_8S) + { + cv::minMaxLoc(src_, &minVal, &maxVal, &minLoc, &maxLoc, mask); + } + else + { + // OpenCV's minMaxLoc doesn't support CV_8S type + minVal = std::numeric_limits::max(); + maxVal = -std::numeric_limits::max(); + for (int i = 0; i < src_.rows; ++i) + for (int j = 0; j < src_.cols; ++j) + { + char val = src_.at(i, j); + if (mask.at(i, j)) { if (val < minVal) minVal = val; } + if (mask.at(i, j)) { if (val > maxVal) maxVal = val; } + } + } + + double minVal_, maxVal_; + cv::Point minLoc_, maxLoc_; + cv::gpu::minMax(cv::gpu::GpuMat(src), &minVal_, &maxVal_, cv::gpu::GpuMat(mask), buf); + + if (abs(minVal - minVal_) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "\nfail: minVal=%f minVal_=%f rows=%d cols=%d depth=%d cn=%d\n", minVal, minVal_, rows, cols, depth, cn); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + if (abs(maxVal - maxVal_) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "\nfail: maxVal=%f maxVal_=%f rows=%d cols=%d depth=%d cn=%d\n", maxVal, maxVal_, rows, cols, depth, cn); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Min max loc + +struct CV_GpuMinMaxLocTest: public cvtest::BaseTest +{ + CV_GpuMinMaxLocTest() {} + + GpuMat valbuf, locbuf; + + void run(int) + { + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + int depth_end = double_ok ? CV_64F : CV_32F; + + for (int depth = CV_8U; depth <= depth_end; ++depth) + { + int rows = 1, cols = 3; + test(rows, cols, depth); + for (int i = 0; i < 4; ++i) + { + int rows = 1 + rand() % 1000; + int cols = 1 + rand() % 1000; + test(rows, cols, depth); + } + } + } + + void test(int rows, int cols, int depth) + { + cv::Mat src(rows, cols, depth); + cv::RNG& rng = ts->get_rng(); + rng.fill(src, RNG::UNIFORM, Scalar(0), Scalar(255)); + + cv::Mat mask(src.size(), CV_8U); + rng.fill(mask, RNG::UNIFORM, Scalar(0), Scalar(2)); + + // At least one of the mask elements must be non zero as OpenCV returns 0 + // in such case, when our implementation returns maximum or minimum value + mask.at(0, 0) = 1; + + double minVal, maxVal; + cv::Point minLoc, maxLoc; + + if (depth != CV_8S) + cv::minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, mask); + else + { + // OpenCV's minMaxLoc doesn't support CV_8S type + minVal = std::numeric_limits::max(); + maxVal = -std::numeric_limits::max(); + for (int i = 0; i < src.rows; ++i) + for (int j = 0; j < src.cols; ++j) + { + char val = src.at(i, j); + if (mask.at(i, j)) + { + if (val < minVal) { minVal = val; minLoc = cv::Point(j, i); } + if (val > maxVal) { maxVal = val; maxLoc = cv::Point(j, i); } + } + } + } + + double minVal_, maxVal_; + cv::Point minLoc_, maxLoc_; + cv::gpu::minMaxLoc(cv::gpu::GpuMat(src), &minVal_, &maxVal_, &minLoc_, &maxLoc_, cv::gpu::GpuMat(mask), valbuf, locbuf); + + CHECK(minVal == minVal_, cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(maxVal == maxVal_, cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(0 == memcmp(src.ptr(minLoc.y) + minLoc.x * src.elemSize(), src.ptr(minLoc_.y) + minLoc_.x * src.elemSize(), src.elemSize()), + cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(0 == memcmp(src.ptr(maxLoc.y) + maxLoc.x * src.elemSize(), src.ptr(maxLoc_.y) + maxLoc_.x * src.elemSize(), src.elemSize()), + cvtest::TS::FAIL_INVALID_OUTPUT); + } +}; + +//////////////////////////////////////////////////////////////////////////// +// Count non zero +struct CV_GpuCountNonZeroTest: cvtest::BaseTest +{ + CV_GpuCountNonZeroTest(){} + + void run(int) + { + int depth_end; + if (cv::gpu::DeviceInfo().supports(cv::gpu::NATIVE_DOUBLE)) + depth_end = CV_64F; + else + depth_end = CV_32F; + for (int depth = CV_8U; depth <= CV_32F; ++depth) + { + for (int i = 0; i < 4; ++i) + { + int rows = 1 + rand() % 1000; + int cols = 1 + rand() % 1000; + test(rows, cols, depth); + } + } + } + + void test(int rows, int cols, int depth) + { + cv::Mat src(rows, cols, depth); + cv::RNG rng; + if (depth == 5) + rng.fill(src, RNG::UNIFORM, Scalar(-1000.f), Scalar(1000.f)); + else if (depth == 6) + rng.fill(src, RNG::UNIFORM, Scalar(-1000.), Scalar(1000.)); + else + for (int i = 0; i < src.rows; ++i) + { + Mat row(1, src.cols * src.elemSize(), CV_8U, src.ptr(i)); + rng.fill(row, RNG::UNIFORM, Scalar(0), Scalar(256)); + } + + int n_gold = cv::countNonZero(src); + int n = cv::gpu::countNonZero(cv::gpu::GpuMat(src)); + + if (n != n_gold) + { + ts->printf(cvtest::TS::LOG, "%d %d %d %d %d\n", n, n_gold, depth, cols, rows); + n_gold = cv::countNonZero(src); + } + + CHECK(n == n_gold, cvtest::TS::FAIL_INVALID_OUTPUT); + } +}; + + +////////////////////////////////////////////////////////////////////////////// +// sum + +struct CV_GpuSumTest: cvtest::BaseTest +{ + CV_GpuSumTest() {} + + void run(int) + { + Mat src; + Scalar a, b; + double max_err = 1e-5; + + int typemax = CV_32F; + for (int type = CV_8U; type <= typemax; ++type) + { + // + // sum + // + + gen(1 + rand() % 500, 1 + rand() % 500, CV_MAKETYPE(type, 1), src); + a = sum(src); + b = sum(GpuMat(src)); + if (abs(a[0] - b[0]) > src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "1 cols: %d, rows: %d, expected: %f, actual: %f\n", src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + gen(1 + rand() % 500, 1 + rand() % 500, CV_MAKETYPE(type, 2), src); + a = sum(src); + b = sum(GpuMat(src)); + if (abs(a[0] - b[0]) + abs(a[1] - b[1]) > src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "2 cols: %d, rows: %d, expected: %f, actual: %f\n", src.cols, src.rows, a[1], b[1]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + gen(1 + rand() % 500, 1 + rand() % 500, CV_MAKETYPE(type, 3), src); + a = sum(src); + b = sum(GpuMat(src)); + if (abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2])> src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "3 cols: %d, rows: %d, expected: %f, actual: %f\n", src.cols, src.rows, a[2], b[2]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + gen(1 + rand() % 500, 1 + rand() % 500, CV_MAKETYPE(type, 4), src); + a = sum(src); + b = sum(GpuMat(src)); + if (abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2]) + abs(a[3] - b[3])> src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "4 cols: %d, rows: %d, expected: %f, actual: %f\n", src.cols, src.rows, a[3], b[3]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + gen(1 + rand() % 500, 1 + rand() % 500, type, src); + a = sum(src); + b = sum(GpuMat(src)); + if (abs(a[0] - b[0]) > src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "cols: %d, rows: %d, expected: %f, actual: %f\n", src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + // + // absSum + // + + gen(1 + rand() % 200, 1 + rand() % 200, CV_MAKETYPE(type, 1), src); + b = absSum(GpuMat(src)); + a = norm(src, NORM_L1); + if (abs(a[0] - b[0]) > src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "type: %d, cols: %d, rows: %d, expected: %f, actual: %f\n", type, src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + // + // sqrSum + // + + if (type != CV_8S) + { + gen(1 + rand() % 200, 1 + rand() % 200, CV_MAKETYPE(type, 1), src); + b = sqrSum(GpuMat(src)); + Mat sqrsrc; + multiply(src, src, sqrsrc); + a = sum(sqrsrc); + if (abs(a[0] - b[0]) > src.size().area() * max_err) + { + ts->printf(cvtest::TS::CONSOLE, "type: %d, cols: %d, rows: %d, expected: %f, actual: %f\n", type, src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + gen(1 + rand() % 200, 1 + rand() % 200, CV_MAKETYPE(type, 2), src); + b = sqrSum(GpuMat(src)); + multiply(src, src, sqrsrc); + a = sum(sqrsrc); + if (abs(a[0] - b[0]) + abs(a[1] - b[1])> src.size().area() * max_err * 2) + { + ts->printf(cvtest::TS::CONSOLE, "type: %d, cols: %d, rows: %d, expected: %f, actual: %f\n", type, src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + gen(1 + rand() % 200, 1 + rand() % 200, CV_MAKETYPE(type, 3), src); + b = sqrSum(GpuMat(src)); + multiply(src, src, sqrsrc); + a = sum(sqrsrc); + if (abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2])> src.size().area() * max_err * 3) + { + ts->printf(cvtest::TS::CONSOLE, "type: %d, cols: %d, rows: %d, expected: %f, actual: %f\n", type, src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + gen(1 + rand() % 200, 1 + rand() % 200, CV_MAKETYPE(type, 4), src); + b = sqrSum(GpuMat(src)); + multiply(src, src, sqrsrc); + a = sum(sqrsrc); + if (abs(a[0] - b[0]) + abs(a[1] - b[1]) + abs(a[2] - b[2]) + abs(a[3] - b[3])> src.size().area() * max_err * 4) + { + ts->printf(cvtest::TS::CONSOLE, "type: %d, cols: %d, rows: %d, expected: %f, actual: %f\n", type, src.cols, src.rows, a[0], b[0]); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + } + } + + void gen(int cols, int rows, int type, Mat& m) + { + m.create(rows, cols, type); + RNG rng; + rng.fill(m, RNG::UNIFORM, Scalar::all(0), Scalar::all(16)); + + } +}; + +TEST(add, accuracy) { CV_GpuNppImageAddTest test; test.safe_run(); } +TEST(subtract, accuracy) { CV_GpuNppImageSubtractTest test; test.safe_run(); } +TEST(multiply, accuracy) { CV_GpuNppImageMultiplyTest test; test.safe_run(); } +TEST(divide, accuracy) { CV_GpuNppImageDivideTest test; test.safe_run(); } +TEST(transpose, accuracy) { CV_GpuNppImageTransposeTest test; test.safe_run(); } +TEST(absdiff, accuracy) { CV_GpuNppImageAbsdiffTest test; test.safe_run(); } +TEST(compare, accuracy) { CV_GpuNppImageCompareTest test; test.safe_run(); } +TEST(meanStdDev, accuracy) { CV_GpuNppImageMeanStdDevTest test; test.safe_run(); } +TEST(normDiff, accuracy) { CV_GpuNppImageNormTest test; test.safe_run(); } +TEST(flip, accuracy) { CV_GpuNppImageFlipTest test; test.safe_run(); } +TEST(LUT, accuracy) { CV_GpuNppImageLUTTest test; test.safe_run(); } +TEST(exp, accuracy) { CV_GpuNppImageExpTest test; test.safe_run(); } +TEST(log, accuracy) { CV_GpuNppImageLogTest test; test.safe_run(); } +TEST(magnitude, accuracy) { CV_GpuNppImageMagnitudeTest test; test.safe_run(); } +TEST(phase, accuracy) { CV_GpuNppImagePhaseTest test; test.safe_run(); } +TEST(cartToPolar, accuracy) { CV_GpuNppImageCartToPolarTest test; test.safe_run(); } +TEST(polarToCart, accuracy) { CV_GpuNppImagePolarToCartTest test; test.safe_run(); } +TEST(minMax, accuracy) { CV_GpuMinMaxTest test; test.safe_run(); } +TEST(minMaxLoc, accuracy) { CV_GpuMinMaxLocTest test; test.safe_run(); } +TEST(countNonZero, accuracy) { CV_GpuCountNonZeroTest test; test.safe_run(); } +TEST(sum, accuracy) { CV_GpuSumTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_bitwise_oper.cpp b/modules/gpu/test/test_bitwise_oper.cpp new file mode 100644 index 0000000000..5d5261b801 --- /dev/null +++ b/modules/gpu/test/test_bitwise_oper.cpp @@ -0,0 +1,235 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 +#include +#include "test_precomp.hpp" + +#define CHECK(pred, err) if (!(pred)) { \ + ts->printf(cvtest::TS::CONSOLE, "Fail: \"%s\" at line: %d\n", #pred, __LINE__); \ + ts->set_failed_test_info(err); \ + return; } + +using namespace cv; +using namespace std; + +struct CV_GpuBitwiseTest: public cvtest::BaseTest +{ + CV_GpuBitwiseTest() {} + + void run(int) + { + int rows, cols; + + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + int depth_end = double_ok ? CV_64F : CV_32F; + + for (int depth = CV_8U; depth <= depth_end; ++depth) + for (int cn = 1; cn <= 4; ++cn) + for (int attempt = 0; attempt < 3; ++attempt) + { + rows = 1 + rand() % 100; + cols = 1 + rand() % 100; + test_bitwise_not(rows, cols, CV_MAKETYPE(depth, cn)); + test_bitwise_or(rows, cols, CV_MAKETYPE(depth, cn)); + test_bitwise_and(rows, cols, CV_MAKETYPE(depth, cn)); + test_bitwise_xor(rows, cols, CV_MAKETYPE(depth, cn)); + } + } + + void test_bitwise_not(int rows, int cols, int type) + { + Mat src(rows, cols, type); + + RNG rng; + for (int i = 0; i < src.rows; ++i) + { + Mat row(1, src.cols * src.elemSize(), CV_8U, src.ptr(i)); + rng.fill(row, RNG::UNIFORM, Scalar(0), Scalar(255)); + } + + Mat dst_gold = ~src; + + gpu::GpuMat mask(src.size(), CV_8U); + mask.setTo(Scalar(1)); + + gpu::GpuMat dst; + gpu::bitwise_not(gpu::GpuMat(src), dst); + + CHECK(dst_gold.size() == dst.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold.type() == dst.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + + Mat dsth(dst); + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold.ptr(i), dsth.ptr(i), dst_gold.cols * dst_gold.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT); + + dst.setTo(Scalar::all(0)); + gpu::bitwise_not(gpu::GpuMat(src), dst, mask); + + CHECK(dst_gold.size() == dst.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold.type() == dst.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + + dsth = dst; + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold.ptr(i), dsth.ptr(i), dst_gold.cols * dst_gold.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + } + + void test_bitwise_or(int rows, int cols, int type) + { + Mat src1(rows, cols, type); + Mat src2(rows, cols, type); + + RNG rng; + for (int i = 0; i < src1.rows; ++i) + { + Mat row1(1, src1.cols * src1.elemSize(), CV_8U, src1.ptr(i)); + rng.fill(row1, RNG::UNIFORM, Scalar(0), Scalar(255)); + Mat row2(1, src2.cols * src2.elemSize(), CV_8U, src2.ptr(i)); + rng.fill(row2, RNG::UNIFORM, Scalar(0), Scalar(255)); + } + + Mat dst_gold = src1 | src2; + gpu::GpuMat dst = gpu::GpuMat(src1) | gpu::GpuMat(src2); + + CHECK(dst_gold.size() == dst.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold.type() == dst.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + Mat dsth(dst); + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold.ptr(i), dsth.ptr(i), dst_gold.cols * dst_gold.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + + Mat mask(src1.size(), CV_8U); + randu(mask, Scalar(0), Scalar(255)); + + Mat dst_gold2(dst_gold.size(), dst_gold.type()); dst_gold2.setTo(Scalar::all(0)); + gpu::GpuMat dst2(dst.size(), dst.type()); dst2.setTo(Scalar::all(0)); + bitwise_or(src1, src2, dst_gold2, mask); + gpu::bitwise_or(gpu::GpuMat(src1), gpu::GpuMat(src2), dst2, gpu::GpuMat(mask)); + + CHECK(dst_gold2.size() == dst2.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold2.type() == dst2.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + dsth = dst2; + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold2.ptr(i), dsth.ptr(i), dst_gold2.cols * dst_gold2.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + } + + void test_bitwise_and(int rows, int cols, int type) + { + Mat src1(rows, cols, type); + Mat src2(rows, cols, type); + + RNG rng; + for (int i = 0; i < src1.rows; ++i) + { + Mat row1(1, src1.cols * src1.elemSize(), CV_8U, src1.ptr(i)); + rng.fill(row1, RNG::UNIFORM, Scalar(0), Scalar(255)); + Mat row2(1, src2.cols * src2.elemSize(), CV_8U, src2.ptr(i)); + rng.fill(row2, RNG::UNIFORM, Scalar(0), Scalar(255)); + } + + Mat dst_gold = src1 & src2; + + gpu::GpuMat dst = gpu::GpuMat(src1) & gpu::GpuMat(src2); + + CHECK(dst_gold.size() == dst.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold.type() == dst.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + Mat dsth(dst); + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold.ptr(i), dsth.ptr(i), dst_gold.cols * dst_gold.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + + + Mat mask(src1.size(), CV_8U); + randu(mask, Scalar(0), Scalar(255)); + + Mat dst_gold2(dst_gold.size(), dst_gold.type()); dst_gold2.setTo(Scalar::all(0)); + gpu::GpuMat dst2(dst.size(), dst.type()); dst2.setTo(Scalar::all(0)); + bitwise_and(src1, src2, dst_gold2, mask); + gpu::bitwise_and(gpu::GpuMat(src1), gpu::GpuMat(src2), dst2, gpu::GpuMat(mask)); + + CHECK(dst_gold2.size() == dst2.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold2.type() == dst2.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + dsth = dst2; + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold2.ptr(i), dsth.ptr(i), dst_gold2.cols * dst_gold2.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + } + + void test_bitwise_xor(int rows, int cols, int type) + { + Mat src1(rows, cols, type); + Mat src2(rows, cols, type); + + RNG rng; + for (int i = 0; i < src1.rows; ++i) + { + Mat row1(1, src1.cols * src1.elemSize(), CV_8U, src1.ptr(i)); + rng.fill(row1, RNG::UNIFORM, Scalar(0), Scalar(255)); + Mat row2(1, src2.cols * src2.elemSize(), CV_8U, src2.ptr(i)); + rng.fill(row2, RNG::UNIFORM, Scalar(0), Scalar(255)); + } + + Mat dst_gold = src1 ^ src2; + + gpu::GpuMat dst = gpu::GpuMat(src1) ^ gpu::GpuMat(src2); + + CHECK(dst_gold.size() == dst.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold.type() == dst.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + Mat dsth(dst); + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold.ptr(i), dsth.ptr(i), dst_gold.cols * dst_gold.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + + + Mat mask(src1.size(), CV_8U); + randu(mask, Scalar(0), Scalar(255)); + + Mat dst_gold2(dst_gold.size(), dst_gold.type()); dst_gold2.setTo(Scalar::all(0)); + gpu::GpuMat dst2(dst.size(), dst.type()); dst2.setTo(Scalar::all(0)); + bitwise_xor(src1, src2, dst_gold2, mask); + gpu::bitwise_xor(gpu::GpuMat(src1), gpu::GpuMat(src2), dst2, gpu::GpuMat(mask)); + + CHECK(dst_gold2.size() == dst2.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(dst_gold2.type() == dst2.type(), cvtest::TS::FAIL_INVALID_OUTPUT); + dsth = dst2; + for (int i = 0; i < dst_gold.rows; ++i) + CHECK(memcmp(dst_gold2.ptr(i), dsth.ptr(i), dst_gold2.cols * dst_gold2.elemSize()) == 0, cvtest::TS::FAIL_INVALID_OUTPUT) + } +}; + +TEST(BitwiseOperations, accuracy) { CV_GpuBitwiseTest test; test; } diff --git a/modules/gpu/test/test_brute_force_matcher.cpp b/modules/gpu/test/test_brute_force_matcher.cpp new file mode 100644 index 0000000000..59af9f04f9 --- /dev/null +++ b/modules/gpu/test/test_brute_force_matcher.cpp @@ -0,0 +1,522 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" +#include +#include + +using namespace cv; +using namespace cv::gpu; +using namespace std; + +class CV_GpuBruteForceMatcherTest : public cvtest::BaseTest +{ +public: + CV_GpuBruteForceMatcherTest() + { + } + +protected: + virtual void run(int); + + void emptyDataTest(); + void dataTest(int dim); + + void generateData(GpuMat& query, GpuMat& train, int dim); + + void matchTest(const GpuMat& query, const GpuMat& train); + void knnMatchTest(const GpuMat& query, const GpuMat& train); + void radiusMatchTest(const GpuMat& query, const GpuMat& train); + +private: + BruteForceMatcher_GPU< L2 > dmatcher; + + static const int queryDescCount = 300; // must be even number because we split train data in some cases in two + static const int countFactor = 4; // do not change it +}; + +void CV_GpuBruteForceMatcherTest::emptyDataTest() +{ + GpuMat queryDescriptors, trainDescriptors, mask; + vector trainDescriptorCollection, masks; + vector matches; + vector< vector > vmatches; + + try + { + dmatcher.match(queryDescriptors, trainDescriptors, matches, mask); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "match() on empty descriptors must not generate exception (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.knnMatch(queryDescriptors, trainDescriptors, vmatches, 2, mask); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "knnMatch() on empty descriptors must not generate exception (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.radiusMatch(queryDescriptors, trainDescriptors, vmatches, 10.f, mask); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "radiusMatch() on empty descriptors must not generate exception (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.add(trainDescriptorCollection); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "add() on empty descriptors must not generate exception.\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.match(queryDescriptors, matches, masks); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "match() on empty descriptors must not generate exception (2).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.knnMatch(queryDescriptors, vmatches, 2, masks); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "knnMatch() on empty descriptors must not generate exception (2).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + try + { + dmatcher.radiusMatch( queryDescriptors, vmatches, 10.f, masks ); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "radiusMatch() on empty descriptors must not generate exception (2).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + +} + +void CV_GpuBruteForceMatcherTest::generateData( GpuMat& queryGPU, GpuMat& trainGPU, int dim ) +{ + Mat query, train; + RNG& rng = ts->get_rng(); + + // Generate query descriptors randomly. + // Descriptor vector elements are integer values. + Mat buf( queryDescCount, dim, CV_32SC1 ); + rng.fill( buf, RNG::UNIFORM, Scalar::all(0), Scalar(3) ); + buf.convertTo( query, CV_32FC1 ); + + // Generate train decriptors as follows: + // copy each query descriptor to train set countFactor times + // and perturb some one element of the copied descriptors in + // in ascending order. General boundaries of the perturbation + // are (0.f, 1.f). + train.create( query.rows*countFactor, query.cols, CV_32FC1 ); + float step = 1.f / countFactor; + for( int qIdx = 0; qIdx < query.rows; qIdx++ ) + { + Mat queryDescriptor = query.row(qIdx); + for( int c = 0; c < countFactor; c++ ) + { + int tIdx = qIdx * countFactor + c; + Mat trainDescriptor = train.row(tIdx); + queryDescriptor.copyTo( trainDescriptor ); + int elem = rng(dim); + float diff = rng.uniform( step*c, step*(c+1) ); + trainDescriptor.at(0, elem) += diff; + } + } + + queryGPU.upload(query); + trainGPU.upload(train); +} + +void CV_GpuBruteForceMatcherTest::matchTest( const GpuMat& query, const GpuMat& train ) +{ + dmatcher.clear(); + + // test const version of match() + { + vector matches; + dmatcher.match( query, train, matches ); + + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test match() function (1).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + else + { + int badCount = 0; + for( size_t i = 0; i < matches.size(); i++ ) + { + DMatch match = matches[i]; + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor) || (match.imgIdx != 0) ) + badCount++; + } + if (badCount > 0) + { + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test match() function (1).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + } + } + + // test version of match() with add() + { + vector matches; + // make add() twice to test such case + dmatcher.add( vector(1,train.rowRange(0, train.rows/2)) ); + dmatcher.add( vector(1,train.rowRange(train.rows/2, train.rows)) ); + // prepare masks (make first nearest match illegal) + vector masks(2); + for(int mi = 0; mi < 2; mi++ ) + { + masks[mi] = GpuMat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1)); + for( int di = 0; di < queryDescCount/2; di++ ) + masks[mi].col(di*countFactor).setTo(Scalar::all(0)); + } + + dmatcher.match( query, matches, masks ); + + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test match() function (2).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + else + { + int badCount = 0; + for( size_t i = 0; i < matches.size(); i++ ) + { + DMatch match = matches[i]; + int shift = dmatcher.isMaskSupported() ? 1 : 0; + { + if( i < queryDescCount/2 ) + { + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + shift) || (match.imgIdx != 0) ) + badCount++; + } + else + { + if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + shift) || (match.imgIdx != 1) ) + badCount++; + } + } + } + if (badCount > 0) + { + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test match() function (2).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } + } + } +} + +void CV_GpuBruteForceMatcherTest::knnMatchTest( const GpuMat& query, const GpuMat& train ) +{ + dmatcher.clear(); + + // test const version of knnMatch() + { + const int knn = 3; + + vector< vector > matches; + dmatcher.knnMatch( query, train, matches, knn ); + + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test knnMatch() function (1).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + else + { + int badCount = 0; + for( size_t i = 0; i < matches.size(); i++ ) + { + if( (int)matches[i].size() != knn ) + badCount++; + else + { + int localBadCount = 0; + for( int k = 0; k < knn; k++ ) + { + DMatch match = matches[i][k]; + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor+k) || (match.imgIdx != 0) ) + localBadCount++; + } + badCount += localBadCount > 0 ? 1 : 0; + } + } + if (badCount > 0) + { + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test knnMatch() function (1).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + } + } + + // test version of knnMatch() with add() + { + const int knn = 2; + vector > matches; + // make add() twice to test such case + dmatcher.add( vector(1,train.rowRange(0, train.rows/2)) ); + dmatcher.add( vector(1,train.rowRange(train.rows/2, train.rows)) ); + // prepare masks (make first nearest match illegal) + vector masks(2); + for(int mi = 0; mi < 2; mi++ ) + { + masks[mi] = GpuMat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1)); + for( int di = 0; di < queryDescCount/2; di++ ) + masks[mi].col(di*countFactor).setTo(Scalar::all(0)); + } + + dmatcher.knnMatch( query, matches, knn, masks ); + + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test knnMatch() function (2).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + else + { + int badCount = 0; + int shift = dmatcher.isMaskSupported() ? 1 : 0; + for( size_t i = 0; i < matches.size(); i++ ) + { + if( (int)matches[i].size() != knn ) + badCount++; + else + { + int localBadCount = 0; + for( int k = 0; k < knn; k++ ) + { + DMatch match = matches[i][k]; + { + if( i < queryDescCount/2 ) + { + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + k + shift) || + (match.imgIdx != 0) ) + localBadCount++; + } + else + { + if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + k + shift) || + (match.imgIdx != 1) ) + localBadCount++; + } + } + } + badCount += localBadCount > 0 ? 1 : 0; + } + } + if (badCount > 0) + { + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test knnMatch() function (2).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } + } + } +} + +void CV_GpuBruteForceMatcherTest::radiusMatchTest( const GpuMat& query, const GpuMat& train ) +{ + bool atomics_ok = TargetArchs::builtWith(GLOBAL_ATOMICS) && DeviceInfo().supports(GLOBAL_ATOMICS); + if (!atomics_ok) + { + ts->printf(cvtest::TS::CONSOLE, "\nCode and device atomics support is required for radiusMatch (CC >= 1.1)"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + dmatcher.clear(); + // test const version of match() + { + const float radius = 1.f/countFactor; + vector< vector > matches; + dmatcher.radiusMatch( query, train, matches, radius ); + + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test radiusMatch() function (1).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + else + { + int badCount = 0; + for( size_t i = 0; i < matches.size(); i++ ) + { + if( (int)matches[i].size() != 1 ) + badCount++; + else + { + DMatch match = matches[i][0]; + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor) || (match.imgIdx != 0) ) + badCount++; + } + } + if (badCount > 0) + { + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test radiusMatch() function (1).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + } + } + + // test version of match() with add() + { + int n = 3; + const float radius = 1.f/countFactor * n; + vector< vector > matches; + // make add() twice to test such case + dmatcher.add( vector(1,train.rowRange(0, train.rows/2)) ); + dmatcher.add( vector(1,train.rowRange(train.rows/2, train.rows)) ); + // prepare masks (make first nearest match illegal) + vector masks(2); + for(int mi = 0; mi < 2; mi++ ) + { + masks[mi] = GpuMat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1)); + for( int di = 0; di < queryDescCount/2; di++ ) + masks[mi].col(di*countFactor).setTo(Scalar::all(0)); + } + + dmatcher.radiusMatch( query, matches, radius, masks ); + + int curRes = cvtest::TS::OK; + if( (int)matches.size() != queryDescCount ) + { + ts->printf(cvtest::TS::LOG, "Incorrect matches count while test radiusMatch() function (1).\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + int badCount = 0; + int shift = dmatcher.isMaskSupported() ? 1 : 0; + int needMatchCount = dmatcher.isMaskSupported() ? n-1 : n; + for( size_t i = 0; i < matches.size(); i++ ) + { + if( (int)matches[i].size() != needMatchCount ) + badCount++; + else + { + int localBadCount = 0; + for( int k = 0; k < needMatchCount; k++ ) + { + DMatch match = matches[i][k]; + { + if( i < queryDescCount/2 ) + { + if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + k + shift) || + (match.imgIdx != 0) ) + localBadCount++; + } + else + { + if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + k + shift) || + (match.imgIdx != 1) ) + localBadCount++; + } + } + } + badCount += localBadCount > 0 ? 1 : 0; + } + } + + if (badCount > 0) + { + curRes = cvtest::TS::FAIL_INVALID_OUTPUT; + ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test radiusMatch() function (2).\n", + (float)badCount/(float)queryDescCount ); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + } + } +} + +void CV_GpuBruteForceMatcherTest::dataTest(int dim) +{ + GpuMat query, train; + generateData(query, train, dim); + + matchTest(query, train); + knnMatchTest(query, train); + radiusMatchTest(query, train); + + dmatcher.clear(); +} + +void CV_GpuBruteForceMatcherTest::run(int) +{ + emptyDataTest(); + + dataTest(50); + dataTest(64); + dataTest(100); + dataTest(128); + dataTest(200); + dataTest(256); + dataTest(300); +} + +TEST(BruteForceMatcher, accuracy) { CV_GpuBruteForceMatcherTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_dft_routines.cpp b/modules/gpu/test/test_dft_routines.cpp new file mode 100644 index 0000000000..f346bef428 --- /dev/null +++ b/modules/gpu/test/test_dft_routines.cpp @@ -0,0 +1,399 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +using namespace cv; +using namespace cv::gpu; +using namespace std; + +struct CV_GpuMulSpectrumsTest: cvtest::BaseTest +{ + CV_GpuMulSpectrumsTest() {} + + void run(int) + { + test(0); + testConj(0); + testScaled(0); + testScaledConj(0); + test(DFT_ROWS); + testConj(DFT_ROWS); + testScaled(DFT_ROWS); + testScaledConj(DFT_ROWS); + } + + void gen(int cols, int rows, Mat& mat) + { + RNG rng; + mat.create(rows, cols, CV_32FC2); + rng.fill(mat, RNG::UNIFORM, Scalar::all(0.f), Scalar::all(10.f)); + } + + bool cmp(const Mat& gold, const Mat& mine, float max_err=1e-3f) + { + if (gold.size() != mine.size()) + { + ts->printf(cvtest::TS::CONSOLE, "bad sizes: gold: %d d%, mine: %d %d\n", gold.cols, gold.rows, mine.cols, mine.rows); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + if (gold.type() != mine.type()) + { + ts->printf(cvtest::TS::CONSOLE, "bad types: gold=%d, mine=%d\n", gold.type(), mine.type()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + for (int i = 0; i < gold.rows; ++i) + { + for (int j = 0; j < gold.cols * 2; ++j) + { + float gold_ = gold.at(i, j); + float mine_ = mine.at(i, j); + if (fabs(gold_ - mine_) > max_err) + { + ts->printf(cvtest::TS::CONSOLE, "bad values at %d %d: gold=%f, mine=%f\n", j, i, gold_, mine_); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + } + } + return true; + } + + bool cmpScaled(const Mat& gold, const Mat& mine, float scale, float max_err=1e-3f) + { + if (gold.size() != mine.size()) + { + ts->printf(cvtest::TS::CONSOLE, "bad sizes: gold: %d d%, mine: %d %d\n", gold.cols, gold.rows, mine.cols, mine.rows); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + if (gold.type() != mine.type()) + { + ts->printf(cvtest::TS::CONSOLE, "bad types: gold=%d, mine=%d\n", gold.type(), mine.type()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + for (int i = 0; i < gold.rows; ++i) + { + for (int j = 0; j < gold.cols * 2; ++j) + { + float gold_ = gold.at(i, j) * scale; + float mine_ = mine.at(i, j); + if (fabs(gold_ - mine_) > max_err) + { + ts->printf(cvtest::TS::CONSOLE, "bad values at %d %d: gold=%f, mine=%f\n", j, i, gold_, mine_); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + } + } + return true; + } + + void test(int flags) + { + int cols = 1 + rand() % 100, rows = 1 + rand() % 1000; + + Mat a, b; + gen(cols, rows, a); + gen(cols, rows, b); + + Mat c_gold; + mulSpectrums(a, b, c_gold, flags, false); + + GpuMat d_c; + mulSpectrums(GpuMat(a), GpuMat(b), d_c, flags, false); + + if (!cmp(c_gold, Mat(d_c))) + ts->printf(cvtest::TS::CONSOLE, "test failed: cols=%d, rows=%d, flags=%d\n", cols, rows, flags); + } + + void testConj(int flags) + { + int cols = 1 + rand() % 100, rows = 1 + rand() % 1000; + + Mat a, b; + gen(cols, rows, a); + gen(cols, rows, b); + + Mat c_gold; + mulSpectrums(a, b, c_gold, flags, true); + + GpuMat d_c; + mulSpectrums(GpuMat(a), GpuMat(b), d_c, flags, true); + + if (!cmp(c_gold, Mat(d_c))) + ts->printf(cvtest::TS::CONSOLE, "testConj failed: cols=%d, rows=%d, flags=%d\n", cols, rows, flags); + } + + void testScaled(int flags) + { + int cols = 1 + rand() % 100, rows = 1 + rand() % 1000; + + Mat a, b; + gen(cols, rows, a); + gen(cols, rows, b); + float scale = 1.f / a.size().area(); + + Mat c_gold; + mulSpectrums(a, b, c_gold, flags, false); + + GpuMat d_c; + mulAndScaleSpectrums(GpuMat(a), GpuMat(b), d_c, flags, scale, false); + + if (!cmpScaled(c_gold, Mat(d_c), scale)) + ts->printf(cvtest::TS::CONSOLE, "testScaled failed: cols=%d, rows=%d, flags=%d\n", cols, rows, flags); + } + + void testScaledConj(int flags) + { + int cols = 1 + rand() % 100, rows = 1 + rand() % 1000; + + Mat a, b; + gen(cols, rows, a); + gen(cols, rows, b); + float scale = 1.f / a.size().area(); + + Mat c_gold; + mulSpectrums(a, b, c_gold, flags, true); + + GpuMat d_c; + mulAndScaleSpectrums(GpuMat(a), GpuMat(b), d_c, flags, scale, true); + + if (!cmpScaled(c_gold, Mat(d_c), scale)) + ts->printf(cvtest::TS::CONSOLE, "testScaledConj failed: cols=%d, rows=%d, flags=%D\n", cols, rows, flags); + } +} CV_GpuMulSpectrumsTest_inst; + + +struct CV_GpuDftTest: cvtest::BaseTest +{ + CV_GpuDftTest() {} + + void run(int) + { + srand(0); + int cols = 2 + rand() % 100, rows = 2 + rand() % 100; + + for (int i = 0; i < 2; ++i) + { + bool inplace = i != 0; + testC2C("no flags", cols, rows, 0, inplace); + testC2C("no flags 0 1", cols, rows + 1, 0, inplace); + testC2C("no flags 1 0", cols, rows + 1, 0, inplace); + testC2C("no flags 1 1", cols + 1, rows, 0, inplace); + testC2C("DFT_INVERSE", cols, rows, DFT_INVERSE, inplace); + testC2C("DFT_ROWS", cols, rows, DFT_ROWS, inplace); + testC2C("single col", 1, rows, 0, inplace); + testC2C("single row", cols, 1, 0, inplace); + testC2C("single col inversed", 1, rows, DFT_INVERSE, inplace); + testC2C("single row inversed", cols, 1, DFT_INVERSE, inplace); + testC2C("single row DFT_ROWS", cols, 1, DFT_ROWS, inplace); + testC2C("size 1 2", 1, 2, 0, inplace); + testC2C("size 2 1", 2, 1, 0, inplace); + } + + testR2CThenC2R("sanity", cols, rows); + testR2CThenC2R("sanity 0 1", cols, rows + 1); + testR2CThenC2R("sanity 1 0", cols + 1, rows); + testR2CThenC2R("sanity 1 1", cols + 1, rows + 1); + testR2CThenC2R("single col", 1, rows); + testR2CThenC2R("single col 1", 1, rows + 1); + testR2CThenC2R("single row", cols, 1); + testR2CThenC2R("single row 1", cols + 1, 1); + + testR2CThenC2R("sanity", cols, rows, true); + testR2CThenC2R("sanity 0 1", cols, rows + 1, true); + testR2CThenC2R("sanity 1 0", cols + 1, rows, true); + testR2CThenC2R("sanity 1 1", cols + 1, rows + 1, true); + testR2CThenC2R("single row", cols, 1, true); + testR2CThenC2R("single row 1", cols + 1, 1, true); +} + + void gen(int cols, int rows, int cn, Mat& mat) + { + RNG rng(1); + mat.create(rows, cols, CV_MAKETYPE(CV_32F, cn)); + rng.fill(mat, RNG::UNIFORM, Scalar::all(0.f), Scalar::all(10.f)); + } + + bool cmp(const Mat& gold, const Mat& mine, float max_err=1e-3f) + { + if (gold.size() != mine.size()) + { + ts->printf(cvtest::TS::CONSOLE, "bad sizes: gold: %d %d, mine: %d %d\n", gold.cols, gold.rows, mine.cols, mine.rows); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + if (gold.depth() != mine.depth()) + { + ts->printf(cvtest::TS::CONSOLE, "bad depth: gold=%d, mine=%d\n", gold.depth(), mine.depth()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + if (gold.channels() != mine.channels()) + { + ts->printf(cvtest::TS::CONSOLE, "bad channel count: gold=%d, mine=%d\n", gold.channels(), mine.channels()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + for (int i = 0; i < gold.rows; ++i) + { + for (int j = 0; j < gold.cols * gold.channels(); ++j) + { + float gold_ = gold.at(i, j); + float mine_ = mine.at(i, j); + if (fabs(gold_ - mine_) > max_err) + { + ts->printf(cvtest::TS::CONSOLE, "bad values at %d %d: gold=%f, mine=%f\n", j / gold.channels(), i, gold_, mine_); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + } + } + return true; + } + + void testC2C(const std::string& hint, int cols, int rows, int flags, bool inplace=false) + { + Mat a; + gen(cols, rows, 2, a); + + Mat b_gold; + dft(a, b_gold, flags); + + GpuMat d_b; + GpuMat d_b_data; + if (inplace) + { + d_b_data.create(1, a.size().area(), CV_32FC2); + d_b = GpuMat(a.rows, a.cols, CV_32FC2, d_b_data.ptr(), a.cols * d_b_data.elemSize()); + } + + dft(GpuMat(a), d_b, Size(cols, rows), flags); + + bool ok = true; + if (ok && inplace && d_b.ptr() != d_b_data.ptr()) + { + ts->printf(cvtest::TS::CONSOLE, "unnecessary reallocation was done\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok && d_b.depth() != CV_32F) + { + ts->printf(cvtest::TS::CONSOLE, "bad depth: %d\n", d_b.depth()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok && d_b.channels() != 2) + { + ts->printf(cvtest::TS::CONSOLE, "bad channel count: %d\n", d_b.channels()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok) ok = cmp(b_gold, Mat(d_b), rows * cols * 1e-4f); + if (!ok) + ts->printf(cvtest::TS::CONSOLE, "testC2C failed: hint=%s, cols=%d, rows=%d, flags=%d, inplace=%d\n", + hint.c_str(), cols, rows, flags, inplace); + } + + void testR2CThenC2R(const std::string& hint, int cols, int rows, bool inplace=false) + { + Mat a; + gen(cols, rows, 1, a); + + bool ok = true; + + GpuMat d_b, d_c; + GpuMat d_b_data, d_c_data; + if (inplace) + { + if (a.cols == 1) + { + d_b_data.create(1, (a.rows / 2 + 1) * a.cols, CV_32FC2); + d_b = GpuMat(a.rows / 2 + 1, a.cols, CV_32FC2, d_b_data.ptr(), a.cols * d_b_data.elemSize()); + } + else + { + d_b_data.create(1, a.rows * (a.cols / 2 + 1), CV_32FC2); + d_b = GpuMat(a.rows, a.cols / 2 + 1, CV_32FC2, d_b_data.ptr(), (a.cols / 2 + 1) * d_b_data.elemSize()); + } + d_c_data.create(1, a.size().area(), CV_32F); + d_c = GpuMat(a.rows, a.cols, CV_32F, d_c_data.ptr(), a.cols * d_c_data.elemSize()); + } + + dft(GpuMat(a), d_b, Size(cols, rows), 0); + dft(d_b, d_c, Size(cols, rows), DFT_REAL_OUTPUT | DFT_SCALE); + + if (ok && inplace && d_b.ptr() != d_b_data.ptr()) + { + ts->printf(cvtest::TS::CONSOLE, "unnecessary reallocation was done for b\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok && inplace && d_c.ptr() != d_c_data.ptr()) + { + ts->printf(cvtest::TS::CONSOLE, "unnecessary reallocation was done for c\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok && d_c.depth() != CV_32F) + { + ts->printf(cvtest::TS::CONSOLE, "bad depth: %d\n", d_c.depth()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok && d_c.channels() != 1) + { + ts->printf(cvtest::TS::CONSOLE, "bad channel count: %d\n", d_c.channels()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ok = false; + } + if (ok) ok = cmp(a, Mat(d_c), rows * cols * 1e-5f); + if (!ok) + ts->printf(cvtest::TS::CONSOLE, "testR2CThenC2R failed: hint=%s, cols=%d, rows=%d, inplace=%d\n", + hint.c_str(), cols, rows, inplace); + } +}; + +TEST(dft, accuracy) { CV_GpuDftTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_features2d.cpp b/modules/gpu/test/test_features2d.cpp new file mode 100644 index 0000000000..c0f254e291 --- /dev/null +++ b/modules/gpu/test/test_features2d.cpp @@ -0,0 +1,229 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" +#include + +using namespace cv; +using namespace cv::gpu; +using namespace std; + +const string FEATURES2D_DIR = "features2d"; +const string IMAGE_FILENAME = "aloe.png"; +const string VALID_FILE_NAME = "surf.xml.gz"; + +class CV_GPU_SURFTest : public cvtest::BaseTest +{ +public: + CV_GPU_SURFTest() + { + } + +protected: + bool isSimilarKeypoints(const KeyPoint& p1, const KeyPoint& p2); + void compareKeypointSets(const vector& validKeypoints, const vector& calcKeypoints, + const Mat& validDescriptors, const Mat& calcDescriptors); + + void emptyDataTest(SURF_GPU& fdetector); + void regressionTest(SURF_GPU& fdetector); + + virtual void run(int); +}; + +void CV_GPU_SURFTest::emptyDataTest(SURF_GPU& fdetector) +{ + GpuMat image; + vector keypoints; + vector descriptors; + try + { + fdetector(image, GpuMat(), keypoints, descriptors); + } + catch(...) + { + ts->printf( cvtest::TS::LOG, "detect() on empty image must not generate exception (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + } + + if( !keypoints.empty() ) + { + ts->printf( cvtest::TS::LOG, "detect() on empty image must return empty keypoints vector (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + return; + } + + if( !descriptors.empty() ) + { + ts->printf( cvtest::TS::LOG, "detect() on empty image must return empty descriptors vector (1).\n" ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + return; + } +} + +bool CV_GPU_SURFTest::isSimilarKeypoints(const KeyPoint& p1, const KeyPoint& p2) +{ + const float maxPtDif = 1.f; + const float maxSizeDif = 1.f; + const float maxAngleDif = 2.f; + const float maxResponseDif = 0.1f; + + float dist = (float)norm( p1.pt - p2.pt ); + return (dist < maxPtDif && + fabs(p1.size - p2.size) < maxSizeDif && + abs(p1.angle - p2.angle) < maxAngleDif && + abs(p1.response - p2.response) < maxResponseDif && + p1.octave == p2.octave && + p1.class_id == p2.class_id ); +} + +void CV_GPU_SURFTest::compareKeypointSets(const vector& validKeypoints, const vector& calcKeypoints, + const Mat& validDescriptors, const Mat& calcDescriptors) +{ + if (validKeypoints.size() != calcKeypoints.size()) + { + ts->printf(cvtest::TS::LOG, "Keypoints sizes doesn't equal (validCount = %d, calcCount = %d).\n", + validKeypoints.size(), calcKeypoints.size()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + if (validDescriptors.size() != calcDescriptors.size()) + { + ts->printf(cvtest::TS::LOG, "Descriptors sizes doesn't equal.\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + for (size_t v = 0; v < validKeypoints.size(); v++) + { + int nearestIdx = -1; + float minDist = std::numeric_limits::max(); + + for (size_t c = 0; c < calcKeypoints.size(); c++) + { + float curDist = (float)norm(calcKeypoints[c].pt - validKeypoints[v].pt); + if (curDist < minDist) + { + minDist = curDist; + nearestIdx = c; + } + } + + assert(minDist >= 0); + if (!isSimilarKeypoints(validKeypoints[v], calcKeypoints[nearestIdx])) + { + ts->printf(cvtest::TS::LOG, "Bad keypoints accuracy.\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; + } + + if (norm(validDescriptors.row(v), calcDescriptors.row(nearestIdx), NORM_L2) > 1.5f) + { + ts->printf(cvtest::TS::LOG, "Bad descriptors accuracy.\n"); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; + } + } +} + +void CV_GPU_SURFTest::regressionTest(SURF_GPU& fdetector) +{ + string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME; + string resFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + VALID_FILE_NAME; + + // Read the test image. + GpuMat image(imread(imgFilename, 0)); + if (image.empty()) + { + ts->printf( cvtest::TS::LOG, "Image %s can not be read.\n", imgFilename.c_str() ); + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); + return; + } + + FileStorage fs(resFilename, FileStorage::READ); + + // Compute keypoints. + GpuMat mask(image.size(), CV_8UC1, Scalar::all(1)); + mask(Range(0, image.rows / 2), Range(0, image.cols / 2)).setTo(Scalar::all(0)); + vector calcKeypoints; + GpuMat calcDespcriptors; + fdetector(image, mask, calcKeypoints, calcDespcriptors); + + if (fs.isOpened()) // Compare computed and valid keypoints. + { + // Read validation keypoints set. + vector validKeypoints; + Mat validDespcriptors; + read(fs["keypoints"], validKeypoints); + read(fs["descriptors"], validDespcriptors); + if (validKeypoints.empty() || validDespcriptors.empty()) + { + ts->printf(cvtest::TS::LOG, "Validation file can not be read.\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + + compareKeypointSets(validKeypoints, calcKeypoints, validDespcriptors, calcDespcriptors); + } + else // Write detector parameters and computed keypoints as validation data. + { + fs.open(resFilename, FileStorage::WRITE); + if (!fs.isOpened()) + { + ts->printf(cvtest::TS::LOG, "File %s can not be opened to write.\n", resFilename.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + else + { + write(fs, "keypoints", calcKeypoints); + write(fs, "descriptors", (Mat)calcDespcriptors); + } + } +} + +void CV_GPU_SURFTest::run( int /*start_from*/ ) +{ + SURF_GPU fdetector; + + emptyDataTest(fdetector); + regressionTest(fdetector); +} + +TEST(SURF, empty_data_and_regression) { CV_GPU_SURFTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_filters.cpp b/modules/gpu/test/test_filters.cpp new file mode 100644 index 0000000000..c3e65b531b --- /dev/null +++ b/modules/gpu/test/test_filters.cpp @@ -0,0 +1,367 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 +#include +#include +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; +using namespace gpu; + +class CV_GpuNppFilterTest : public cvtest::BaseTest +{ +public: + CV_GpuNppFilterTest(const char* test_name, const char* test_funcs) {} + virtual ~CV_GpuNppFilterTest() {} + +protected: + void run(int); + virtual int test(const Mat& img) = 0; + + int test8UC1(const Mat& img) + { + cv::Mat img_C1; + cvtColor(img, img_C1, CV_BGR2GRAY); + return test(img_C1); + } + + int test8UC4(const Mat& img) + { + cv::Mat img_C4; + cvtColor(img, img_C4, CV_BGR2BGRA); + return test(img_C4); + } + + int CheckNorm(const Mat& m1, const Mat& m2, const Size& ksize) + { + Rect roi = Rect(ksize.width, ksize.height, m1.cols - 2 * ksize.width, m1.rows - 2 * ksize.height); + Mat m1ROI = m1(roi); + Mat m2ROI = m2(roi); + + double res = norm(m1ROI, m2ROI, NORM_INF); + + // Max difference (2.0) in GaussianBlur + if (res <= 2) + return cvtest::TS::OK; + + ts->printf(cvtest::TS::LOG, "Norm: %f\n", res); + return cvtest::TS::FAIL_GENERIC; + } +}; + +void CV_GpuNppFilterTest::run( int ) +{ + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png"); + + if (img.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + //run tests + int testResult = cvtest::TS::OK; + + if (test8UC1(img) != cvtest::TS::OK) + testResult = cvtest::TS::FAIL_GENERIC; + + if (test8UC4(img) != cvtest::TS::OK) + testResult = cvtest::TS::FAIL_GENERIC; + + ts->set_failed_test_info(testResult); + + ts->set_failed_test_info(cvtest::TS::OK); +} + +//////////////////////////////////////////////////////////////////////////////// +// blur +struct CV_GpuNppImageBlurTest : public CV_GpuNppFilterTest +{ + CV_GpuNppImageBlurTest() : CV_GpuNppFilterTest( "GPU-NppImageBlur", "blur" ) {} + + int test(const Mat& img) + { + int ksizes[] = {3, 5, 7}; + int ksizes_num = sizeof(ksizes) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < ksizes_num; ++i) + { + for (int j = 0; j < ksizes_num; ++j) + { + Size ksize(ksizes[i], ksizes[j]); + + ts->printf(cvtest::TS::LOG, "\nksize = (%dx%d)\n", ksizes[i], ksizes[j]); + + Mat cpudst; + cv::blur(img, cpudst, ksize); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::blur(gpu1, gpudst, ksize); + + if (CheckNorm(cpudst, gpudst, ksize) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Sobel +struct CV_GpuNppImageSobelTest : public CV_GpuNppFilterTest +{ + CV_GpuNppImageSobelTest() : CV_GpuNppFilterTest( "GPU-NppImageSobel", "Sobel" ) {} + + int test(const Mat& img) + { + int ksizes[] = {3, 5, 7}; + int ksizes_num = sizeof(ksizes) / sizeof(int); + + int dx = 1, dy = 0; + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < ksizes_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nksize = %d\n", ksizes[i]); + + Mat cpudst; + cv::Sobel(img, cpudst, -1, dx, dy, ksizes[i]); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::Sobel(gpu1, gpudst, -1, dx, dy, ksizes[i]); + + if (CheckNorm(cpudst, gpudst, Size(ksizes[i], ksizes[i])) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Scharr +struct CV_GpuNppImageScharrTest : public CV_GpuNppFilterTest +{ + CV_GpuNppImageScharrTest() : CV_GpuNppFilterTest( "GPU-NppImageScharr", "Scharr" ) {} + + int test(const Mat& img) + { + int dx = 1, dy = 0; + + Mat cpudst; + cv::Scharr(img, cpudst, -1, dx, dy); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::Scharr(gpu1, gpudst, -1, dx, dy); + + return CheckNorm(cpudst, gpudst, Size(3, 3)); + } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// GaussianBlur +struct CV_GpuNppImageGaussianBlurTest : public CV_GpuNppFilterTest +{ + CV_GpuNppImageGaussianBlurTest() : CV_GpuNppFilterTest( "GPU-NppImageGaussianBlur", "GaussianBlur" ) {} + + int test(const Mat& img) + { + int ksizes[] = {3, 5, 7}; + int ksizes_num = sizeof(ksizes) / sizeof(int); + + int test_res = cvtest::TS::OK; + + const double sigma1 = 3.0; + + for (int i = 0; i < ksizes_num; ++i) + { + for (int j = 0; j < ksizes_num; ++j) + { + cv::Size ksize(ksizes[i], ksizes[j]); + + ts->printf(cvtest::TS::LOG, "ksize = (%dx%d)\t\n", ksizes[i], ksizes[j]); + + Mat cpudst; + cv::GaussianBlur(img, cpudst, ksize, sigma1); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::GaussianBlur(gpu1, gpudst, ksize, sigma1); + + if (CheckNorm(cpudst, gpudst, ksize) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Laplacian +struct CV_GpuNppImageLaplacianTest : public CV_GpuNppFilterTest +{ + CV_GpuNppImageLaplacianTest() : CV_GpuNppFilterTest( "GPU-NppImageLaplacian", "Laplacian" ) {} + + int test(const Mat& img) + { + int ksizes[] = {1, 3}; + int ksizes_num = sizeof(ksizes) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < ksizes_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nksize = %d\n", ksizes[i]); + + Mat cpudst; + cv::Laplacian(img, cpudst, -1, ksizes[i]); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::Laplacian(gpu1, gpudst, -1, ksizes[i]); + + if (CheckNorm(cpudst, gpudst, Size(3, 3)) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Erode +class CV_GpuErodeTest : public CV_GpuNppFilterTest +{ +public: + CV_GpuErodeTest() : CV_GpuNppFilterTest( "GPU-NppErode", "erode" ) {} + +protected: + virtual int test(const Mat& img) + { + Mat kernel(Mat::ones(3, 3, CV_8U)); + + cv::Mat cpuRes; + cv::erode(img, cpuRes, kernel); + + GpuMat gpuRes; + cv::gpu::erode(GpuMat(img), gpuRes, kernel); + + return CheckNorm(cpuRes, gpuRes, Size(3, 3)); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Dilate +class CV_GpuDilateTest : public CV_GpuNppFilterTest +{ +public: + CV_GpuDilateTest() : CV_GpuNppFilterTest( "GPU-NppDilate", "dilate" ) {} + +protected: + virtual int test(const Mat& img) + { + Mat kernel(Mat::ones(3, 3, CV_8U)); + + cv::Mat cpuRes; + cv::dilate(img, cpuRes, kernel); + + GpuMat gpuRes; + cv::gpu::dilate(GpuMat(img), gpuRes, kernel); + + return CheckNorm(cpuRes, gpuRes, Size(3, 3)); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// MorphologyEx +class CV_GpuMorphExTest : public CV_GpuNppFilterTest +{ +public: + CV_GpuMorphExTest() : CV_GpuNppFilterTest( "GPU-NppMorphologyEx", "morphologyEx" ) {} + +protected: + virtual int test(const Mat& img) + { + static int ops[] = { MORPH_OPEN, CV_MOP_CLOSE, CV_MOP_GRADIENT, CV_MOP_TOPHAT, CV_MOP_BLACKHAT}; + const char *names[] = { "MORPH_OPEN", "CV_MOP_CLOSE", "CV_MOP_GRADIENT", "CV_MOP_TOPHAT", "CV_MOP_BLACKHAT"}; + int num = sizeof(ops)/sizeof(ops[0]); + + GpuMat kernel(Mat::ones(3, 3, CV_8U)); + + int res = cvtest::TS::OK; + + for(int i = 0; i < num; ++i) + { + ts->printf(cvtest::TS::LOG, "Tesing %s\n", names[i]); + + cv::Mat cpuRes; + cv::morphologyEx(img, cpuRes, ops[i], kernel); + + GpuMat gpuRes; + cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel); + + if (cvtest::TS::OK != CheckNorm(cpuRes, gpuRes, Size(4, 4))) + res = cvtest::TS::FAIL_GENERIC; + } + return res; + } +}; + + +TEST(blur, accuracy) { CV_GpuNppImageBlurTest test; test.safe_run(); } +TEST(sobel, accuracy) { CV_GpuNppImageSobelTest test; test.safe_run(); } +TEST(scharr, accuracy) { CV_GpuNppImageScharrTest test; test.safe_run(); } +TEST(gaussianBlur, accuracy) { CV_GpuNppImageGaussianBlurTest test; test.safe_run(); } +TEST(laplcaian, accuracy) { CV_GpuNppImageLaplacianTest test; test.safe_run(); } +TEST(erode, accuracy) { CV_GpuErodeTest test; test.safe_run(); } +TEST(dilate, accuracy) { CV_GpuDilateTest test; test.safe_run(); } +TEST(morphEx, accuracy) { CV_GpuMorphExTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_hog.cpp b/modules/gpu/test/test_hog.cpp new file mode 100644 index 0000000000..b44285f9d9 --- /dev/null +++ b/modules/gpu/test/test_hog.cpp @@ -0,0 +1,319 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" +#include + +using namespace std; + +//#define DUMP + +#define CHECK(pred, err) if (!(pred)) { \ + ts->printf(cvtest::TS::CONSOLE, "Fail: \"%s\" at line: %d\n", #pred, __LINE__); \ + ts->set_failed_test_info(err); \ + return; } + +struct CV_GpuHogDetectTestRunner: cv::gpu::HOGDescriptor +{ + CV_GpuHogDetectTestRunner(cvtest::TS* ts_): ts(ts_) {} + + void run(int) + { + cv::Mat img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/road.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + +#ifdef DUMP + f.open((std::string(ts->get_data_path()) + "hog/expected_output.bin").c_str(), std::ios_base::binary); + CHECK(f.is_open(), cvtest::TS::FAIL_GENERIC); +#else + f.open((std::string(ts->get_data_path()) + "hog/expected_output.bin").c_str(), std::ios_base::binary); + CHECK(f.is_open(), cvtest::TS::FAIL_MISSING_TEST_DATA); +#endif + + // Test on color image + cv::Mat img; + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + test(img); + + // Test on gray image + cv::cvtColor(img_rgb, img, CV_BGR2GRAY); + test(img); + + f.close(); + + } + +#ifdef DUMP + void dump(const cv::Mat& block_hists, const std::vector& locations) + { + f.write((char*)&block_hists.rows, sizeof(block_hists.rows)); + f.write((char*)&block_hists.cols, sizeof(block_hists.cols)); + for (int i = 0; i < block_hists.rows; ++i) + { + for (int j = 0; j < block_hists.cols; ++j) + { + float val = block_hists.at(i, j); + f.write((char*)&val, sizeof(val)); + } + } + size_t nlocations = locations.size(); + f.write((char*)&nlocations, sizeof(nlocations)); + for (size_t i = 0; i < locations.size(); ++i) + f.write((char*)&locations[i], sizeof(locations[i])); + } +#else + void compare(const cv::Mat& block_hists, const std::vector& locations) + { + int rows, cols; + size_t nlocations; + + f.read((char*)&rows, sizeof(rows)); + f.read((char*)&cols, sizeof(cols)); + CHECK(rows == block_hists.rows, cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(cols == block_hists.cols, cvtest::TS::FAIL_INVALID_OUTPUT); + for (int i = 0; i < block_hists.rows; ++i) + { + for (int j = 0; j < block_hists.cols; ++j) + { + float val; + f.read((char*)&val, sizeof(val)); + CHECK(fabs(val - block_hists.at(i, j)) < 1e-3f, cvtest::TS::FAIL_INVALID_OUTPUT); + } + } + f.read((char*)&nlocations, sizeof(nlocations)); + CHECK(nlocations == locations.size(), cvtest::TS::FAIL_INVALID_OUTPUT); + for (size_t i = 0; i < nlocations; ++i) + { + cv::Point location; + f.read((char*)&location, sizeof(location)); + CHECK(location == locations[i], cvtest::TS::FAIL_INVALID_OUTPUT); + } + } +#endif + + void test(const cv::Mat& img) + { + cv::gpu::GpuMat d_img(img); + + gamma_correction = false; + setSVMDetector(cv::gpu::HOGDescriptor::getDefaultPeopleDetector()); + //cpu detector may be updated soon + //hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector()); + + std::vector locations; + + // Test detect + detect(d_img, locations, 0); + +#ifdef DUMP + dump(block_hists, locations); +#else + compare(block_hists, locations); +#endif + + // Test detect on smaller image + cv::Mat img2; + cv::resize(img, img2, cv::Size(img.cols / 2, img.rows / 2)); + detect(cv::gpu::GpuMat(img2), locations, 0); + +#ifdef DUMP + dump(block_hists, locations); +#else + compare(block_hists, locations); +#endif + + // Test detect on greater image + cv::resize(img, img2, cv::Size(img.cols * 2, img.rows * 2)); + detect(cv::gpu::GpuMat(img2), locations, 0); + +#ifdef DUMP + dump(block_hists, locations); +#else + compare(block_hists, locations); +#endif + } + +#ifdef DUMP + std::ofstream f; +#else + std::ifstream f; +#endif + + cvtest::TS* ts; +}; + + +struct CV_GpuHogDetectTest: cvtest::BaseTest +{ + CV_GpuHogDetectTest() {} + + void run(int i) + { + CV_GpuHogDetectTestRunner runner(ts); + runner.run(i); + } +}; + +TEST(HOG, detect_accuracy) { CV_GpuHogDetectTest test; test.safe_run(); } + +struct CV_GpuHogGetDescriptorsTestRunner: cv::gpu::HOGDescriptor +{ + CV_GpuHogGetDescriptorsTestRunner(cvtest::TS* ts_): HOGDescriptor(cv::Size(64, 128)), ts(ts_) {} + + void run(int) + { + // Load image (e.g. train data, composed from windows) + cv::Mat img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/train_data.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + + // Convert to C4 + cv::Mat img; + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + cv::gpu::GpuMat d_img(img); + + + // Convert train images into feature vectors (train table) + cv::gpu::GpuMat descriptors, descriptors_by_cols; + getDescriptors(d_img, win_size, descriptors, DESCR_FORMAT_ROW_BY_ROW); + getDescriptors(d_img, win_size, descriptors_by_cols, DESCR_FORMAT_COL_BY_COL); + + // Check size of the result train table + wins_per_img_x = 3; + wins_per_img_y = 2; + blocks_per_win_x = 7; + blocks_per_win_y = 15; + block_hist_size = 36; + cv::Size descr_size_expected = cv::Size(blocks_per_win_x * blocks_per_win_y * block_hist_size, + wins_per_img_x * wins_per_img_y); + CHECK(descriptors.size() == descr_size_expected, cvtest::TS::FAIL_INVALID_OUTPUT); + + // Check both formats of output descriptors are handled correctly + cv::Mat dr(descriptors); + cv::Mat dc(descriptors_by_cols); + for (int i = 0; i < wins_per_img_x * wins_per_img_y; ++i) + { + const float* l = dr.rowRange(i, i + 1).ptr(); + const float* r = dc.rowRange(i, i + 1).ptr(); + for (int y = 0; y < blocks_per_win_y; ++y) + for (int x = 0; x < blocks_per_win_x; ++x) + for (int k = 0; k < block_hist_size; ++k) + CHECK(l[(y * blocks_per_win_x + x) * block_hist_size + k] == + r[(x * blocks_per_win_y + y) * block_hist_size + k], cvtest::TS::FAIL_INVALID_OUTPUT); + } + + /* Now we want to extract the same feature vectors, but from single images. NOTE: results will + be defferent, due to border values interpolation. Using of many small images is slower, however we + wont't call getDescriptors and will use computeBlockHistograms instead of. computeBlockHistograms + works good, it can be checked in the gpu_hog sample */ + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/positive1.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + // Everything is fine with interpolation for left top subimage + CHECK(cv::norm(block_hists, descriptors.rowRange(0, 1)) == 0.f, cvtest::TS::FAIL_INVALID_OUTPUT); + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/positive2.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + compare_inner_parts(block_hists, descriptors.rowRange(1, 2)); + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/negative1.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + compare_inner_parts(block_hists, descriptors.rowRange(2, 3)); + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/negative2.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + compare_inner_parts(block_hists, descriptors.rowRange(3, 4)); + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/positive3.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + compare_inner_parts(block_hists, descriptors.rowRange(4, 5)); + + img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/negative3.png"); + CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); + cv::cvtColor(img_rgb, img, CV_BGR2BGRA); + computeBlockHistograms(cv::gpu::GpuMat(img)); + compare_inner_parts(block_hists, descriptors.rowRange(5, 6)); + } + + // Does not compare border value, as interpolation leads to delta + void compare_inner_parts(cv::Mat d1, cv::Mat d2) + { + for (int i = 1; i < blocks_per_win_y - 1; ++i) + for (int j = 1; j < blocks_per_win_x - 1; ++j) + for (int k = 0; k < block_hist_size; ++k) + { + float a = d1.at(0, (i * blocks_per_win_x + j) * block_hist_size); + float b = d2.at(0, (i * blocks_per_win_x + j) * block_hist_size); + CHECK(a == b, cvtest::TS::FAIL_INVALID_OUTPUT) + } + } + + int wins_per_img_x; + int wins_per_img_y; + int blocks_per_win_x; + int blocks_per_win_y; + int block_hist_size; + + cvtest::TS* ts; +}; + + +struct CV_GpuHogGetDescriptorsTest: cvtest::BaseTest +{ + CV_GpuHogGetDescriptorsTest() {} + + void run(int i) + { + CV_GpuHogGetDescriptorsTestRunner runner(ts); + runner.run(i); + } +}; + +TEST(HOG, descriptors_accuracy) { CV_GpuHogGetDescriptorsTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_imgproc_gpu.cpp b/modules/gpu/test/test_imgproc_gpu.cpp new file mode 100644 index 0000000000..ce0c4ed5ab --- /dev/null +++ b/modules/gpu/test/test_imgproc_gpu.cpp @@ -0,0 +1,917 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 +#include +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; +using namespace gpu; + +class CV_GpuImageProcTest : public cvtest::BaseTest +{ +public: + virtual ~CV_GpuImageProcTest() {} + +protected: + void run(int); + + int test8UC1 (const Mat& img); + int test8UC4 (const Mat& img); + int test32SC1(const Mat& img); + int test32FC1(const Mat& img); + + virtual int test(const Mat& img) = 0; + + int CheckNorm(const Mat& m1, const Mat& m2); + + // Checks whether two images are similar enough using normalized + // cross-correlation as an error measure + int CheckSimilarity(const Mat& m1, const Mat& m2, float max_err=1e-3f); +}; + + +int CV_GpuImageProcTest::test8UC1(const Mat& img) +{ + cv::Mat img_C1; + cvtColor(img, img_C1, CV_BGR2GRAY); + + return test(img_C1); +} + +int CV_GpuImageProcTest::test8UC4(const Mat& img) +{ + cv::Mat img_C4; + cvtColor(img, img_C4, CV_BGR2BGRA); + + return test(img_C4); +} + +int CV_GpuImageProcTest::test32SC1(const Mat& img) +{ + cv::Mat img_C1; + cvtColor(img, img_C1, CV_BGR2GRAY); + img_C1.convertTo(img_C1, CV_32S); + + return test(img_C1); +} + +int CV_GpuImageProcTest::test32FC1(const Mat& img) +{ + cv::Mat temp, img_C1; + img.convertTo(temp, CV_32F, 1.f / 255.f); + cvtColor(temp, img_C1, CV_BGR2GRAY); + + return test(img_C1); +} + +int CV_GpuImageProcTest::CheckNorm(const Mat& m1, const Mat& m2) +{ + double ret = norm(m1, m2, NORM_INF); + + if (ret < std::numeric_limits::epsilon()) + { + return cvtest::TS::OK; + } + else + { + ts->printf(cvtest::TS::LOG, "Norm: %f\n", ret); + return cvtest::TS::FAIL_GENERIC; + } +} + +int CV_GpuImageProcTest::CheckSimilarity(const Mat& m1, const Mat& m2, float max_err) +{ + Mat diff; + cv::matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED); + + float err = abs(diff.at(0, 0) - 1.f); + + if (err > max_err) + return cvtest::TS::FAIL_INVALID_OUTPUT; + + return cvtest::TS::OK; +} + +void CV_GpuImageProcTest::run( int ) +{ + //load image + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png"); + + if (img.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + int testResult = cvtest::TS::OK; + //run tests + ts->printf(cvtest::TS::LOG, "\n========Start test 8UC1========\n"); + if (test8UC1(img) == cvtest::TS::OK) + ts->printf(cvtest::TS::LOG, "SUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "FAIL\n"); + testResult = cvtest::TS::FAIL_GENERIC; + } + + ts->printf(cvtest::TS::LOG, "\n========Start test 8UC4========\n"); + if (test8UC4(img) == cvtest::TS::OK) + ts->printf(cvtest::TS::LOG, "SUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "FAIL\n"); + testResult = cvtest::TS::FAIL_GENERIC; + } + + ts->printf(cvtest::TS::LOG, "\n========Start test 32SC1========\n"); + if (test32SC1(img) == cvtest::TS::OK) + ts->printf(cvtest::TS::LOG, "SUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "FAIL\n"); + testResult = cvtest::TS::FAIL_GENERIC; + } + + ts->printf(cvtest::TS::LOG, "\n========Start test 32FC1========\n"); + if (test32FC1(img) == cvtest::TS::OK) + ts->printf(cvtest::TS::LOG, "SUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "FAIL\n"); + testResult = cvtest::TS::FAIL_GENERIC; + } + + ts->set_failed_test_info(testResult); +} + +//////////////////////////////////////////////////////////////////////////////// +// threshold +struct CV_GpuImageThresholdTest : public CV_GpuImageProcTest +{ +public: + CV_GpuImageThresholdTest() {} + + int test(const Mat& img) + { + if (img.type() != CV_8UC1 && img.type() != CV_32FC1) + { + ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); + return cvtest::TS::OK; + } + + const double maxVal = img.type() == CV_8UC1 ? 255 : 1.0; + + cv::RNG& rng = ts->get_rng(); + + int res = cvtest::TS::OK; + + for (int type = THRESH_BINARY; type <= THRESH_TOZERO_INV; ++type) + { + const double thresh = rng.uniform(0.0, maxVal); + + cv::Mat cpuRes; + cv::threshold(img, cpuRes, thresh, maxVal, type); + + GpuMat gpu1(img); + GpuMat gpuRes; + cv::gpu::threshold(gpu1, gpuRes, thresh, maxVal, type); + + if (CheckNorm(cpuRes, gpuRes) != cvtest::TS::OK) + res = cvtest::TS::FAIL_GENERIC; + } + + return res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// resize +struct CV_GpuNppImageResizeTest : public CV_GpuImageProcTest +{ + CV_GpuNppImageResizeTest() {} + int test(const Mat& img) + { + if (img.type() != CV_8UC1 && img.type() != CV_8UC4) + { + ts->printf(cvtest::TS::LOG, "Unsupported type\n"); + return cvtest::TS::OK; + } + + int interpolations[] = {INTER_NEAREST, INTER_LINEAR, /*INTER_CUBIC,*/ /*INTER_LANCZOS4*/}; + const char* interpolations_str[] = {"INTER_NEAREST", "INTER_LINEAR", /*"INTER_CUBIC",*/ /*"INTER_LANCZOS4"*/}; + int interpolations_num = sizeof(interpolations) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < interpolations_num; ++i) + { + ts->printf(cvtest::TS::LOG, "Interpolation: %s\n", interpolations_str[i]); + + Mat cpu_res1, cpu_res2; + cv::resize(img, cpu_res1, Size(), 2.0, 2.0, interpolations[i]); + cv::resize(cpu_res1, cpu_res2, Size(), 0.5, 0.5, interpolations[i]); + + GpuMat gpu1(img), gpu_res1, gpu_res2; + cv::gpu::resize(gpu1, gpu_res1, Size(), 2.0, 2.0, interpolations[i]); + cv::gpu::resize(gpu_res1, gpu_res2, Size(), 0.5, 0.5, interpolations[i]); + + if (CheckSimilarity(cpu_res2, gpu_res2) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// copyMakeBorder +struct CV_GpuNppImageCopyMakeBorderTest : public CV_GpuImageProcTest +{ + CV_GpuNppImageCopyMakeBorderTest() {} + + int test(const Mat& img) + { + if (img.type() != CV_8UC1 && img.type() != CV_8UC4 && img.type() != CV_32SC1) + { + ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); + return cvtest::TS::OK; + } + + cv::RNG& rng = ts->get_rng(); + int top = rng.uniform(1, 10); + int botton = rng.uniform(1, 10); + int left = rng.uniform(1, 10); + int right = rng.uniform(1, 10); + cv::Scalar val(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); + + Mat cpudst; + cv::copyMakeBorder(img, cpudst, top, botton, left, right, BORDER_CONSTANT, val); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::copyMakeBorder(gpu1, gpudst, top, botton, left, right, val); + + return CheckNorm(cpudst, gpudst); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// warpAffine +struct CV_GpuNppImageWarpAffineTest : public CV_GpuImageProcTest +{ + CV_GpuNppImageWarpAffineTest() {} + + int test(const Mat& img) + { + if (img.type() == CV_32SC1) + { + ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); + return cvtest::TS::OK; + } + + static double reflect[2][3] = { {-1, 0, 0}, + { 0, -1, 0} }; + reflect[0][2] = img.cols; + reflect[1][2] = img.rows; + + Mat M(2, 3, CV_64F, (void*)reflect); + + int flags[] = {INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_NEAREST | WARP_INVERSE_MAP, INTER_LINEAR | WARP_INVERSE_MAP, INTER_CUBIC | WARP_INVERSE_MAP}; + const char* flags_str[] = {"INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_NEAREST | WARP_INVERSE_MAP", "INTER_LINEAR | WARP_INVERSE_MAP", "INTER_CUBIC | WARP_INVERSE_MAP"}; + int flags_num = sizeof(flags) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < flags_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nFlags: %s\n", flags_str[i]); + + Mat cpudst; + cv::warpAffine(img, cpudst, M, img.size(), flags[i]); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::warpAffine(gpu1, gpudst, M, gpu1.size(), flags[i]); + + // Check inner parts (ignoring 1 pixel width border) + if (CheckSimilarity(cpudst.rowRange(1, cpudst.rows - 1).colRange(1, cpudst.cols - 1), + gpudst.rowRange(1, gpudst.rows - 1).colRange(1, gpudst.cols - 1)) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// warpPerspective +struct CV_GpuNppImageWarpPerspectiveTest : public CV_GpuImageProcTest +{ + CV_GpuNppImageWarpPerspectiveTest() {} + + + int test(const Mat& img) + { + if (img.type() == CV_32SC1) + { + ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); + return cvtest::TS::OK; + } + + static double reflect[3][3] = { { -1, 0, 0}, + { 0, -1, 0}, + { 0, 0, 1 }}; + reflect[0][2] = img.cols; + reflect[1][2] = img.rows; + Mat M(3, 3, CV_64F, (void*)reflect); + + int flags[] = {INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_NEAREST | WARP_INVERSE_MAP, INTER_LINEAR | WARP_INVERSE_MAP, INTER_CUBIC | WARP_INVERSE_MAP}; + const char* flags_str[] = {"INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_NEAREST | WARP_INVERSE_MAP", "INTER_LINEAR | WARP_INVERSE_MAP", "INTER_CUBIC | WARP_INVERSE_MAP"}; + int flags_num = sizeof(flags) / sizeof(int); + + int test_res = cvtest::TS::OK; + + for (int i = 0; i < flags_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\nFlags: %s\n", flags_str[i]); + + Mat cpudst; + cv::warpPerspective(img, cpudst, M, img.size(), flags[i]); + + GpuMat gpu1(img); + GpuMat gpudst; + cv::gpu::warpPerspective(gpu1, gpudst, M, gpu1.size(), flags[i]); + + // Check inner parts (ignoring 1 pixel width border) + if (CheckSimilarity(cpudst.rowRange(1, cpudst.rows - 1).colRange(1, cpudst.cols - 1), + gpudst.rowRange(1, gpudst.rows - 1).colRange(1, gpudst.cols - 1)) != cvtest::TS::OK) + test_res = cvtest::TS::FAIL_GENERIC; + } + + return test_res; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// integral +struct CV_GpuNppImageIntegralTest : public CV_GpuImageProcTest +{ + CV_GpuNppImageIntegralTest() {} + + int test(const Mat& img) + { + if (img.type() != CV_8UC1) + { + ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); + return cvtest::TS::OK; + } + + Mat cpusum; + cv::integral(img, cpusum, CV_32S); + + GpuMat gpu1(img); + GpuMat gpusum; + cv::gpu::integral(gpu1, gpusum); + + return CheckNorm(cpusum, gpusum) == cvtest::TS::OK ? cvtest::TS::OK : cvtest::TS::FAIL_GENERIC; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Canny +//struct CV_GpuNppImageCannyTest : public CV_GpuImageProcTest +//{ +// CV_GpuNppImageCannyTest() : CV_GpuImageProcTest( "GPU-NppImageCanny", "Canny" ) {} +// +// int test(const Mat& img) +// { +// if (img.type() != CV_8UC1) +// { +// ts->printf(cvtest::TS::LOG, "\nUnsupported type\n"); +// return cvtest::TS::OK; +// } +// +// const double threshold1 = 1.0, threshold2 = 10.0; +// +// Mat cpudst; +// cv::Canny(img, cpudst, threshold1, threshold2); +// +// GpuMat gpu1(img); +// GpuMat gpudst; +// cv::gpu::Canny(gpu1, gpudst, threshold1, threshold2); +// +// return CheckNorm(cpudst, gpudst); +// } +//}; + +//////////////////////////////////////////////////////////////////////////////// +// cvtColor +class CV_GpuCvtColorTest : public cvtest::BaseTest +{ +public: + CV_GpuCvtColorTest() {} + ~CV_GpuCvtColorTest() {}; + +protected: + void run(int); + + int CheckNorm(const Mat& m1, const Mat& m2); +}; + + +int CV_GpuCvtColorTest::CheckNorm(const Mat& m1, const Mat& m2) +{ + double ret = norm(m1, m2, NORM_INF); + + if (ret <= 3) + { + return cvtest::TS::OK; + } + else + { + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return cvtest::TS::FAIL_GENERIC; + } +} + +void CV_GpuCvtColorTest::run( int ) +{ + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png"); + + if (img.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + int testResult = cvtest::TS::OK; + cv::Mat cpuRes; + cv::gpu::GpuMat gpuImg(img), gpuRes; + + int codes[] = { CV_BGR2RGB, CV_RGB2BGRA, CV_BGRA2RGB, + CV_RGB2BGR555, CV_BGR5552BGR, CV_BGR2BGR565, CV_BGR5652RGB, + CV_RGB2YCrCb, CV_YCrCb2BGR, CV_BGR2YUV, CV_YUV2RGB, + CV_RGB2XYZ, CV_XYZ2BGR, CV_BGR2XYZ, CV_XYZ2RGB, + CV_RGB2HSV, CV_HSV2BGR, CV_BGR2HSV_FULL, CV_HSV2RGB_FULL, + CV_RGB2HLS, CV_HLS2BGR, CV_BGR2HLS_FULL, CV_HLS2RGB_FULL, + CV_RGB2GRAY, CV_GRAY2BGRA, CV_BGRA2GRAY, + CV_GRAY2BGR555, CV_BGR5552GRAY, CV_GRAY2BGR565, CV_BGR5652GRAY}; + const char* codes_str[] = { "CV_BGR2RGB", "CV_RGB2BGRA", "CV_BGRA2RGB", + "CV_RGB2BGR555", "CV_BGR5552BGR", "CV_BGR2BGR565", "CV_BGR5652RGB", + "CV_RGB2YCrCb", "CV_YCrCb2BGR", "CV_BGR2YUV", "CV_YUV2RGB", + "CV_RGB2XYZ", "CV_XYZ2BGR", "CV_BGR2XYZ", "CV_XYZ2RGB", + "CV_RGB2HSV", "CV_HSV2RGB", "CV_BGR2HSV_FULL", "CV_HSV2RGB_FULL", + "CV_RGB2HLS", "CV_HLS2RGB", "CV_BGR2HLS_FULL", "CV_HLS2RGB_FULL", + "CV_RGB2GRAY", "CV_GRAY2BGRA", "CV_BGRA2GRAY", + "CV_GRAY2BGR555", "CV_BGR5552GRAY", "CV_GRAY2BGR565", "CV_BGR5652GRAY"}; + int codes_num = sizeof(codes) / sizeof(int); + + for (int i = 0; i < codes_num; ++i) + { + ts->printf(cvtest::TS::LOG, "\n%s\n", codes_str[i]); + + cv::cvtColor(img, cpuRes, codes[i]); + cv::gpu::cvtColor(gpuImg, gpuRes, codes[i]); + + if (CheckNorm(cpuRes, gpuRes) == cvtest::TS::OK) + ts->printf(cvtest::TS::LOG, "\nSUCCESS\n"); + else + { + ts->printf(cvtest::TS::LOG, "\nFAIL\n"); + testResult = cvtest::TS::FAIL_GENERIC; + } + + img = cpuRes; + gpuImg = gpuRes; + } + + ts->set_failed_test_info(testResult); +} + +//////////////////////////////////////////////////////////////////////////////// +// Histograms +class CV_GpuHistogramsTest : public cvtest::BaseTest +{ +public: + CV_GpuHistogramsTest() {} + ~CV_GpuHistogramsTest() {}; + +protected: + void run(int); + + int CheckNorm(const Mat& m1, const Mat& m2) + { + double ret = norm(m1, m2, NORM_INF); + + if (ret < std::numeric_limits::epsilon()) + { + return cvtest::TS::OK; + } + else + { + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return cvtest::TS::FAIL_GENERIC; + } + } +}; + +void CV_GpuHistogramsTest::run( int ) +{ + //load image + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png"); + + if (img.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + Mat hsv; + cv::cvtColor(img, hsv, CV_BGR2HSV); + + int hbins = 30; + int histSize[] = {hbins}; + + float hranges[] = {0, 180}; + const float* ranges[] = {hranges}; + + MatND hist; + + int channels[] = {0}; + calcHist(&hsv, 1, channels, Mat(), hist, 1, histSize, ranges); + + GpuMat gpuHsv(hsv); + std::vector srcs; + cv::gpu::split(gpuHsv, srcs); + GpuMat gpuHist; + histEven(srcs[0], gpuHist, hbins, (int)hranges[0], (int)hranges[1]); + + Mat cpuHist = hist; + cpuHist = cpuHist.t(); + cpuHist.convertTo(cpuHist, CV_32S); + + ts->set_failed_test_info(CheckNorm(cpuHist, gpuHist)); +} + +//////////////////////////////////////////////////////////////////////// +// Corner Harris feature detector + +struct CV_GpuCornerHarrisTest: cvtest::BaseTest +{ + CV_GpuCornerHarrisTest() {} + + void run(int) + { + for (int i = 0; i < 5; ++i) + { + int rows = 25 + rand() % 300, cols = 25 + rand() % 300; + if (!compareToCpuTest(rows, cols, CV_32F, 1 + rand() % 5, 1 + 2 * (rand() % 4))) return; + if (!compareToCpuTest(rows, cols, CV_32F, 1 + rand() % 5, -1)) return; + if (!compareToCpuTest(rows, cols, CV_8U, 1 + rand() % 5, 1 + 2 * (rand() % 4))) return; + if (!compareToCpuTest(rows, cols, CV_8U, 1 + rand() % 5, -1)) return; + } + } + + bool compareToCpuTest(int rows, int cols, int depth, int blockSize, int apertureSize) + { + RNG rng; + cv::Mat src(rows, cols, depth); + if (depth == CV_32F) + rng.fill(src, RNG::UNIFORM, cv::Scalar(0), cv::Scalar(1)); + else if (depth == CV_8U) + rng.fill(src, RNG::UNIFORM, cv::Scalar(0), cv::Scalar(256)); + + double k = 0.1; + + cv::Mat dst_gold; + cv::gpu::GpuMat dst; + cv::Mat dsth; + int borderType; + + borderType = BORDER_REFLECT101; + cv::cornerHarris(src, dst_gold, blockSize, apertureSize, k, borderType); + cv::gpu::cornerHarris(cv::gpu::GpuMat(src), dst, blockSize, apertureSize, k, borderType); + + dsth = dst; + for (int i = 0; i < dst.rows; ++i) + { + for (int j = 0; j < dst.cols; ++j) + { + float a = dst_gold.at(i, j); + float b = dsth.at(i, j); + if (fabs(a - b) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "%d %d %f %f %d\n", i, j, a, b, apertureSize); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + }; + } + } + + borderType = BORDER_REPLICATE; + cv::cornerHarris(src, dst_gold, blockSize, apertureSize, k, borderType); + cv::gpu::cornerHarris(cv::gpu::GpuMat(src), dst, blockSize, apertureSize, k, borderType); + + dsth = dst; + for (int i = 0; i < dst.rows; ++i) + { + for (int j = 0; j < dst.cols; ++j) + { + float a = dst_gold.at(i, j); + float b = dsth.at(i, j); + if (fabs(a - b) > 1e-3f) + { + ts->printf(cvtest::TS::CONSOLE, "%d %d %f %f %d\n", i, j, a, b, apertureSize); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + }; + } + } + return true; + } +}; + +//////////////////////////////////////////////////////////////////////// +// Corner Min Eigen Val + +struct CV_GpuCornerMinEigenValTest: cvtest::BaseTest +{ + CV_GpuCornerMinEigenValTest() {} + + void run(int) + { + for (int i = 0; i < 3; ++i) + { + int rows = 25 + rand() % 300, cols = 25 + rand() % 300; + if (!compareToCpuTest(rows, cols, CV_32F, 1 + rand() % 5, -1)) return; + if (!compareToCpuTest(rows, cols, CV_32F, 1 + rand() % 5, 1 + 2 * (rand() % 4))) return; + if (!compareToCpuTest(rows, cols, CV_8U, 1 + rand() % 5, -1)) return; + if (!compareToCpuTest(rows, cols, CV_8U, 1 + rand() % 5, 1 + 2 * (rand() % 4))) return; + } + } + + bool compareToCpuTest(int rows, int cols, int depth, int blockSize, int apertureSize) + { + RNG rng; + cv::Mat src(rows, cols, depth); + if (depth == CV_32F) + rng.fill(src, RNG::UNIFORM, cv::Scalar(0), cv::Scalar(1)); + else if (depth == CV_8U) + rng.fill(src, RNG::UNIFORM, cv::Scalar(0), cv::Scalar(256)); + + cv::Mat dst_gold; + cv::gpu::GpuMat dst; + cv::Mat dsth; + + int borderType; + + borderType = BORDER_REFLECT101; + cv::cornerMinEigenVal(src, dst_gold, blockSize, apertureSize, borderType); + cv::gpu::cornerMinEigenVal(cv::gpu::GpuMat(src), dst, blockSize, apertureSize, borderType); + + dsth = dst; + for (int i = 0; i < dst.rows; ++i) + { + for (int j = 0; j < dst.cols; ++j) + { + float a = dst_gold.at(i, j); + float b = dsth.at(i, j); + if (fabs(a - b) > 1e-2f) + { + ts->printf(cvtest::TS::CONSOLE, "%d %d %f %f %d %d\n", i, j, a, b, apertureSize, blockSize); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + }; + } + } + + borderType = BORDER_REPLICATE; + cv::cornerMinEigenVal(src, dst_gold, blockSize, apertureSize, borderType); + cv::gpu::cornerMinEigenVal(cv::gpu::GpuMat(src), dst, blockSize, apertureSize, borderType); + + dsth = dst; + for (int i = 0; i < dst.rows; ++i) + { + for (int j = 0; j < dst.cols; ++j) + { + float a = dst_gold.at(i, j); + float b = dsth.at(i, j); + if (fabs(a - b) > 1e-2f) + { + ts->printf(cvtest::TS::CONSOLE, "%d %d %f %f %d %d\n", i, j, a, b, apertureSize, blockSize); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + }; + } + } + + return true; + } +}; + +struct CV_GpuColumnSumTest: cvtest::BaseTest +{ + CV_GpuColumnSumTest() {} + + void run(int) + { + int cols = 375; + int rows = 1072; + + Mat src(rows, cols, CV_32F); + RNG rng(1); + rng.fill(src, RNG::UNIFORM, Scalar(0), Scalar(1)); + + GpuMat d_dst; + columnSum(GpuMat(src), d_dst); + + Mat dst = d_dst; + for (int j = 0; j < src.cols; ++j) + { + float a = src.at(0, j); + float b = dst.at(0, j); + if (fabs(a - b) > 0.5f) + { + ts->printf(cvtest::TS::CONSOLE, "big diff at %d %d: %f %f\n", 0, j, a, b); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + for (int i = 1; i < src.rows; ++i) + { + for (int j = 0; j < src.cols; ++j) + { + float a = src.at(i, j) += src.at(i - 1, j); + float b = dst.at(i, j); + if (fabs(a - b) > 0.5f) + { + ts->printf(cvtest::TS::CONSOLE, "big diff at %d %d: %f %f\n", i, j, a, b); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + } + } +}; + +struct CV_GpuNormTest : cvtest::BaseTest +{ + CV_GpuNormTest() {} + + void run(int) + { + RNG rng(0); + + int rows = rng.uniform(1, 500); + int cols = rng.uniform(1, 500); + + for (int cn = 1; cn <= 4; ++cn) + { + test(NORM_L1, rows, cols, CV_8U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_L1, rows, cols, CV_8S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L1, rows, cols, CV_16U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_L1, rows, cols, CV_16S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L1, rows, cols, CV_32S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L1, rows, cols, CV_32F, cn, Scalar::all(0), Scalar::all(1)); + + test(NORM_L2, rows, cols, CV_8U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_L2, rows, cols, CV_8S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L2, rows, cols, CV_16U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_L2, rows, cols, CV_16S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L2, rows, cols, CV_32S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_L2, rows, cols, CV_32F, cn, Scalar::all(0), Scalar::all(1)); + + test(NORM_INF, rows, cols, CV_8U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_INF, rows, cols, CV_8S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_INF, rows, cols, CV_16U, cn, Scalar::all(0), Scalar::all(10)); + test(NORM_INF, rows, cols, CV_16S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_INF, rows, cols, CV_32S, cn, Scalar::all(-10), Scalar::all(10)); + test(NORM_INF, rows, cols, CV_32F, cn, Scalar::all(0), Scalar::all(1)); + } + } + + void gen(Mat& mat, int rows, int cols, int type, Scalar low, Scalar high) + { + mat.create(rows, cols, type); + RNG rng(0); + rng.fill(mat, RNG::UNIFORM, low, high); + } + + void test(int norm_type, int rows, int cols, int depth, int cn, Scalar low, Scalar high) + { + int type = CV_MAKE_TYPE(depth, cn); + + Mat src; + gen(src, rows, cols, type, low, high); + + double gold = norm(src, norm_type); + double mine = norm(GpuMat(src), norm_type); + + if (abs(gold - mine) > 1e-3) + { + ts->printf(cvtest::TS::CONSOLE, "failed test: gold=%f, mine=%f, norm_type=%d, rows=%d, " + "cols=%d, depth=%d, cn=%d\n", gold, mine, norm_type, rows, cols, depth, cn); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// reprojectImageTo3D +class CV_GpuReprojectImageTo3DTest : public cvtest::BaseTest +{ +public: + CV_GpuReprojectImageTo3DTest() {} + +protected: + void run(int) + { + Mat disp(320, 240, CV_8UC1); + + RNG& rng = ts->get_rng(); + rng.fill(disp, RNG::UNIFORM, Scalar(5), Scalar(30)); + + Mat Q(4, 4, CV_32FC1); + rng.fill(Q, RNG::UNIFORM, Scalar(0.1), Scalar(1)); + + Mat cpures; + GpuMat gpures; + + reprojectImageTo3D(disp, cpures, Q, false); + reprojectImageTo3D(GpuMat(disp), gpures, Q); + + Mat temp = gpures; + + for (int y = 0; y < cpures.rows; ++y) + { + const Vec3f* cpu_row = cpures.ptr(y); + const Vec4f* gpu_row = temp.ptr(y); + for (int x = 0; x < cpures.cols; ++x) + { + Vec3f a = cpu_row[x]; + Vec4f b = gpu_row[x]; + + if (fabs(a[0] - b[0]) > 1e-5 || fabs(a[1] - b[1]) > 1e-5 || fabs(a[2] - b[2]) > 1e-5) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + } + } +}; + +TEST(threshold, accuracy) { CV_GpuImageThresholdTest test; test.safe_run(); } +TEST(resize, accuracy) { CV_GpuNppImageResizeTest test; test.safe_run(); } +TEST(copyMakeBorder, accuracy) { CV_GpuNppImageCopyMakeBorderTest test; test.safe_run(); } +TEST(warpAffine, accuracy) { CV_GpuNppImageWarpAffineTest test; test.safe_run(); } +TEST(warpPerspective, accuracy) { CV_GpuNppImageWarpPerspectiveTest test; test.safe_run(); } +TEST(integral, accuracy) { CV_GpuNppImageIntegralTest test; test.safe_run(); } +//TEST(canny, accuracy) { CV_GpuNppImageCannyTest test; test.safe_run(); } +TEST(cvtColor, accuracy) { CV_GpuCvtColorTest test; test.safe_run(); } +TEST(histograms, accuracy) { CV_GpuHistogramsTest test; test.safe_run(); } +TEST(cornerHearris, accuracy) { CV_GpuCornerHarrisTest test; test.safe_run(); } +TEST(minEigen, accuracy) { CV_GpuCornerMinEigenValTest test; test.safe_run(); } +TEST(columnSum, accuracy) { CV_GpuColumnSumTest test; test.safe_run(); } +TEST(norm, accuracy) { CV_GpuNormTest test; test.safe_run(); } +TEST(reprojectImageTo3D, accuracy) { CV_GpuReprojectImageTo3DTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_main.cpp b/modules/gpu/test/test_main.cpp index d9d535109e..5ca54a39ec 100644 --- a/modules/gpu/test/test_main.cpp +++ b/modules/gpu/test/test_main.cpp @@ -5,4 +5,4 @@ CV_TEST_MAIN("gpu") // Run test with --gtest_catch_exceptions flag to avoid runtime errors in // the case when there is no GPU -// TODO Add other tests from tests/gpu folder +// TODO Add NVIDIA tests diff --git a/modules/gpu/test/test_match_template.cpp b/modules/gpu/test/test_match_template.cpp new file mode 100644 index 0000000000..b646723051 --- /dev/null +++ b/modules/gpu/test/test_match_template.cpp @@ -0,0 +1,295 @@ +/*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 GpuMaterials 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 bpied warranties, including, but not limited to, the bpied +// 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" +#include +#include + +//#define SHOW_TIME + +#ifdef SHOW_TIME +#include +#define F(x) x +#else +#define F(x) +#endif + +using namespace cv; +using namespace std; + +struct CV_GpuMatchTemplateTest: cvtest::BaseTest +{ + CV_GpuMatchTemplateTest() {} + + void run(int) + { + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + if (!double_ok) + { + // For sqrIntegral + ts->printf(cvtest::TS::CONSOLE, "\nCode and device double support is required (CC >= 1.3)"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + Mat image, templ; + Mat dst_gold; + gpu::GpuMat dst; + int n, m, h, w; + F(clock_t t;) + + RNG& rng = ts->get_rng(); + + for (int cn = 1; cn <= 4; ++cn) + { + F(ts->printf(cvtest::TS::CONSOLE, "cn: %d\n", cn);) + for (int i = 0; i <= 0; ++i) + { + n = rng.uniform(30, 100); + m = rng.uniform(30, 100); + h = rng.uniform(5, n - 1); + w = rng.uniform(5, m - 1); + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_SQDIFF); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_SQDIFF); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), 5 * h * w * 1e-4f, "SQDIFF 8U")) return; + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_SQDIFF_NORMED); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_SQDIFF_NORMED); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), h * w * 1e-5f, "SQDIFF_NOREMD 8U")) return; + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_CCORR); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCORR); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), 5 * h * w * cn * cn * 1e-5f, "CCORR 8U")) return; + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_CCORR_NORMED); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCORR_NORMED); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), h * w * 1e-6f, "CCORR_NORMED 8U")) return; + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_CCOEFF); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCOEFF); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), 5 * h * w * cn * cn * 1e-5f, "CCOEFF 8U")) return; + + gen(image, n, m, CV_8U, cn); + gen(templ, h, w, CV_8U, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_CCOEFF_NORMED); + F(cout << "depth: 8U cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCOEFF_NORMED); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), h * w * 1e-6f, "CCOEFF_NORMED 8U")) return; + + gen(image, n, m, CV_32F, cn); + gen(templ, h, w, CV_32F, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_SQDIFF); + F(cout << "depth: 32F cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_SQDIFF); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), 0.25f * h * w * 1e-5f, "SQDIFF 32F")) return; + + gen(image, n, m, CV_32F, cn); + gen(templ, h, w, CV_32F, cn); + F(t = clock();) + matchTemplate(image, templ, dst_gold, CV_TM_CCORR); + F(cout << "depth: 32F cn: " << cn << " n: " << n << " m: " << m << " w: " << w << " h: " << h << endl;) + F(cout << "cpu:" << clock() - t << endl;) + F(t = clock();) + gpu::matchTemplate(gpu::GpuMat(image), gpu::GpuMat(templ), dst, CV_TM_CCORR); + F(cout << "gpu_block: " << clock() - t << endl;) + if (!check(dst_gold, Mat(dst), 0.25f * h * w * 1e-5f, "CCORR 32F")) return; + } + } + } + + void gen(Mat& a, int rows, int cols, int depth, int cn) + { + RNG rng; + a.create(rows, cols, CV_MAKETYPE(depth, cn)); + if (depth == CV_8U) + rng.fill(a, RNG::UNIFORM, Scalar::all(1), Scalar::all(10)); + else if (depth == CV_32F) + rng.fill(a, RNG::UNIFORM, Scalar::all(0.001f), Scalar::all(1.f)); + } + + bool check(const Mat& a, const Mat& b, float max_err, const string& method="") + { + if (a.size() != b.size()) + { + ts->printf(cvtest::TS::CONSOLE, "bad size, method=%s\n", method.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + + //for (int i = 0; i < a.rows; ++i) + //{ + // for (int j = 0; j < a.cols; ++j) + // { + // float a_ = a.at(i, j); + // float b_ = b.at(i, j); + // if (fabs(a_ - b_) > max_err) + // { + // ts->printf(cvtest::TS::CONSOLE, "a=%f, b=%f, i=%d, j=%d\n", a_, b_, i, j); + // cin.get(); + // } + // } + //} + + float err = (float)norm(a, b, NORM_INF); + if (err > max_err) + { + ts->printf(cvtest::TS::CONSOLE, "bad accuracy: %f, method=%s\n", err, method.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return false; + } + + return true; + } +}; + +TEST(matchTemplate, accuracy) { CV_GpuMatchTemplateTest test; test.safe_run(); } + +struct CV_GpuMatchTemplateFindPatternInBlackTest: cvtest::BaseTest +{ + CV_GpuMatchTemplateFindPatternInBlackTest() {} + + void run(int) + { + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + if (!double_ok) + { + // For sqrIntegral + ts->printf(cvtest::TS::CONSOLE, "\nCode and device double support is required (CC >= 1.3)"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + Mat image = imread(std::string(ts->get_data_path()) + "matchtemplate/black.png"); + if (image.empty()) + { + ts->printf(cvtest::TS::CONSOLE, "can't open file '%s'", (std::string(ts->get_data_path()) + + "matchtemplate/black.png").c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + Mat pattern = imread(std::string(ts->get_data_path()) + "matchtemplate/cat.png"); + if (pattern.empty()) + { + ts->printf(cvtest::TS::CONSOLE, "can't open file '%s'", (std::string(ts->get_data_path()) + + "matchtemplate/cat.png").c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + gpu::GpuMat d_image(image); + gpu::GpuMat d_pattern(pattern); + gpu::GpuMat d_result; + + double maxValue; + Point maxLoc; + Point maxLocGold(284, 12); + + gpu::matchTemplate(d_image, d_pattern, d_result, CV_TM_CCOEFF_NORMED); + gpu::minMaxLoc(d_result, NULL, &maxValue, NULL, &maxLoc ); + if (maxLoc != maxLocGold) + { + ts->printf(cvtest::TS::CONSOLE, "bad match (CV_TM_CCOEFF_NORMED): %d %d, must be at: %d %d", + maxLoc.x, maxLoc.y, maxLocGold.x, maxLocGold.y); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + gpu::matchTemplate(d_image, d_pattern, d_result, CV_TM_CCORR_NORMED); + gpu::minMaxLoc(d_result, NULL, &maxValue, NULL, &maxLoc ); + if (maxLoc != maxLocGold) + { + ts->printf(cvtest::TS::CONSOLE, "bad match (CV_TM_CCORR_NORMED): %d %d, must be at: %d %d", + maxLoc.x, maxLoc.y, maxLocGold.x, maxLocGold.y); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } +}; + +TEST(matchTemplate, find_pattern_in_black) { CV_GpuMatchTemplateFindPatternInBlackTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_meanshift.cpp b/modules/gpu/test/test_meanshift.cpp new file mode 100644 index 0000000000..e58bd15549 --- /dev/null +++ b/modules/gpu/test/test_meanshift.cpp @@ -0,0 +1,237 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" +#include +#include + +using namespace cv; +using namespace cv::gpu; + + +struct CV_GpuMeanShiftTest : public cvtest::BaseTest +{ + CV_GpuMeanShiftTest() {} + + void run(int) + { + bool cc12_ok = TargetArchs::builtWith(FEATURE_SET_COMPUTE_12) && DeviceInfo().supports(FEATURE_SET_COMPUTE_12); + if (!cc12_ok) + { + ts->printf(cvtest::TS::CONSOLE, "\nCompute capability 1.2 is required"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + int spatialRad = 30; + int colorRad = 30; + + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "meanshift/cones.png"); + cv::Mat img_template; + + if (cv::gpu::TargetArchs::builtWith(cv::gpu::FEATURE_SET_COMPUTE_20) && + cv::gpu::DeviceInfo().supports(cv::gpu::FEATURE_SET_COMPUTE_20)) + img_template = cv::imread(std::string(ts->get_data_path()) + "meanshift/con_result.png"); + else + img_template = cv::imread(std::string(ts->get_data_path()) + "meanshift/con_result_CC1X.png"); + + if (img.empty() || img_template.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + cv::Mat rgba; + cvtColor(img, rgba, CV_BGR2BGRA); + + + cv::gpu::GpuMat res; + cv::gpu::meanShiftFiltering( cv::gpu::GpuMat(rgba), res, spatialRad, colorRad ); + + if (res.type() != CV_8UC4) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + cv::Mat result; + res.download(result); + + uchar maxDiff = 0; + for (int j = 0; j < result.rows; ++j) + { + const uchar* res_line = result.ptr(j); + const uchar* ref_line = img_template.ptr(j); + + for (int i = 0; i < result.cols; ++i) + { + for (int k = 0; k < 3; ++k) + { + const uchar& ch1 = res_line[result.channels()*i + k]; + const uchar& ch2 = ref_line[img_template.channels()*i + k]; + uchar diff = static_cast(abs(ch1 - ch2)); + if (maxDiff < diff) + maxDiff = diff; + } + } + } + if (maxDiff > 0) + { + ts->printf(cvtest::TS::LOG, "\nMeanShift maxDiff = %d\n", maxDiff); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + ts->set_failed_test_info(cvtest::TS::OK); + } + +}; + +///////////////////////////////////////////////////////////////////////////// +/////////////////// tests registration ///////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +CV_GpuMeanShiftTest CV_GpuMeanShift_test; + +struct CV_GpuMeanShiftProcTest : public cvtest::BaseTest +{ + CV_GpuMeanShiftProcTest() {} + + void run(int) + { + bool cc12_ok = TargetArchs::builtWith(FEATURE_SET_COMPUTE_12) && DeviceInfo().supports(FEATURE_SET_COMPUTE_12); + if (!cc12_ok) + { + ts->printf(cvtest::TS::CONSOLE, "\nCompute capability 1.2 is required"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + int spatialRad = 30; + int colorRad = 30; + + cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "meanshift/cones.png"); + + if (img.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + cv::Mat rgba; + cvtColor(img, rgba, CV_BGR2BGRA); + + cv::gpu::GpuMat h_rmap_filtered; + cv::gpu::meanShiftFiltering( cv::gpu::GpuMat(rgba), h_rmap_filtered, spatialRad, colorRad ); + + cv::gpu::GpuMat d_rmap; + cv::gpu::GpuMat d_spmap; + cv::gpu::meanShiftProc( cv::gpu::GpuMat(rgba), d_rmap, d_spmap, spatialRad, colorRad ); + + if (d_rmap.type() != CV_8UC4) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + + cv::Mat rmap_filtered; + h_rmap_filtered.download(rmap_filtered); + + cv::Mat rmap; + d_rmap.download(rmap); + + uchar maxDiff = 0; + for (int j = 0; j < rmap_filtered.rows; ++j) + { + const uchar* res_line = rmap_filtered.ptr(j); + const uchar* ref_line = rmap.ptr(j); + + for (int i = 0; i < rmap_filtered.cols; ++i) + { + for (int k = 0; k < 3; ++k) + { + const uchar& ch1 = res_line[rmap_filtered.channels()*i + k]; + const uchar& ch2 = ref_line[rmap.channels()*i + k]; + uchar diff = static_cast(abs(ch1 - ch2)); + if (maxDiff < diff) + maxDiff = diff; + } + } + } + if (maxDiff > 0) + { + ts->printf(cvtest::TS::LOG, "\nMeanShiftProc maxDiff = %d\n", maxDiff); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + cv::Mat spmap; + d_spmap.download(spmap); + + cv::Mat spmap_template; + cv::FileStorage fs; + + if (cv::gpu::TargetArchs::builtWith(cv::gpu::FEATURE_SET_COMPUTE_20) && + cv::gpu::DeviceInfo().supports(cv::gpu::FEATURE_SET_COMPUTE_20)) + fs.open(std::string(ts->get_data_path()) + "meanshift/spmap.yaml", cv::FileStorage::READ); + else + fs.open(std::string(ts->get_data_path()) + "meanshift/spmap_CC1X.yaml", cv::FileStorage::READ); + fs["spmap"] >> spmap_template; + + for (int y = 0; y < spmap.rows; ++y) { + for (int x = 0; x < spmap.cols; ++x) { + cv::Point_ expected = spmap_template.at >(y, x); + cv::Point_ actual = spmap.at >(y, x); + int diff = (expected - actual).dot(expected - actual); + if (actual != expected) { + ts->printf(cvtest::TS::LOG, "\nMeanShiftProc SpMap is bad, diff=%d\n", diff); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + } + } + + ts->set_failed_test_info(cvtest::TS::OK); + } + +}; + +TEST(meanShiftProc, accuracy) { CV_GpuMeanShiftProcTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_mssegmentation.cpp b/modules/gpu/test/test_mssegmentation.cpp new file mode 100644 index 0000000000..b64914704b --- /dev/null +++ b/modules/gpu/test/test_mssegmentation.cpp @@ -0,0 +1,122 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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 +#include +#include +#include "test_precomp.hpp" +using namespace cv; +using namespace cv::gpu; +using namespace std; + +struct CV_GpuMeanShiftSegmentationTest : public cvtest::BaseTest { + CV_GpuMeanShiftSegmentationTest() {} + + void run(int) + { + bool cc12_ok = TargetArchs::builtWith(FEATURE_SET_COMPUTE_12) && DeviceInfo().supports(FEATURE_SET_COMPUTE_12); + if (!cc12_ok) + { + ts->printf(cvtest::TS::CONSOLE, "\nCompute capability 1.2 is required"); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + Mat img_rgb = imread(string(ts->get_data_path()) + "meanshift/cones.png"); + if (img_rgb.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + Mat img; + cvtColor(img_rgb, img, CV_BGR2BGRA); + + + for (int minsize = 0; minsize < 2000; minsize = (minsize + 1) * 4) + { + stringstream path; + path << ts->get_data_path() << "meanshift/cones_segmented_sp10_sr10_minsize" << minsize; + if (TargetArchs::builtWith(FEATURE_SET_COMPUTE_20) && DeviceInfo().supports(FEATURE_SET_COMPUTE_20)) + path << ".png"; + else + path << "_CC1X.png"; + + Mat dst; + meanShiftSegmentation((GpuMat)img, dst, 10, 10, minsize); + Mat dst_rgb; + cvtColor(dst, dst_rgb, CV_BGRA2BGR); + + //imwrite(path.str(), dst_rgb); + Mat dst_ref = imread(path.str()); + if (dst_ref.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + if (CheckSimilarity(dst_rgb, dst_ref, 1e-3f) != cvtest::TS::OK) + { + ts->printf(cvtest::TS::LOG, "\ndiffers from image *minsize%d.png\n", minsize); + ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); + } + } + + ts->set_failed_test_info(cvtest::TS::OK); + } + + int CheckSimilarity(const Mat& m1, const Mat& m2, float max_err) + { + Mat diff; + cv::matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED); + + float err = abs(diff.at(0, 0) - 1.f); + + if (err > max_err) + return cvtest::TS::FAIL_INVALID_OUTPUT; + + return cvtest::TS::OK; + } + + +}; + + +TEST(meanShiftSegmentation, regression) { CV_GpuMeanShiftSegmentationTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_operator_async_call.cpp b/modules/gpu/test/test_operator_async_call.cpp new file mode 100644 index 0000000000..34459298ad --- /dev/null +++ b/modules/gpu/test/test_operator_async_call.cpp @@ -0,0 +1,84 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +using namespace std; +using namespace cv; +using namespace cv::gpu; + +struct CV_AsyncGpuMatTest : public cvtest::BaseTest +{ + CV_AsyncGpuMatTest() {} + + void run(int) + { + CudaMem src(Mat::zeros(100, 100, CV_8UC1)); + + GpuMat gpusrc; + GpuMat gpudst0, gpudst1(100, 100, CV_8UC1); + + CudaMem cpudst0; + CudaMem cpudst1; + + Stream stream0, stream1; + + stream0.enqueueUpload(src, gpusrc); + bitwise_not(gpusrc, gpudst0, GpuMat(), stream0); + stream0.enqueueDownload(gpudst0, cpudst0); + + stream1.enqueueMemSet(gpudst1, Scalar::all(128)); + stream1.enqueueDownload(gpudst1, cpudst1); + + stream0.waitForCompletion(); + stream1.waitForCompletion(); + + Mat cpu_gold0(100, 100, CV_8UC1, Scalar::all(255)); + Mat cpu_gold1(100, 100, CV_8UC1, Scalar::all(128)); + + if (norm(cpudst0, cpu_gold0, NORM_INF) > 0 || norm(cpudst1, cpu_gold1, NORM_INF) > 0) + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + else + ts->set_failed_test_info(cvtest::TS::OK); + } +}; + +TEST(GpuMat, async) { CV_AsyncGpuMatTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_operator_convert_to.cpp b/modules/gpu/test/test_operator_convert_to.cpp new file mode 100644 index 0000000000..b604de33e1 --- /dev/null +++ b/modules/gpu/test/test_operator_convert_to.cpp @@ -0,0 +1,110 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +#include +#include +#include + +using namespace cv; +using namespace std; +using namespace gpu; + +class CV_GpuMatOpConvertToTest : public cvtest::BaseTest +{ + public: + CV_GpuMatOpConvertToTest() {} + ~CV_GpuMatOpConvertToTest() {} + + protected: + void run(int); +}; + +void CV_GpuMatOpConvertToTest::run(int /* start_from */) +{ + const Size img_size(67, 35); + + const char* types_str[] = {"CV_8U", "CV_8S", "CV_16U", "CV_16S", "CV_32S", "CV_32F", "CV_64F"}; + + bool passed = true; + int lastType = CV_32F; + + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + lastType = CV_64F; + + for (int i = 0; i <= lastType && passed; ++i) + { + for (int j = 0; j <= lastType && passed; ++j) + { + for (int c = 1; c < 5 && passed; ++c) + { + const int src_type = CV_MAKETYPE(i, c); + const int dst_type = j; + + cv::RNG& rng = ts->get_rng(); + + Mat cpumatsrc(img_size, src_type); + rng.fill(cpumatsrc, RNG::UNIFORM, Scalar::all(0), Scalar::all(300)); + + GpuMat gpumatsrc(cpumatsrc); + Mat cpumatdst; + GpuMat gpumatdst; + + cpumatsrc.convertTo(cpumatdst, dst_type, 0.5, 3.0); + gpumatsrc.convertTo(gpumatdst, dst_type, 0.5, 3.0); + + double r = norm(cpumatdst, gpumatdst, NORM_INF); + if (r > 1) + { + ts->printf(cvtest::TS::LOG, + "\nFAILED: SRC_TYPE=%sC%d DST_TYPE=%s NORM = %f\n", + types_str[i], c, types_str[j], r); + passed = false; + } + } + } + } + + ts->set_failed_test_info(passed ? cvtest::TS::OK : cvtest::TS::FAIL_GENERIC); +} + +TEST(GpuMat_convertTo, accuracy) { CV_GpuMatOpConvertToTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_operator_copy_to.cpp b/modules/gpu/test/test_operator_copy_to.cpp new file mode 100644 index 0000000000..fccf0ab83a --- /dev/null +++ b/modules/gpu/test/test_operator_copy_to.cpp @@ -0,0 +1,145 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" +#include +#include +#include +#include // for cout << setw() + +using namespace cv; +using namespace std; +using namespace gpu; + +class CV_GpuMatOpCopyToTest : public cvtest::BaseTest +{ + public: + CV_GpuMatOpCopyToTest() + { + rows = 234; + cols = 123; + } + ~CV_GpuMatOpCopyToTest() {} + + protected: + void run(int); + template + void print_mat(const T & mat, const std::string & name) const; + bool compare_matrix(cv::Mat & cpumat, gpu::GpuMat & gpumat); + + private: + int rows; + int cols; +}; + +template +void CV_GpuMatOpCopyToTest::print_mat(const T & mat, const std::string & name) const { cv::imshow(name, mat); } + +bool CV_GpuMatOpCopyToTest::compare_matrix(cv::Mat & cpumat, gpu::GpuMat & gpumat) +{ + Mat cmat(cpumat.size(), cpumat.type(), Scalar::all(0)); + GpuMat gmat(cmat); + + Mat cpumask(cpumat.size(), CV_8U); + + cv::RNG& rng = ts->get_rng(); + + rng.fill(cpumask, RNG::NORMAL, Scalar::all(0), Scalar::all(127)); + + threshold(cpumask, cpumask, 0, 127, THRESH_BINARY); + + GpuMat gpumask(cpumask); + + //int64 time = getTickCount(); + cpumat.copyTo(cmat, cpumask); + //int64 time1 = getTickCount(); + gpumat.copyTo(gmat, gpumask); + //int64 time2 = getTickCount(); + + //std::cout << "\ntime cpu: " << std::fixed << std::setprecision(12) << 1.0 / double((time1 - time) / (double)getTickFrequency()); + //std::cout << "\ntime gpu: " << std::fixed << std::setprecision(12) << 1.0 / double((time2 - time1) / (double)getTickFrequency()); + //std::cout << "\n"; + +#ifdef PRINT_MATRIX + print_mat(cmat, "cpu mat"); + print_mat(gmat, "gpu mat"); + print_mat(cpumask, "cpu mask"); + print_mat(gpumask, "gpu mask"); + cv::waitKey(0); +#endif + + double ret = norm(cmat, gmat); + + if (ret < 1.0) + return true; + else + { + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return false; + } +} + +void CV_GpuMatOpCopyToTest::run( int /* start_from */) +{ + bool is_test_good = true; + + int lastType = CV_32F; + + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + lastType = CV_64F; + + for (int i = 0 ; i <= lastType; i++) + { + Mat cpumat(rows, cols, i); + cpumat.setTo(Scalar::all(127)); + + GpuMat gpumat(cpumat); + + is_test_good &= compare_matrix(cpumat, gpumat); + } + + if (is_test_good == true) + ts->set_failed_test_info(cvtest::TS::OK); + else + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); +} + +TEST(GpuMat_copyTo, accuracy) { CV_GpuMatOpCopyToTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_operator_set_to.cpp b/modules/gpu/test/test_operator_set_to.cpp new file mode 100644 index 0000000000..db0908cfa3 --- /dev/null +++ b/modules/gpu/test/test_operator_set_to.cpp @@ -0,0 +1,123 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +using namespace cv; +using namespace std; +using namespace gpu; + +class CV_GpuMatOpSetToTest : public cvtest::BaseTest +{ +public: + CV_GpuMatOpSetToTest(); + ~CV_GpuMatOpSetToTest() {} + +protected: + void run(int); + + bool testSetTo(cv::Mat& cpumat, gpu::GpuMat& gpumat, const cv::Mat& cpumask = cv::Mat(), const cv::gpu::GpuMat& gpumask = cv::gpu::GpuMat()); + +private: + int rows; + int cols; + Scalar s; +}; + +CV_GpuMatOpSetToTest::CV_GpuMatOpSetToTest() +{ + rows = 35; + cols = 67; + + s.val[0] = 127.0; + s.val[1] = 127.0; + s.val[2] = 127.0; + s.val[3] = 127.0; +} + +bool CV_GpuMatOpSetToTest::testSetTo(cv::Mat& cpumat, gpu::GpuMat& gpumat, const cv::Mat& cpumask, const cv::gpu::GpuMat& gpumask) +{ + cpumat.setTo(s, cpumask); + gpumat.setTo(s, gpumask); + + double ret = norm(cpumat, gpumat, NORM_INF); + + if (ret < std::numeric_limits::epsilon()) + return true; + else + { + ts->printf(cvtest::TS::LOG, "\nNorm: %f\n", ret); + return false; + } +} + +void CV_GpuMatOpSetToTest::run( int /* start_from */) +{ + bool is_test_good = true; + + cv::Mat cpumask(rows, cols, CV_8UC1); + cv::RNG& rng = ts->get_rng(); + rng.fill(cpumask, RNG::UNIFORM, cv::Scalar::all(0.0), cv::Scalar(1.5)); + cv::gpu::GpuMat gpumask(cpumask); + + int lastType = CV_32F; + + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + lastType = CV_64F; + + for (int i = 0; i <= lastType; i++) + { + for (int cn = 1; cn <= 4; ++cn) + { + int mat_type = CV_MAKETYPE(i, cn); + Mat cpumat(rows, cols, mat_type, Scalar::all(0)); + GpuMat gpumat(cpumat); + is_test_good &= testSetTo(cpumat, gpumat, cpumask, gpumask); + } + } + + if (is_test_good == true) + ts->set_failed_test_info(cvtest::TS::OK); + else + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); +} + +TEST(GpuMat_setTo, accuracy) { CV_GpuMatOpSetToTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_precomp.hpp b/modules/gpu/test/test_precomp.hpp index aac57335a5..9b048fc81e 100644 --- a/modules/gpu/test/test_precomp.hpp +++ b/modules/gpu/test/test_precomp.hpp @@ -1,8 +1,11 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ +#include +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/calib3d/calib3d.hpp" #include "opencv2/ts/ts.hpp" #include "opencv2/gpu/gpu.hpp" -#include "opencv2/highgui/highgui.hpp" #endif diff --git a/modules/gpu/test/test_split_merge.cpp b/modules/gpu/test/test_split_merge.cpp new file mode 100644 index 0000000000..ca5f4a9727 --- /dev/null +++ b/modules/gpu/test/test_split_merge.cpp @@ -0,0 +1,312 @@ +/*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 GpuMaterials 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 bpied warranties, including, but not limited to, the bpied +// 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" + +using namespace std; +using namespace cv; + +//////////////////////////////////////////////////////////////////////////////// +// Merge + +struct CV_MergeTest : public cvtest::BaseTest +{ + void can_merge(size_t rows, size_t cols); + void can_merge_submatrixes(size_t rows, size_t cols); + void run(int); +}; + + +void CV_MergeTest::can_merge(size_t rows, size_t cols) +{ + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + size_t depth_end = double_ok ? CV_64F : CV_32F; + + for (size_t num_channels = 1; num_channels <= 4; ++num_channels) + for (size_t depth = CV_8U; depth <= depth_end; ++depth) + { + vector src; + for (size_t i = 0; i < num_channels; ++i) + src.push_back(Mat(rows, cols, depth, Scalar::all(static_cast(i)))); + + Mat dst(rows, cols, CV_MAKETYPE(depth, num_channels)); + + cv::merge(src, dst); + + vector dev_src; + for (size_t i = 0; i < num_channels; ++i) + dev_src.push_back(gpu::GpuMat(src[i])); + + gpu::GpuMat dev_dst(rows, cols, CV_MAKETYPE(depth, num_channels)); + cv::gpu::merge(dev_src, dev_dst); + + Mat host_dst = dev_dst; + + double err = norm(dst, host_dst, NORM_INF); + + if (err > 1e-3) + { + //ts->printf(cvtest::TS::CONSOLE, "\nNorm: %f\n", err); + //ts->printf(cvtest::TS::CONSOLE, "Depth: %d\n", depth); + //ts->printf(cvtest::TS::CONSOLE, "Rows: %d\n", rows); + //ts->printf(cvtest::TS::CONSOLE, "Cols: %d\n", cols); + //ts->printf(cvtest::TS::CONSOLE, "NumChannels: %d\n", num_channels); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } +} + + +void CV_MergeTest::can_merge_submatrixes(size_t rows, size_t cols) +{ + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + size_t depth_end = double_ok ? CV_64F : CV_32F; + + for (size_t num_channels = 1; num_channels <= 4; ++num_channels) + for (size_t depth = CV_8U; depth <= depth_end; ++depth) + { + vector src; + for (size_t i = 0; i < num_channels; ++i) + { + Mat m(rows * 2, cols * 2, depth, Scalar::all(static_cast(i))); + src.push_back(m(Range(rows / 2, rows / 2 + rows), Range(cols / 2, cols / 2 + cols))); + } + + Mat dst(rows, cols, CV_MAKETYPE(depth, num_channels)); + + cv::merge(src, dst); + + vector dev_src; + for (size_t i = 0; i < num_channels; ++i) + dev_src.push_back(gpu::GpuMat(src[i])); + + gpu::GpuMat dev_dst(rows, cols, CV_MAKETYPE(depth, num_channels)); + cv::gpu::merge(dev_src, dev_dst); + + Mat host_dst = dev_dst; + + double err = norm(dst, host_dst, NORM_INF); + + if (err > 1e-3) + { + //ts->printf(cvtest::TS::CONSOLE, "\nNorm: %f\n", err); + //ts->printf(cvtest::TS::CONSOLE, "Depth: %d\n", depth); + //ts->printf(cvtest::TS::CONSOLE, "Rows: %d\n", rows); + //ts->printf(cvtest::TS::CONSOLE, "Cols: %d\n", cols); + //ts->printf(cvtest::TS::CONSOLE, "NumChannels: %d\n", num_channels); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } +} + +void CV_MergeTest::run(int) +{ + can_merge(1, 1); + can_merge(1, 7); + can_merge(53, 7); + can_merge_submatrixes(1, 1); + can_merge_submatrixes(1, 7); + can_merge_submatrixes(53, 7); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Split + +struct CV_SplitTest : public cvtest::BaseTest +{ + void can_split(size_t rows, size_t cols); + void can_split_submatrix(size_t rows, size_t cols); + void run(int); +}; + +void CV_SplitTest::can_split(size_t rows, size_t cols) +{ + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + size_t depth_end = double_ok ? CV_64F : CV_32F; + + for (size_t num_channels = 1; num_channels <= 4; ++num_channels) + for (size_t depth = CV_8U; depth <= depth_end; ++depth) + { + Mat src(rows, cols, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0)); + vector dst; + cv::split(src, dst); + + gpu::GpuMat dev_src(src); + vector dev_dst; + cv::gpu::split(dev_src, dev_dst); + + if (dev_dst.size() != dst.size()) + { + ts->printf(cvtest::TS::CONSOLE, "Bad output sizes"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + + for (size_t i = 0; i < num_channels; ++i) + { + Mat host_dst = dev_dst[i]; + double err = norm(dst[i], host_dst, NORM_INF); + + if (err > 1e-3) + { + //ts->printf(cvtest::TS::CONSOLE, "\nNorm: %f\n", err); + //ts->printf(cvtest::TS::CONSOLE, "Depth: %d\n", depth); + //ts->printf(cvtest::TS::CONSOLE, "Rows: %d\n", rows); + //ts->printf(cvtest::TS::CONSOLE, "Cols: %d\n", cols); + //ts->printf(cvtest::TS::CONSOLE, "NumChannels: %d\n", num_channels); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + } +} + +void CV_SplitTest::can_split_submatrix(size_t rows, size_t cols) +{ + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + size_t depth_end = double_ok ? CV_64F : CV_32F; + + for (size_t num_channels = 1; num_channels <= 4; ++num_channels) + for (size_t depth = CV_8U; depth <= depth_end; ++depth) + { + Mat src_data(rows * 2, cols * 2, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0)); + Mat src(src_data(Range(rows / 2, rows / 2 + rows), Range(cols / 2, cols / 2 + cols))); + vector dst; + cv::split(src, dst); + + gpu::GpuMat dev_src(src); + vector dev_dst; + cv::gpu::split(dev_src, dev_dst); + + if (dev_dst.size() != dst.size()) + { + ts->printf(cvtest::TS::CONSOLE, "Bad output sizes"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + + for (size_t i = 0; i < num_channels; ++i) + { + Mat host_dst = dev_dst[i]; + double err = norm(dst[i], host_dst, NORM_INF); + + if (err > 1e-3) + { + //ts->printf(cvtest::TS::CONSOLE, "\nNorm: %f\n", err); + //ts->printf(cvtest::TS::CONSOLE, "Depth: %d\n", depth); + //ts->printf(cvtest::TS::CONSOLE, "Rows: %d\n", rows); + //ts->printf(cvtest::TS::CONSOLE, "Cols: %d\n", cols); + //ts->printf(cvtest::TS::CONSOLE, "NumChannels: %d\n", num_channels); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + } +} + +void CV_SplitTest::run(int) +{ + can_split(1, 1); + can_split(1, 7); + can_split(7, 53); + can_split_submatrix(1, 1); + can_split_submatrix(1, 7); + can_split_submatrix(7, 53); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Split and merge + +struct CV_SplitMergeTest : public cvtest::BaseTest +{ + void can_split_merge(size_t rows, size_t cols); + void run(int); +}; + +void CV_SplitMergeTest::can_split_merge(size_t rows, size_t cols) { + bool double_ok = gpu::TargetArchs::builtWith(gpu::NATIVE_DOUBLE) && + gpu::DeviceInfo().supports(gpu::NATIVE_DOUBLE); + size_t depth_end = double_ok ? CV_64F : CV_32F; + + for (size_t num_channels = 1; num_channels <= 4; ++num_channels) + for (size_t depth = CV_8U; depth <= depth_end; ++depth) + { + Mat orig(rows, cols, CV_MAKETYPE(depth, num_channels), Scalar(1.0, 2.0, 3.0, 4.0)); + gpu::GpuMat dev_orig(orig); + vector dev_vec; + cv::gpu::split(dev_orig, dev_vec); + + gpu::GpuMat dev_final(rows, cols, CV_MAKETYPE(depth, num_channels)); + cv::gpu::merge(dev_vec, dev_final); + + double err = cv::norm((Mat)dev_orig, (Mat)dev_final, NORM_INF); + if (err > 1e-3) + { + //ts->printf(cvtest::TS::CONSOLE, "\nNorm: %f\n", err); + //ts->printf(cvtest::TS::CONSOLE, "Depth: %d\n", depth); + //ts->printf(cvtest::TS::CONSOLE, "Rows: %d\n", rows); + //ts->printf(cvtest::TS::CONSOLE, "Cols: %d\n", cols); + //ts->printf(cvtest::TS::CONSOLE, "NumChannels: %d\n", num_channels); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } +} + + +void CV_SplitMergeTest::run(int) +{ + can_split_merge(1, 1); + can_split_merge(1, 7); + can_split_merge(7, 53); +} + + +TEST(merge, accuracy) { CV_MergeTest test; test.safe_run(); } +TEST(split, accuracy) { CV_SplitTest test; test.safe_run(); } +TEST(split, merge_consistency) { CV_SplitMergeTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_stereo_bm.cpp b/modules/gpu/test/test_stereo_bm.cpp new file mode 100644 index 0000000000..da925ca16b --- /dev/null +++ b/modules/gpu/test/test_stereo_bm.cpp @@ -0,0 +1,131 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +using namespace cv; +using namespace cv::gpu; + +struct CV_GpuStereoBMTest : public cvtest::BaseTest +{ + void run_stress() + { + RNG rng; + + for(int i = 0; i < 10; ++i) + { + int winSize = cvRound(rng.uniform(2, 11)) * 2 + 1; + + for(int j = 0; j < 10; ++j) + { + int ndisp = cvRound(rng.uniform(5, 32)) * 8; + + for(int s = 0; s < 10; ++s) + { + int w = cvRound(rng.uniform(1024, 2048)); + int h = cvRound(rng.uniform(768, 1152)); + + for(int p = 0; p < 2; ++p) + { + //int winSize = winsz[i]; + //int disp = disps[j]; + Size imgSize(w, h);//res[s]; + int preset = p; + + printf("Preset = %d, nidsp = %d, winsz = %d, width = %d, height = %d\n", p, ndisp, winSize, imgSize.width, imgSize.height); + + GpuMat l(imgSize, CV_8U); + GpuMat r(imgSize, CV_8U); + + GpuMat disparity; + StereoBM_GPU bm(preset, ndisp, winSize); + bm(l, r, disparity); + + + } + } + } + } + } + + void run(int ) + { + /*run_stress(); + return;*/ + + cv::Mat img_l = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-L.png", 0); + cv::Mat img_r = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-R.png", 0); + cv::Mat img_reference = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-disp.png", 0); + + if (img_l.empty() || img_r.empty() || img_reference.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + cv::gpu::GpuMat disp; + cv::gpu::StereoBM_GPU bm(0, 128, 19); + bm(cv::gpu::GpuMat(img_l), cv::gpu::GpuMat(img_r), disp); + + disp.convertTo(disp, img_reference.type()); + double norm = cv::norm(disp, img_reference, cv::NORM_INF); + + //cv::imwrite(std::string(ts->get_data_path()) + "stereobm/aloe-disp.png", disp); + + /*cv::imshow("disp", disp); + cv::imshow("img_reference", img_reference); + + cv::Mat diff = (cv::Mat)disp - (cv::Mat)img_reference; + cv::imshow("diff", diff); + cv::waitKey();*/ + + if (norm >= 100) + { + ts->printf(cvtest::TS::LOG, "\nStereoBM norm = %f\n", norm); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + ts->set_failed_test_info(cvtest::TS::OK); + } +}; + +TEST(StereoBM, regression) { CV_GpuStereoBMTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_stereo_bm_async.cpp b/modules/gpu/test/test_stereo_bm_async.cpp new file mode 100644 index 0000000000..89afab884c --- /dev/null +++ b/modules/gpu/test/test_stereo_bm_async.cpp @@ -0,0 +1,86 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +using namespace cv; +using namespace std; + +struct CV_AsyncStereoBMTest : public cvtest::BaseTest +{ + void run( int /* start_from */) + { + cv::Mat img_l = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-L.png", 0); + cv::Mat img_r = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-R.png", 0); + cv::Mat img_reference = cv::imread(std::string(ts->get_data_path()) + "stereobm/aloe-disp.png", 0); + + if (img_l.empty() || img_r.empty() || img_reference.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + cv::gpu::GpuMat disp; + cv::gpu::StereoBM_GPU bm(0, 128, 19); + + cv::gpu::Stream stream; + + for (size_t i = 0; i < 50; i++) + { + bm(cv::gpu::GpuMat(img_l), cv::gpu::GpuMat(img_r), disp, stream); + } + + stream.waitForCompletion(); + disp.convertTo(disp, img_reference.type()); + double norm = cv::norm(disp, img_reference, cv::NORM_INF); + + if (norm >= 100) + { + ts->printf(cvtest::TS::LOG, "\nStereoBM norm = %f\n", norm); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + ts->set_failed_test_info(cvtest::TS::OK); + } +}; + +TEST(StereoBM, async) { CV_AsyncStereoBMTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_stereo_bp.cpp b/modules/gpu/test/test_stereo_bp.cpp index a3b1780bd7..cf277c2b91 100644 --- a/modules/gpu/test/test_stereo_bp.cpp +++ b/modules/gpu/test/test_stereo_bp.cpp @@ -79,4 +79,4 @@ struct CV_GpuStereoBPTest : public cvtest::BaseTest } }; -TEST(StereoBP, StereoBP) { CV_GpuStereoBPTest test; test.safe_run(); } \ No newline at end of file +TEST(StereoBP, regression) { CV_GpuStereoBPTest test; test.safe_run(); } diff --git a/modules/gpu/test/test_stereo_csbp.cpp b/modules/gpu/test/test_stereo_csbp.cpp new file mode 100644 index 0000000000..c2ff012a6a --- /dev/null +++ b/modules/gpu/test/test_stereo_csbp.cpp @@ -0,0 +1,82 @@ +/*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. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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" + +struct CV_GpuStereoCSBPTest : public cvtest::BaseTest +{ + void run(int ) + { + cv::Mat img_l = cv::imread(std::string(ts->get_data_path()) + "csstereobp/aloe-L.png"); + cv::Mat img_r = cv::imread(std::string(ts->get_data_path()) + "csstereobp/aloe-R.png"); + cv::Mat img_template = cv::imread(std::string(ts->get_data_path()) + "csstereobp/aloe-disp.png", 0); + + if (img_l.empty() || img_r.empty() || img_template.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + {cv::Mat temp; cv::cvtColor(img_l, temp, CV_BGR2BGRA); cv::swap(temp, img_l);} + {cv::Mat temp; cv::cvtColor(img_r, temp, CV_BGR2BGRA); cv::swap(temp, img_r);} + + cv::gpu::GpuMat disp; + cv::gpu::StereoConstantSpaceBP bpm(128, 16, 4, 4); + + bpm(cv::gpu::GpuMat(img_l), cv::gpu::GpuMat(img_r), disp); + + //cv::imwrite(std::string(ts->get_data_path()) + "csstereobp/aloe-disp.png", disp); + + disp.convertTo(disp, img_template.type()); + + double norm = cv::norm(disp, img_template, cv::NORM_INF); + if (norm >= 0.5) + { + ts->printf(cvtest::TS::LOG, "\nConstantSpaceStereoBP norm = %f\n", norm); + ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); + return; + } + + ts->set_failed_test_info(cvtest::TS::OK); + } +}; + +TEST(StereoConstantSpaceBP, regression) { CV_GpuStereoCSBPTest test; test.safe_run(); }