From 881e837520960798b2f8c2f1944f10ca9b5aef25 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 22 Nov 2013 16:51:01 +0400 Subject: [PATCH] ocl/core: added prototype for tests --- cmake/OpenCVModule.cmake | 8 +- modules/core/include/opencv2/core/mat.hpp | 25 +++ modules/core/src/arithm.cpp | 2 +- modules/core/test/ocl/test_arithm.cpp | 177 ++++++++++++++++++ modules/ts/include/opencv2/ts/ocl_test.hpp | 290 +++++++++++++++++++++++++++++ modules/ts/src/ocl_test.cpp | 166 +++++++++++++++++ 6 files changed, 663 insertions(+), 5 deletions(-) create mode 100644 modules/core/test/ocl/test_arithm.cpp create mode 100644 modules/ts/include/opencv2/ts/ocl_test.hpp create mode 100644 modules/ts/src/ocl_test.cpp diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index c07a2b8..011529d 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -690,8 +690,8 @@ function(ocv_add_perf_tests) ocv_module_include_directories(${perf_deps} "${perf_path}") if(NOT OPENCV_PERF_${the_module}_SOURCES) - file(GLOB perf_srcs "${perf_path}/*.cpp") - file(GLOB perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h") + file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp") + file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h") source_group("Src" FILES ${perf_srcs}) source_group("Include" FILES ${perf_hdrs}) set(OPENCV_PERF_${the_module}_SOURCES ${perf_srcs} ${perf_hdrs}) @@ -740,8 +740,8 @@ function(ocv_add_accuracy_tests) ocv_module_include_directories(${test_deps} "${test_path}") if(NOT OPENCV_TEST_${the_module}_SOURCES) - file(GLOB test_srcs "${test_path}/*.cpp") - file(GLOB test_hdrs "${test_path}/*.hpp" "${test_path}/*.h") + file(GLOB_RECURSE test_srcs "${test_path}/*.cpp") + file(GLOB_RECURSE test_hdrs "${test_path}/*.hpp" "${test_path}/*.h") source_group("Src" FILES ${test_srcs}) source_group("Include" FILES ${test_hdrs}) set(OPENCV_TEST_${the_module}_SOURCES ${test_srcs} ${test_hdrs}) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 2f38f8b..79fac33 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -2340,6 +2340,31 @@ CV_EXPORTS MatExpr max(double s, const Mat& a); CV_EXPORTS MatExpr abs(const Mat& m); CV_EXPORTS MatExpr abs(const MatExpr& e); +namespace traits { + +template +struct GetMatForRead +{ +}; +template <> +struct GetMatForRead +{ + static const Mat get(const Mat& m) { return m; } +}; +template <> +struct GetMatForRead +{ + static const Mat get(const UMat& m) { return m.getMat(ACCESS_READ); } +}; + +} // namespace traits + +template +const Mat getMatForRead(const T& mat) +{ + return traits::GetMatForRead::get(mat); +} + } // cv #include "opencv2/core/mat.inl.hpp" diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index a2b8a9e..9c36d18 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1410,7 +1410,7 @@ static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, int wtype, dims1 = psrc1->dims(), dims2 = psrc2->dims(); Size sz1 = dims1 <= 2 ? psrc1->size() : Size(); Size sz2 = dims2 <= 2 ? psrc2->size() : Size(); - bool use_opencl = (kind1 == _InputArray::UMAT || kind2 == _InputArray::UMAT) && + bool use_opencl = (kind1 == _InputArray::UMAT || kind2 == _InputArray::UMAT || _dst.kind() == _OutputArray::UMAT) && ocl::useOpenCL() && dims1 <= 2 && dims2 <= 2; bool src1Scalar = checkScalar(*psrc1, type2, kind1, kind2); bool src2Scalar = checkScalar(*psrc2, type1, kind2, kind1); diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp new file mode 100644 index 0000000..24d0f75 --- /dev/null +++ b/modules/core/test/ocl/test_arithm.cpp @@ -0,0 +1,177 @@ +/*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) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation 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 "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +///////////////////////// ArithmTestBase /////////////////////////// + +PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) +{ + int depth; + int cn; + bool use_roi; + cv::Scalar val; + + // declare Mat + UMat mirrors + TEST_DECLARE_INPUT_PARATEMER(src1) + TEST_DECLARE_INPUT_PARATEMER(src2) + TEST_DECLARE_INPUT_PARATEMER(mask) + TEST_DECLARE_OUTPUT_PARATEMER(dst1) + TEST_DECLARE_OUTPUT_PARATEMER(dst2) + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + virtual void generateTestData() + { + const int type = CV_MAKE_TYPE(depth, cn); + + Size roiSize = randomSize(1, MAX_VALUE); + Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src1, src1_roi, roiSize, src1Border, type, 2, 11); + + Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src2, src2_roi, roiSize, src2Border, type, -1540, 1740); + + Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst1, dst1_roi, roiSize, dst1Border, type, 5, 16); + + Border dst2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst2, dst2_roi, roiSize, dst2Border, type, 5, 16); + + Border maskBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(mask, mask_roi, roiSize, maskBorder, CV_8UC1, 0, 2); + cv::threshold(mask, mask, 0.5, 255., CV_8UC1); + + val = cv::Scalar(rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0), + rng.uniform(-100.0, 100.0), rng.uniform(-100.0, 100.0)); + + UMAT_UPLOAD_INPUT_PARAMETER(src1) + UMAT_UPLOAD_INPUT_PARAMETER(src2) + UMAT_UPLOAD_INPUT_PARAMETER(mask) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst1) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst2) + } + + void Near(double threshold = 0.) + { + EXPECT_MAT_NEAR(dst1, udst1, threshold); + EXPECT_MAT_NEAR(dst1_roi, udst1_roi, threshold); + } + + void Near1(double threshold = 0.) + { + EXPECT_MAT_NEAR(dst2, udst2, threshold); + EXPECT_MAT_NEAR(dst2_roi, udst2_roi, threshold); + } +}; + +//////////////////////////////// Add ///////////////////////////////////////////////// + +typedef ArithmTestBase Add; + +OCL_TEST_P(Add, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::add(src1_roi, src2_roi, dst1_roi)); + OCL_ON(cv::add(usrc1_roi, usrc2_roi, udst1_roi)); + Near(0); + } +} + +OCL_TEST_P(Add, Mat_Mask) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::add(src1_roi, src2_roi, dst1_roi, mask_roi)); + OCL_ON(cv::add(usrc1_roi, usrc2_roi, udst1_roi, umask_roi)); + Near(0); + } +} + +OCL_TEST_P(Add, Scalar) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::add(src1_roi, val, dst1_roi)); + OCL_ON(cv::add(usrc1_roi, val, udst1_roi)); + Near(1e-5); + } +} + +OCL_TEST_P(Add, Scalar_Mask) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::add(src1_roi, val, dst1_roi, mask_roi)); + OCL_ON(cv::add(usrc1_roi, val, udst1_roi, umask_roi)); + Near(1e-5); + } +} + + + +//////////////////////////////////////// Instantiation ///////////////////////////////////////// + +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Add, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp new file mode 100644 index 0000000..5c6aaef --- /dev/null +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -0,0 +1,290 @@ +/*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) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation 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*/ + +#ifndef __OPENCV_TS_OCL_TEST_HPP__ +#define __OPENCV_TS_OCL_TEST_HPP__ + +#ifdef HAVE_OPENCL + +#include "cvconfig.h" +#include "opencv2/opencv_modules.hpp" + +#include "opencv2/ts.hpp" + +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgproc/types_c.h" +#include "opencv2/core/ocl.hpp" + +namespace cvtest { +namespace ocl { + +using namespace cv; +using namespace testing; + +extern int test_loop_times; + +#define MAX_VALUE 357 + +#define EXPECT_MAT_NORM(mat, eps) \ +{ \ + EXPECT_LE(checkNorm(mat), eps) \ +} + +#define EXPECT_MAT_NEAR(mat1, mat2, eps) \ +{ \ + ASSERT_EQ(mat1.type(), mat2.type()); \ + ASSERT_EQ(mat1.size(), mat2.size()); \ + EXPECT_LE(checkNorm(mat1, mat2), eps) \ + << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ +} + +#define EXPECT_MAT_NEAR_RELATIVE(mat1, mat2, eps) \ +{ \ + ASSERT_EQ(mat1.type(), mat2.type()); \ + ASSERT_EQ(mat1.size(), mat2.size()); \ + EXPECT_LE(checkNormRelative(mat1, mat2), eps) \ + << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ +} + +#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \ +{ \ + ASSERT_EQ(mat1.type(), mat2.type()); \ + ASSERT_EQ(mat1.size(), mat2.size()); \ + EXPECT_LE(checkSimilarity(mat1, mat2), eps); \ + << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ +} + +using perf::MatDepth; +using perf::MatType; + +#define OCL_RNG_SEED 123456 + +struct TestUtils +{ + cv::RNG rng; + + TestUtils() + { + rng = cv::RNG(OCL_RNG_SEED); + } + + int randomInt(int minVal, int maxVal) + { + return rng.uniform(minVal, maxVal); + } + + double randomDouble(double minVal, double maxVal) + { + return rng.uniform(minVal, maxVal); + } + + double randomDoubleLog(double minVal, double maxVal) + { + double logMin = log((double)minVal + 1); + double logMax = log((double)maxVal + 1); + double pow = rng.uniform(logMin, logMax); + double v = exp(pow) - 1; + CV_Assert(v >= minVal && (v < maxVal || (v == minVal && v == maxVal))); + return v; + } + + Size randomSize(int minVal, int maxVal) + { +#if 1 + return cv::Size((int)randomDoubleLog(minVal, maxVal), (int)randomDoubleLog(minVal, maxVal)); +#else + return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal)); +#endif + } + + Size randomSize(int minValX, int maxValX, int minValY, int maxValY) + { +#if 1 + return cv::Size((int)randomDoubleLog(minValX, maxValX), (int)randomDoubleLog(minValY, maxValY)); +#else + return cv::Size(randomInt(minVal, maxVal), randomInt(minVal, maxVal)); +#endif + } + + Scalar randomScalar(double minVal, double maxVal) + { + return Scalar(randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal), randomDouble(minVal, maxVal)); + } + + Mat randomMat(Size size, int type, double minVal, double maxVal, bool useRoi = false) + { + RNG dataRng(rng.next()); + return cvtest::randomMat(dataRng, size, type, minVal, maxVal, useRoi); + } + + struct Border + { + int top, bot, lef, rig; + }; + + Border randomBorder(int minValue = 0, int maxValue = MAX_VALUE) + { + Border border = { + (int)randomDoubleLog(minValue, maxValue), + (int)randomDoubleLog(minValue, maxValue), + (int)randomDoubleLog(minValue, maxValue), + (int)randomDoubleLog(minValue, maxValue) + }; + return border; + } + + void randomSubMat(Mat& whole, Mat& subMat, const Size& roiSize, const Border& border, int type, double minVal, double maxVal) + { + Size wholeSize = Size(roiSize.width + border.lef + border.rig, roiSize.height + border.top + border.bot); + whole = randomMat(wholeSize, type, minVal, maxVal, false); + subMat = whole(Rect(border.lef, border.top, roiSize.width, roiSize.height)); + } + + // If the two vectors are not equal, it will return the difference in vector size + // Else it will return (total diff of each 1 and 2 rects covered pixels)/(total 1 rects covered pixels) + // The smaller, the better matched + static double checkRectSimilarity(cv::Size sz, std::vector& ob1, std::vector& ob2); + + //! read image from testdata folder. + + static cv::Mat readImage(const String &fileName, int flags = cv::IMREAD_COLOR); + static cv::Mat readImageType(const String &fname, int type); + + static double checkNorm(const cv::Mat &m); + static double checkNorm(const cv::Mat &m1, const cv::Mat &m2); + static double checkSimilarity(const cv::Mat &m1, const cv::Mat &m2); + static inline double checkNormRelative(const Mat &m1, const Mat &m2) + { + return cv::norm(m1, m2, cv::NORM_INF) / + std::max((double)std::numeric_limits::epsilon(), + (double)std::max(cv::norm(m1, cv::NORM_INF), norm(m2, cv::NORM_INF))); + } + static void showDiff(const Mat& src, const Mat& gold, const Mat& actual, double eps, bool alwaysShow = false); + + template + static double checkNorm(const T1& m) + { + return checkNorm(cv::getMatForRead(m)); + } + template + static double checkNorm(const T1& m1, const T2& m2) + { + return checkNorm(cv::getMatForRead(m1), cv::getMatForRead(m2)); + } + template + static double checkSimilarity(const T1& m1, const T2& m2) + { + return checkSimilarity(cv::getMatForRead(m1), cv::getMatForRead(m2)); + } + template + static inline double checkNormRelative(const T1& m1, const T2& m2) + { + const Mat _m1 = cv::getMatForRead(m1); + const Mat _m2 = cv::getMatForRead(m2); + return checkNormRelative(_m1, _m2); + } + + template + static void showDiff(const T1& src, const T2& gold, const T3& actual, double eps, bool alwaysShow = false) + { + const Mat _src = cv::getMatForRead(src); + const Mat _gold = cv::getMatForRead(gold); + const Mat _actual = cv::getMatForRead(actual); + showDiff(_src, _gold, _actual, eps, alwaysShow); + } +}; + +#define TEST_DECLARE_INPUT_PARATEMER(name) Mat name, name ## _roi; UMat u ## name, u ## name ## _roi; +#define TEST_DECLARE_OUTPUT_PARATEMER(name) TEST_DECLARE_INPUT_PARATEMER(name) + +#define UMAT_UPLOAD_INPUT_PARAMETER(name) \ +{ \ + name.copyTo(u ## name); \ + Size wholeSize; Point ofs; name ## _roi.locateROI(wholeSize, ofs); \ + u ## name ## _roi = u ## name(Rect(ofs.x, ofs.y, name ## _roi.size().width, name ## _roi.size().height)); \ +} +#define UMAT_UPLOAD_OUTPUT_PARAMETER(name) UMAT_UPLOAD_INPUT_PARAMETER(name) + +template +struct TSTestWithParam : public TestUtils, public ::testing::TestWithParam +{ + +}; + +#define PARAM_TEST_CASE(name, ...) struct name : public TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > > + +#define GET_PARAM(k) std::tr1::get< k >(GetParam()) + +#ifndef IMPLEMENT_PARAM_CLASS +#define IMPLEMENT_PARAM_CLASS(name, type) \ + class name \ + { \ + public: \ + name ( type arg = type ()) : val_(arg) {} \ + operator type () const {return val_;} \ + private: \ + type val_; \ + }; \ + inline void PrintTo( name param, std::ostream* os) \ + { \ + *os << #name << "(" << testing::PrintToString(static_cast< type >(param)) << ")"; \ + } + +IMPLEMENT_PARAM_CLASS(Channels, int) +#endif // IMPLEMENT_PARAM_CLASS + +#define OCL_TEST_P TEST_P + +#define OCL_OFF(fn) cv::ocl::setUseOpenCL(false); fn +#define OCL_ON(fn) cv::ocl::setUseOpenCL(true); fn + +#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F) +#define OCL_ALL_CHANNELS Values(1, 2, 3, 4) + +#define OCL_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + INSTANTIATE_TEST_CASE_P(OCL_ ## prefix, test_case_name, generator) + +}} // namespace cvtest::ocl + +#endif // HAVE_OPENCL + +#endif // __OPENCV_TS_OCL_TEST_HPP__ diff --git a/modules/ts/src/ocl_test.cpp b/modules/ts/src/ocl_test.cpp new file mode 100644 index 0000000..d2ee771 --- /dev/null +++ b/modules/ts/src/ocl_test.cpp @@ -0,0 +1,166 @@ +/*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) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation 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 "precomp.hpp" + +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +using namespace cv; + +int test_loop_times = 1; // TODO Read from command line / environment + +Mat TestUtils::readImage(const String &fileName, int flags) +{ + return cv::imread(cvtest::TS::ptr()->get_data_path() + fileName, flags); +} + +Mat TestUtils::readImageType(const String &fname, int type) +{ + Mat src = readImage(fname, CV_MAT_CN(type) == 1 ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR); + if (CV_MAT_CN(type) == 4) + { + Mat temp; + cv::cvtColor(src, temp, cv::COLOR_BGR2BGRA); + swap(src, temp); + } + src.convertTo(src, CV_MAT_DEPTH(type)); + return src; +} + +double TestUtils::checkNorm(const Mat &m) +{ + return norm(m, NORM_INF); +} + +double TestUtils::checkNorm(const Mat &m1, const Mat &m2) +{ + return norm(m1, m2, NORM_INF); +} + +double TestUtils::checkSimilarity(const Mat &m1, const Mat &m2) +{ + Mat diff; + matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED); + return std::abs(diff.at(0, 0) - 1.f); +} + +double TestUtils::checkRectSimilarity(Size sz, std::vector& ob1, std::vector& ob2) +{ + double final_test_result = 0.0; + size_t sz1 = ob1.size(); + size_t sz2 = ob2.size(); + + if(sz1 != sz2) + { + return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1); + } + else + { + if(sz1==0 && sz2==0) + return 0; + cv::Mat cpu_result(sz, CV_8UC1); + cpu_result.setTo(0); + + for(vector::const_iterator r = ob1.begin(); r != ob1.end(); r++) + { + cv::Mat cpu_result_roi(cpu_result, *r); + cpu_result_roi.setTo(1); + cpu_result.copyTo(cpu_result); + } + int cpu_area = cv::countNonZero(cpu_result > 0); + + cv::Mat gpu_result(sz, CV_8UC1); + gpu_result.setTo(0); + for(vector::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++) + { + cv::Mat gpu_result_roi(gpu_result, *r2); + gpu_result_roi.setTo(1); + gpu_result.copyTo(gpu_result); + } + + cv::Mat result_; + multiply(cpu_result, gpu_result, result_); + int result = cv::countNonZero(result_ > 0); + if(cpu_area!=0 && result!=0) + final_test_result = 1.0 - (double)result/(double)cpu_area; + else if(cpu_area==0 && result!=0) + final_test_result = -1; + } + return final_test_result; +} + +void TestUtils::showDiff(const Mat& src, const Mat& gold, const Mat& actual, double eps, bool alwaysShow) +{ + Mat diff, diff_thresh; + absdiff(gold, actual, diff); + diff.convertTo(diff, CV_32F); + threshold(diff, diff_thresh, eps, 255.0, cv::THRESH_BINARY); + + if (alwaysShow || cv::countNonZero(diff_thresh.reshape(1)) > 0) + { +#if 0 + std::cout << "Source: " << std::endl << src << std::endl; + std::cout << "Expected: " << std::endl << gold << std::endl; + std::cout << "Actual: " << std::endl << actual << std::endl; +#endif + + namedWindow("src", WINDOW_NORMAL); + namedWindow("gold", WINDOW_NORMAL); + namedWindow("actual", WINDOW_NORMAL); + namedWindow("diff", WINDOW_NORMAL); + + imshow("src", src); + imshow("gold", gold); + imshow("actual", actual); + imshow("diff", diff); + + cv::waitKey(); + } +} + +}} // namespace cvtest::ocl + +#endif // HAVE_OPENCL -- 2.7.4