From 315e7fbbee5ccc23bc7411874f0f636b8defecbb Mon Sep 17 00:00:00 2001 From: Alexey Smirnov Date: Thu, 7 Feb 2019 16:05:39 +0300 Subject: [PATCH] Merge pull request #13721 from smirnov-alexey:gapi_add_normalize GAPI: Add normalize kernel in G-API (#13721) * Add normalize kernel in G-API In addition add several tests on new kernel * Fix indentations and normalize test structure * Move normalize kernel from imgproc to core Set default parameter ddepth to -1 * Fix alignment --- modules/gapi/include/opencv2/gapi/core.hpp | 30 ++++++++++++++++ modules/gapi/include/opencv2/gapi/imgproc.hpp | 1 - modules/gapi/src/api/kernels_core.cpp | 6 ++++ modules/gapi/src/backends/cpu/gcpucore.cpp | 10 ++++++ modules/gapi/test/common/gapi_core_tests.hpp | 1 + .../gapi/test/common/gapi_core_tests_inl.hpp | 34 +++++++++++++++++++ .../test/common/gapi_imgproc_tests_inl.hpp | 1 + modules/gapi/test/cpu/gapi_core_tests_cpu.cpp | 12 +++++++ 8 files changed, 94 insertions(+), 1 deletion(-) diff --git a/modules/gapi/include/opencv2/gapi/core.hpp b/modules/gapi/include/opencv2/gapi/core.hpp index 9af3620fe9..6922b99c4b 100644 --- a/modules/gapi/include/opencv2/gapi/core.hpp +++ b/modules/gapi/include/opencv2/gapi/core.hpp @@ -459,6 +459,13 @@ namespace core { return in; } }; + + G_TYPED_KERNEL(GNormalize, , "org.opencv.core.normalize") { + static GMatDesc outMeta(GMatDesc in, double, double, int, int ddepth) { + // unlike opencv doesn't have a mask as a parameter + return (ddepth < 0 ? in : in.withDepth(ddepth)); + } + }; } //! @addtogroup gapi_math @@ -1592,6 +1599,29 @@ same as the input has; if rdepth is negative, the output matrix will have the sa @param beta optional delta added to the scaled values. */ GAPI_EXPORTS GMat convertTo(const GMat& src, int rdepth, double alpha=1, double beta=0); + +/** @brief Normalizes the norm or value range of an array. + +The function normalizes scale and shift the input array elements so that +\f[\| \texttt{dst} \| _{L_p}= \texttt{alpha}\f] +(where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that +\f[\min _I \texttt{dst} (I)= \texttt{alpha} , \, \, \max _I \texttt{dst} (I)= \texttt{beta}\f] +when normType=NORM_MINMAX (for dense arrays only). + +@note Function textual ID is "org.opencv.core.normalize" + +@param src input array. +@param alpha norm value to normalize to or the lower range boundary in case of the range +normalization. +@param beta upper range boundary in case of the range normalization; it is not used for the norm +normalization. +@param norm_type normalization type (see cv::NormTypes). +@param ddepth when negative, the output array has the same type as src; otherwise, it has the same +number of channels as src and the depth =ddepth. +@sa norm, Mat::convertTo +*/ +GAPI_EXPORTS GMat normalize(const GMat& src, double alpha, double beta, + int norm_type, int ddepth = -1); //! @} gapi_transform } //namespace gapi diff --git a/modules/gapi/include/opencv2/gapi/imgproc.hpp b/modules/gapi/include/opencv2/gapi/imgproc.hpp index aeed9fa6cf..b5a2b82507 100644 --- a/modules/gapi/include/opencv2/gapi/imgproc.hpp +++ b/modules/gapi/include/opencv2/gapi/imgproc.hpp @@ -669,7 +669,6 @@ Output image must be 8-bit unsigned 3-channel image @ref CV_8UC3. @sa RGB2Lab, RGB2YUV */ GAPI_EXPORTS GMat YUV2RGB(const GMat& src); - //! @} gapi_colorconvert } //namespace gapi } //namespace cv diff --git a/modules/gapi/src/api/kernels_core.cpp b/modules/gapi/src/api/kernels_core.cpp index c9fe19ed66..e46968b9d9 100644 --- a/modules/gapi/src/api/kernels_core.cpp +++ b/modules/gapi/src/api/kernels_core.cpp @@ -355,5 +355,11 @@ GMat sqrt(const GMat& src) return core::GSqrt::on(src); } +GMat normalize(const GMat& _src, double a, double b, + int norm_type, int ddepth) +{ + return core::GNormalize::on(_src, a, b, norm_type, ddepth); +} + } //namespace gapi } //namespace cv diff --git a/modules/gapi/src/backends/cpu/gcpucore.cpp b/modules/gapi/src/backends/cpu/gcpucore.cpp index c42f863bfe..cec9abcd5c 100644 --- a/modules/gapi/src/backends/cpu/gcpucore.cpp +++ b/modules/gapi/src/backends/cpu/gcpucore.cpp @@ -525,6 +525,15 @@ GAPI_OCV_KERNEL(GCPUSqrt, cv::gapi::core::GSqrt) } }; +GAPI_OCV_KERNEL(GCPUNormalize, cv::gapi::core::GNormalize) +{ + static void run(const cv::Mat& src, double a, double b, + int norm_type, int ddepth, cv::Mat& out) + { + cv::normalize(src, out, a, b, norm_type, ddepth); + } +}; + cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels() { static auto pkg = cv::gapi::kernels @@ -590,6 +599,7 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels() , GCPULUT , GCPUConvertTo , GCPUSqrt + , GCPUNormalize >(); return pkg; } diff --git a/modules/gapi/test/common/gapi_core_tests.hpp b/modules/gapi/test/common/gapi_core_tests.hpp index 69028fdf20..6b5babc754 100644 --- a/modules/gapi/test/common/gapi_core_tests.hpp +++ b/modules/gapi/test/common/gapi_core_tests.hpp @@ -148,6 +148,7 @@ struct LUTTest : public TestParams> {}; struct PhaseTest : public TestParams> {}; struct SqrtTest : public TestParams> {}; +struct NormalizeTest : public TestParams> {}; } // opencv_test #endif //OPENCV_GAPI_CORE_TESTS_HPP diff --git a/modules/gapi/test/common/gapi_core_tests_inl.hpp b/modules/gapi/test/common/gapi_core_tests_inl.hpp index bc4359d66b..bf0ac98954 100644 --- a/modules/gapi/test/common/gapi_core_tests_inl.hpp +++ b/modules/gapi/test/common/gapi_core_tests_inl.hpp @@ -1437,6 +1437,40 @@ TEST_P(SqrtTest, AccuracyTest) } } +TEST_P(NormalizeTest, Test) +{ + auto param = GetParam(); + + compare_f cmpF; + MatType type, ddepth; + cv::Size sz; + double a = 0 , b = 0; + int norm_type = 0; + bool createOut = 0; + cv::GCompileArgs compile_args; + + std::tie(cmpF, type, sz, a, b, norm_type, ddepth, createOut, compile_args) = GetParam(); + int dtype = CV_MAKETYPE(ddepth, CV_MAT_CN(type)); + + initMatsRandN(type, sz, dtype, createOut); + + // G-API code ////////////////////////////////////////////////////////////// + cv::GMat in; + auto out = cv::gapi::normalize(in, a, b, norm_type, ddepth); + + cv::GComputation c(cv::GIn(in), cv::GOut(out)); + c.apply(cv::gin(in_mat1), cv::gout(out_mat_gapi), std::move(compile_args)); + + // OpenCV code ///////////////////////////////////////////////////////////// + { + cv::normalize(in_mat1, out_mat_ocv, a, b, norm_type, ddepth); + } + // Comparison ////////////////////////////////////////////////////////////// + { + EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv)); + EXPECT_EQ(out_mat_gapi.size(), sz); + } +} } // opencv_test diff --git a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp index 3de4289222..0812191f0f 100644 --- a/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp +++ b/modules/gapi/test/common/gapi_imgproc_tests_inl.hpp @@ -625,6 +625,7 @@ TEST_P(YUV2BGRTest, AccuracyTest) EXPECT_EQ(out_mat_gapi.size(), std::get<1>(param)); } } + } // opencv_test #endif //OPENCV_GAPI_IMGPROC_TESTS_INL_HPP diff --git a/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp b/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp index 608f6d1840..5414263fd6 100644 --- a/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp +++ b/modules/gapi/test/cpu/gapi_core_tests_cpu.cpp @@ -403,4 +403,16 @@ INSTANTIATE_TEST_CASE_P(ConcatHorVecTestCPU, ConcatHorVecTest, cv::Size(640, 480), cv::Size(128, 128)), Values(cv::compile_args(CORE_CPU)))); + +INSTANTIATE_TEST_CASE_P(NormalizeTestCPU, NormalizeTest, + Combine(Values(AbsExact().to_compare_f()), + Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1), + Values(cv::Size(1280, 720), + cv::Size(640, 480)), + Values(0.0, 15.0), + Values(1.0, 120.0, 255.0), + Values(NORM_MINMAX, NORM_INF, NORM_L1, NORM_L2), + Values(-1, CV_8U, CV_16U, CV_16S, CV_32F), +/*init output matrices or not*/ testing::Bool(), + Values(cv::compile_args(CORE_CPU)))); }