From 2fe9c8743316f015d8d46798d727bc7349622d6a Mon Sep 17 00:00:00 2001 From: Orest Chura Date: Tue, 7 Apr 2020 18:53:24 +0300 Subject: [PATCH] Merge pull request #16717 from OrestChura:oc/goodFeatures - cv::gapi::goodFeaturesToTrack() kernel is implemented - tests (for exact check with cv::goodFeaturesToTrack() and for internal cases) are implemented - a custom comparison function for vectors and a custom test fixture implemented - some posiible issues as wrong/inexact sorting of two compared vectors are not taken into account - initializations of an input Mat using a picture from opencv_extra implemented (function from gapi_streaming_test used) --- modules/gapi/include/opencv2/gapi/imgproc.hpp | 65 +++++- .../perf/common/gapi_imgproc_perf_tests.hpp | 5 +- .../common/gapi_imgproc_perf_tests_inl.hpp | 49 ++++- .../perf/cpu/gapi_imgproc_perf_tests_cpu.cpp | 24 ++- modules/gapi/src/api/kernels_imgproc.cpp | 10 +- modules/gapi/src/backends/cpu/gcpuimgproc.cpp | 14 +- modules/gapi/test/common/gapi_core_tests.hpp | 4 +- .../gapi/test/common/gapi_imgproc_tests.hpp | 8 +- .../test/common/gapi_imgproc_tests_inl.hpp | 30 ++- .../gapi/test/common/gapi_tests_common.hpp | 186 ++++++++++++++++-- .../gapi/test/cpu/gapi_imgproc_tests_cpu.cpp | 25 ++- 11 files changed, 389 insertions(+), 31 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/imgproc.hpp b/modules/gapi/include/opencv2/gapi/imgproc.hpp index 775c30a76a..148539826d 100644 --- a/modules/gapi/include/opencv2/gapi/imgproc.hpp +++ b/modules/gapi/include/opencv2/gapi/imgproc.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_IMGPROC_HPP @@ -102,6 +102,14 @@ namespace imgproc { } }; + G_TYPED_KERNEL(GGoodFeatures, + (GMat,int,double,double,Mat,int,bool,double)>, + "org.opencv.imgproc.goodFeaturesToTrack") { + static GArrayDesc outMeta(GMatDesc, int, double, double, const Mat&, int, bool, double) { + return empty_array_desc(); + } + }; + G_TYPED_KERNEL(GRGB2YUV, , "org.opencv.imgproc.colorconvert.rgb2yuv") { static GMatDesc outMeta(GMatDesc in) { return in; // type still remains CV_8UC3; @@ -251,7 +259,7 @@ namespace imgproc { } }; -} +} //namespace imgproc //! @addtogroup gapi_filters @@ -657,6 +665,59 @@ L2gradient=false ). GAPI_EXPORTS GMat Canny(const GMat& image, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false); +/** @brief Determines strong corners on an image. + +The function finds the most prominent corners in the image or in the specified image region, as +described in @cite Shi94 + +- Function calculates the corner quality measure at every source image pixel using the + #cornerMinEigenVal or #cornerHarris . +- Function performs a non-maximum suppression (the local maximums in *3 x 3* neighborhood are + retained). +- The corners with the minimal eigenvalue less than + \f$\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)\f$ are rejected. +- The remaining corners are sorted by the quality measure in the descending order. +- Function throws away each corner for which there is a stronger corner at a distance less than + maxDistance. + +The function can be used to initialize a point-based tracker of an object. + +@note If the function is called with different values A and B of the parameter qualityLevel , and +A \> B, the vector of returned corners with qualityLevel=A will be the prefix of the output vector +with qualityLevel=B . + +@note Function textual ID is "org.opencv.imgproc.goodFeaturesToTrack" + +@param image Input 8-bit or floating-point 32-bit, single-channel image. +@param maxCorners Maximum number of corners to return. If there are more corners than are found, +the strongest of them is returned. `maxCorners <= 0` implies that no limit on the maximum is set +and all detected corners are returned. +@param qualityLevel Parameter characterizing the minimal accepted quality of image corners. The +parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue +(see #cornerMinEigenVal ) or the Harris function response (see #cornerHarris ). The corners with the +quality measure less than the product are rejected. For example, if the best corner has the +quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure +less than 15 are rejected. +@param minDistance Minimum possible Euclidean distance between the returned corners. +@param mask Optional region of interest. If the image is not empty (it needs to have the type +CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected. +@param blockSize Size of an average block for computing a derivative covariation matrix over each +pixel neighborhood. See cornerEigenValsAndVecs . +@param useHarrisDetector Parameter indicating whether to use a Harris detector (see #cornerHarris) +or #cornerMinEigenVal. +@param k Free parameter of the Harris detector. + +@return vector of detected corners. + */ +GAPI_EXPORTS GArray goodFeaturesToTrack(const GMat &image, + int maxCorners, + double qualityLevel, + double minDistance, + const Mat &mask = Mat(), + int blockSize = 3, + bool useHarrisDetector = false, + double k = 0.04); + /** @brief Equalizes the histogram of a grayscale image. The function equalizes the histogram of the input image using the following algorithm: diff --git a/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp b/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp index c4e5bc64ae..9d3433d19b 100644 --- a/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp +++ b/modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_HPP @@ -33,6 +33,9 @@ class Dilate3x3PerfTest : public TestPerfParams> {}; class SobelXYPerfTest : public TestPerfParams> {}; class CannyPerfTest : public TestPerfParams> {}; +class GoodFeaturesPerfTest : public TestPerfParams, std::string, + int,int,double,double,int,bool, + cv::GCompileArgs>> {}; class EqHistPerfTest : public TestPerfParams> {}; class RGB2GrayPerfTest : public TestPerfParams> {}; class BGR2GrayPerfTest : public TestPerfParams> {}; diff --git a/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp b/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp index 3fea552ede..cd70d024a4 100644 --- a/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp +++ b/modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_IMGPROC_PERF_TESTS_INL_HPP @@ -622,6 +622,53 @@ PERF_TEST_P_(CannyPerfTest, TestPerformance) //------------------------------------------------------------------------------ +PERF_TEST_P_(GoodFeaturesPerfTest, TestPerformance) +{ + double k = 0.04; + + compare_vector_f cmpF; + std::string fileName = ""; + int type = -1, maxCorners = -1, blockSize = -1; + double qualityLevel = 0.0, minDistance = 0.0; + bool useHarrisDetector = false; + cv::GCompileArgs compileArgs; + std::tie(cmpF, fileName, type, maxCorners, qualityLevel, + minDistance, blockSize, useHarrisDetector, compileArgs) = GetParam(); + + initMatFromImage(type, fileName); + std::vector outVecOCV, outVecGAPI; + + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::goodFeaturesToTrack(in_mat1, outVecOCV, maxCorners, qualityLevel, minDistance, + cv::noArray(), blockSize, useHarrisDetector, k); + } + + // G-API code ////////////////////////////////////////////////////////////// + cv::GMat in; + auto out = cv::gapi::goodFeaturesToTrack(in, maxCorners, qualityLevel, minDistance, cv::Mat(), + blockSize, useHarrisDetector, k); + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + + // Warm-up graph engine: + c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI), std::move(compileArgs)); + + TEST_CYCLE() + { + c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI)); + } + + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(outVecGAPI, outVecOCV)); + } + + SANITY_CHECK_NOTHING(); + +} + +//------------------------------------------------------------------------------ + PERF_TEST_P_(EqHistPerfTest, TestPerformance) { compare_f cmpF = get<0>(GetParam()); diff --git a/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp b/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp index b2e5b3d1b7..3f2270391c 100644 --- a/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp +++ b/modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #include "../perf_precomp.hpp" @@ -134,6 +134,28 @@ INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest, Values(true, false), Values(cv::compile_args(IMGPROC_CPU)))); +INSTANTIATE_TEST_CASE_P(GoodFeaturesPerfTestCPU, GoodFeaturesPerfTest, + Combine(Values(AbsExactVector().to_compare_f()), + Values("cv/shared/pic5.png", "stitching/a1.png"), + Values(CV_32FC1, CV_8UC1), + Values(100, 500), + Values(0.1, 0.01), + Values(1.0), + Values(3, 5), + Values(true, false), + Values(cv::compile_args(IMGPROC_CPU)))); + +INSTANTIATE_TEST_CASE_P(GoodFeaturesInternalPerfTestCPU, GoodFeaturesPerfTest, + Combine(Values(AbsExactVector().to_compare_f()), + Values("cv/cascadeandhog/images/audrybt1.png"), + Values(CV_32FC1, CV_8UC1), + Values(100), + Values(0.0000001), + Values(5.0), + Values(3), + Values(true), + Values(cv::compile_args(IMGPROC_CPU)))); + INSTANTIATE_TEST_CASE_P(EqHistPerfTestCPU, EqHistPerfTest, Combine(Values(AbsExact().to_compare_f()), Values(szVGA, sz720p, sz1080p), diff --git a/modules/gapi/src/api/kernels_imgproc.cpp b/modules/gapi/src/api/kernels_imgproc.cpp index 8168c64a8c..eba26bbcec 100644 --- a/modules/gapi/src/api/kernels_imgproc.cpp +++ b/modules/gapi/src/api/kernels_imgproc.cpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #include "precomp.hpp" @@ -97,6 +97,14 @@ GMat Canny(const GMat& src, double thr1, double thr2, int apertureSize, bool l2g return imgproc::GCanny::on(src, thr1, thr2, apertureSize, l2gradient); } +cv::GArray goodFeaturesToTrack(const GMat& image, int maxCorners, double qualityLevel, + double minDistance, const Mat& mask, int blockSize, + bool useHarrisDetector, double k) +{ + return imgproc::GGoodFeatures::on(image, maxCorners, qualityLevel, minDistance, mask, blockSize, + useHarrisDetector, k); +} + GMat RGB2Gray(const GMat& src) { return imgproc::GRGB2Gray::on(src); diff --git a/modules/gapi/src/backends/cpu/gcpuimgproc.cpp b/modules/gapi/src/backends/cpu/gcpuimgproc.cpp index 29328c4969..e10c13fedd 100644 --- a/modules/gapi/src/backends/cpu/gcpuimgproc.cpp +++ b/modules/gapi/src/backends/cpu/gcpuimgproc.cpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #include "precomp.hpp" @@ -182,6 +182,17 @@ GAPI_OCV_KERNEL(GCPUCanny, cv::gapi::imgproc::GCanny) } }; +GAPI_OCV_KERNEL(GCPUGoodFeatures, cv::gapi::imgproc::GGoodFeatures) +{ + static void run(const cv::Mat& image, int maxCorners, double qualityLevel, double minDistance, + const cv::Mat& mask, int blockSize, bool useHarrisDetector, double k, + std::vector &out) + { + cv::goodFeaturesToTrack(image, out, maxCorners, qualityLevel, minDistance, + mask, blockSize, useHarrisDetector, k); + } +}; + GAPI_OCV_KERNEL(GCPURGB2YUV, cv::gapi::imgproc::GRGB2YUV) { static void run(const cv::Mat& in, cv::Mat &out) @@ -412,6 +423,7 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels() , GCPUSobel , GCPUSobelXY , GCPUCanny + , GCPUGoodFeatures , GCPUEqualizeHist , GCPURGB2YUV , GCPUYUV2RGB diff --git a/modules/gapi/test/common/gapi_core_tests.hpp b/modules/gapi/test/common/gapi_core_tests.hpp index 1d8bba969e..8a786a9ab0 100644 --- a/modules/gapi/test/common/gapi_core_tests.hpp +++ b/modules/gapi/test/common/gapi_core_tests.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_CORE_TESTS_HPP @@ -128,7 +128,7 @@ GAPI_TEST_FIXTURE(PhaseTest, initMatsRandU, FIXTURE_API(bool), 1, angle_in_degre GAPI_TEST_FIXTURE(SqrtTest, initMatrixRandU, <>, 0) GAPI_TEST_FIXTURE(NormalizeTest, initNothing, FIXTURE_API(CompareMats,double,double,int,MatType2), 5, cmpF, a, b, norm_type, ddepth) -struct BackendOutputAllocationTest : TestWithParamBase<> +struct BackendOutputAllocationTest : TestWithParams<> { BackendOutputAllocationTest() { diff --git a/modules/gapi/test/common/gapi_imgproc_tests.hpp b/modules/gapi/test/common/gapi_imgproc_tests.hpp index cba6b2a3ad..165f5d3ef0 100644 --- a/modules/gapi/test/common/gapi_imgproc_tests.hpp +++ b/modules/gapi/test/common/gapi_imgproc_tests.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_IMGPROC_TESTS_HPP @@ -14,6 +14,7 @@ namespace opencv_test { + // Create new value-parameterized test fixture: // Filter2DTest - fixture name // initMatrixRandN - function that is used to initialize input/output data @@ -52,6 +53,11 @@ GAPI_TEST_FIXTURE(SobelXYTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int, GAPI_TEST_FIXTURE(EqHistTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(CannyTest, initMatrixRandN, FIXTURE_API(CompareMats,double,double,int,bool), 5, cmpF, thrLow, thrUp, apSize, l2gr) +GAPI_TEST_FIXTURE_SPEC_PARAMS(GoodFeaturesTest, + FIXTURE_API(CompareVectors,std::string,int,int,double, + double,int,bool), + 8, cmpF, fileName, type, maxCorners, qualityLevel, minDistance, + blockSize, useHarrisDetector) GAPI_TEST_FIXTURE(RGB2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(BGR2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) GAPI_TEST_FIXTURE(RGB2YUVTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF) diff --git a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp index 3c62ff39fd..ecc7195c41 100644 --- a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp +++ b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_IMGPROC_TESTS_INL_HPP @@ -380,6 +380,34 @@ TEST_P(CannyTest, AccuracyTest) } } +TEST_P(GoodFeaturesTest, AccuracyTest) +{ + double k = 0.04; + + initMatFromImage(type, fileName); + + std::vector outVecOCV, outVecGAPI; + + // G-API code ////////////////////////////////////////////////////////////// + cv::GMat in; + auto out = cv::gapi::goodFeaturesToTrack(in, maxCorners, qualityLevel, minDistance, cv::Mat(), + blockSize, useHarrisDetector, k); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_mat1), cv::gout(outVecGAPI), getCompileArgs()); + + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::goodFeaturesToTrack(in_mat1, outVecOCV, maxCorners, qualityLevel, minDistance, + cv::noArray(), blockSize, useHarrisDetector, k); + } + + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(outVecGAPI, outVecOCV)); + } +} + TEST_P(RGB2GrayTest, AccuracyTest) { // G-API code ////////////////////////////////////////////////////////////// diff --git a/modules/gapi/test/common/gapi_tests_common.hpp b/modules/gapi/test/common/gapi_tests_common.hpp index 232616d727..938a7f77da 100644 --- a/modules/gapi/test/common/gapi_tests_common.hpp +++ b/modules/gapi/test/common/gapi_tests_common.hpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #ifndef OPENCV_GAPI_TESTS_COMMON_HPP #define OPENCV_GAPI_TESTS_COMMON_HPP @@ -56,7 +56,24 @@ namespace return o; } -} + + inline void initTestDataPath() + { +#ifndef WINRT + static bool initialized = false; + if (!initialized) + { + // Since G-API has no own test data (yet), it is taken from the common space + const char* testDataPath = getenv("OPENCV_TEST_DATA_PATH"); + GAPI_Assert(testDataPath != nullptr && + "OPENCV_TEST_DATA_PATH environment variable is either not set or set incorrectly."); + + cvtest::addDataSearchPath(testDataPath); + initialized = true; + } +#endif // WINRT + } +} // namespace namespace opencv_test { @@ -155,6 +172,30 @@ public: } } + void initMatFromImage(int type, const std::string& fileName) + { + initTestDataPath(); + + int channels = (type >> CV_CN_SHIFT) + 1; + GAPI_Assert(channels == 1 || channels == 3 || channels == 4); + const int readFlags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR; + cv::Mat mat = cv::imread(findDataFile(fileName), readFlags); + if (channels == 4) + { + cv::cvtColor(mat, in_mat1, cv::COLOR_BGR2BGRA); + } + else + { + in_mat1 = mat; + } + + int depth = CV_MAT_DEPTH(type); + if (in_mat1.depth() != depth) + { + in_mat1.convertTo(in_mat1, depth); + } + } + // empty function intended to show that nothing is to be initialized via TestFunctional methods void initNothing(int, cv::Size, int, bool = true) {} }; @@ -169,6 +210,11 @@ using compare_f = std::function; using compare_scalar_f = std::function; +template +using compare_vector_f = std::function &a, + const std::vector &b)>; + + // FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed // as 16FC512) struct MatType2 @@ -189,14 +235,16 @@ private: }; // Universal parameter wrapper for common (pre-defined) and specific (user-defined) parameters -template -struct Params +template +struct ParamsBase; + +template +struct ParamsBase, std::tuple> { - using gcomp_args_function_t = cv::GCompileArgs(*)(); - using common_params_t = std::tuple; + using common_params_t = std::tuple; using specific_params_t = std::tuple; - using params_t = std::tuple; - static constexpr const size_t common_params_size = std::tuple_size::value; + using params_t = std::tuple; + static constexpr const size_t common_params_size = std::tuple_size::value; static constexpr const size_t specific_params_size = std::tuple_size::value; template @@ -218,17 +266,24 @@ struct Params } }; -// Base class for test fixtures -template -struct TestWithParamBase : TestFunctional, - TestWithParam::params_t> +template +struct Params : public ParamsBase, + std::tuple> { - using AllParams = Params; + static constexpr const size_t compile_args_num = 3; +}; - MatType2 type = getCommonParam<0>(); - cv::Size sz = getCommonParam<1>(); - MatType2 dtype = getCommonParam<2>(); +template +struct ParamsSpecific : public ParamsBase, + std::tuple> +{ + static constexpr const size_t compile_args_num = 0; +}; +// Base class for test fixtures +template +struct TestWithParamsBase : TestFunctional, TestWithParam +{ // Get common (pre-defined) parameter value by index template inline auto getCommonParam() const @@ -248,13 +303,30 @@ struct TestWithParamBase : TestFunctional, // Return G-API compile arguments specified for test fixture inline cv::GCompileArgs getCompileArgs() const { - return getCommonParam<3>()(); + return getCommonParam()(); } }; +template +struct TestWithParams : public TestWithParamsBase> +{ + using AllParams = Params; + + MatType2 type = this->template getCommonParam<0>(); + cv::Size sz = this->template getCommonParam<1>(); + MatType2 dtype = this->template getCommonParam<2>(); +}; + +template +struct TestWithParamsSpecific : public TestWithParamsBase> +{ + using AllParams = ParamsSpecific; +}; + + /** * @private - * @brief Create G-API test fixture with TestWithParamBase base class + * @brief Create G-API test fixture with TestWithParams base class * @param Fixture test fixture name * @param InitF callable that will initialize default available members (from TestFunctional) * @param API base class API. Specifies types of user-defined parameters. If there are no such @@ -265,13 +337,33 @@ struct TestWithParamBase : TestFunctional, * must be empty. */ #define GAPI_TEST_FIXTURE(Fixture, InitF, API, Number, ...) \ - struct Fixture : public TestWithParamBase API { \ + struct Fixture : public TestWithParams API { \ static_assert(Number == AllParams::specific_params_size, \ "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \ __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \ Fixture() { InitF(type, sz, dtype); } \ }; +/** + * @private + * @brief Create G-API test fixture with TestWithParamsSpecific base class + * This fixture has reduced number of common parameters and no initialization; + * it should be used if you don't need common parameters of GAPI_TEST_FIXTURE. + * @param Fixture test fixture name + * @param API base class API. Specifies types of user-defined parameters. If there are no such + * parameters, empty angle brackets ("<>") must be specified. + * @param Number number of user-defined parameters (corresponds to the number of types in API). + * if there are no such parameters, 0 must be specified. + * @param ... list of names of user-defined parameters. if there are no parameters, the list + * must be empty. + */ +#define GAPI_TEST_FIXTURE_SPEC_PARAMS(Fixture, API, Number, ...) \ + struct Fixture : public TestWithParamsSpecific API { \ + static_assert(Number == AllParams::specific_params_size, \ + "Number of user-defined parameters doesn't match size of __VA_ARGS__"); \ + __WRAP_VAARGS(DEFINE_SPECIFIC_PARAMS_##Number(__VA_ARGS__)) \ + }; + // Wrapper for test fixture API. Use to specify multiple types. // Example: FIXTURE_API(int, bool) expands to #define FIXTURE_API(...) <__VA_ARGS__> @@ -298,6 +390,9 @@ private: using CompareMats = CompareF; using CompareScalars = CompareF; +template +using CompareVectors = CompareF, std::vector>; + template struct Wrappable { @@ -340,6 +435,28 @@ struct WrappableScalar } }; +template +struct WrappableVector +{ + compare_vector_f to_compare_f() + { + T t = *static_cast(this); + return [t](const std::vector& a, + const std::vector& b) + { + return t(a, b); + }; + } + + CompareVectors to_compare_obj() + { + T t = *static_cast(this); + std::stringstream ss; + ss << t; + return CompareVectors(to_compare_f(), ss.str()); + } +}; + class AbsExact : public Wrappable { @@ -547,6 +664,31 @@ public: private: double _tol; }; + +template +class AbsExactVector : public WrappableVector, Elem> +{ +public: + AbsExactVector() {} + bool operator() (const std::vector& in1, + const std::vector& in2) const + { + if (cv::norm(in1, in2, NORM_INF, cv::noArray()) != 0) + { + std::cout << "AbsExact error: G-API output and reference output vectors are not" + " bitexact equal." << std::endl; + return false; + } + else + { + return true; + } + } + friend std::ostream& operator<<(std::ostream& os, const AbsExactVector&) + { + return os << "AbsExactVector()"; + } +}; } // namespace opencv_test namespace @@ -560,6 +702,12 @@ inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_sca { return os << "compare_scalar_f"; } + +template +inline std::ostream& operator<<(std::ostream& os, const opencv_test::compare_vector_f&) +{ + return os << "compare_vector_f"; +} } // anonymous namespace // Note: namespace must match the namespace of the type of the printed object diff --git a/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp b/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp index 5658c6dd4f..937aef9e5a 100644 --- a/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp +++ b/modules/gapi/test/cpu/gapi_imgproc_tests_cpu.cpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2018-2019 Intel Corporation +// Copyright (C) 2018-2020 Intel Corporation #include "../test_precomp.hpp" @@ -196,6 +196,29 @@ INSTANTIATE_TEST_CASE_P(CannyTestCPU, CannyTest, Values(3, 5), testing::Bool())); +INSTANTIATE_TEST_CASE_P(GoodFeaturesTestCPU, GoodFeaturesTest, + Combine(Values(IMGPROC_CPU), + Values(AbsExactVector().to_compare_obj()), + Values("cv/shared/fruits.png"), + Values(CV_32FC1, CV_8UC1), + Values(50, 100), + Values(0.01), + Values(10.0), + Values(3), + testing::Bool())); + +INSTANTIATE_TEST_CASE_P(GoodFeaturesInternalTestCPU, GoodFeaturesTest, + Combine(Values(IMGPROC_CPU), + Values(AbsExactVector().to_compare_obj()), + Values("cv/cascadeandhog/images/audrybt1.png"), + Values(CV_32FC1, CV_8UC1), + Values(100), + Values(0.0000001), + Values(5.0), + Values(3), + Values(true))); + + INSTANTIATE_TEST_CASE_P(RGB2GrayTestCPU, RGB2GrayTest, Combine(Values(CV_8UC3), Values(cv::Size(1280, 720),