From abcf8d9e610e08227de9cada14868e46a651b8d7 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 29 Dec 2013 18:01:01 +0400 Subject: [PATCH] implemented OpenCL version of cv::convertScaleAbs --- modules/core/src/convert.cpp | 39 +++++++++++++++++++++++++++ modules/core/src/opencl/arithm.cl | 9 +++---- modules/core/test/ocl/test_arithm.cpp | 18 +++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index dba8c7b0c..c2014f1be 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -1266,10 +1266,49 @@ static BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) return cvtScaleTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; } +static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta ) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if (!doubleSupport && depth == CV_64F) + return false; + + char cvt[2][50]; + int wdepth = std::max(depth, CV_32F); + ocl::Kernel k("KF", ocl::core::arithm_oclsrc, + format("-D OP_CONVERT_SCALE_ABS -D UNARY_OP -D dstT=uchar -D srcT1=%s" + " -D workT=%s -D convertToWT1=%s -D convertToDT=%s%s", + ocl::typeToStr(depth), ocl::typeToStr(wdepth), + ocl::convertTypeStr(depth, wdepth, 1, cvt[0]), + ocl::convertTypeStr(wdepth, CV_8U, 1, cvt[1]), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + if (k.empty()) + return false; + + _dst.createSameSize(_src, CV_8UC(cn)); + UMat src = _src.getUMat(), dst = _dst.getUMat(); + + ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), + dstarg = ocl::KernelArg::WriteOnly(dst, cn); + + if (wdepth == CV_32F) + k.args(srcarg, dstarg, (float)alpha, (float)beta); + else if (wdepth == CV_64F) + k.args(srcarg, dstarg, alpha, beta); + + size_t globalsize[2] = { src.cols * cn, src.rows }; + return k.run(2, globalsize, NULL, false); +} + } void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta ) { + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && + ocl_convertScaleAbs(_src, _dst, alpha, beta)) + return; + Mat src = _src.getMat(); int cn = src.channels(); double scale[] = {alpha, beta}; diff --git a/modules/core/src/opencl/arithm.cl b/modules/core/src/opencl/arithm.cl index 1647e8d19..add4b0695 100644 --- a/modules/core/src/opencl/arithm.cl +++ b/modules/core/src/opencl/arithm.cl @@ -223,13 +223,12 @@ dstelem = v > (dstT)(0) ? log(v) : log(-v) #define convertToWT2 #define PROCESS_ELEM dstelem = convert_uchar(srcelem1 CMP_OPERATOR srcelem2 ? 255 : 0) -#elif defined OP_CONVERT -#define PROCESS_ELEM dstelem = convertToDT(srcelem1) - -#elif defined OP_CONVERT_SCALE +#elif defined OP_CONVERT_SCALE_ABS #undef EXTRA_PARAMS #define EXTRA_PARAMS , workT alpha, workT beta -#define PROCESS_ELEM dstelem = convertToDT(srcelem1*alpha + beta) +#define PROCESS_ELEM \ + workT value = srcelem1 * alpha + beta; \ + dstelem = convertToDT(value >= 0 ? value : -value) #elif defined OP_CTP_AD || defined OP_CTP_AR #ifdef OP_CTP_AD diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 3aa47b7d2..df692b818 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -1324,6 +1324,23 @@ OCL_TEST_P(InRange, Scalar) } +//////////////////////////////// ConvertScaleAbs //////////////////////////////////////////////// + +typedef ArithmTestBase ConvertScaleAbs; + +OCL_TEST_P(ConvertScaleAbs, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::convertScaleAbs(src1_roi, dst1_roi, val[0], val[1])); + OCL_ON(cv::convertScaleAbs(usrc1_roi, udst1_roi, val[0], val[1])); + + Near(depth <= CV_32S ? 1 : 1e-6); + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); @@ -1360,6 +1377,7 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNE OCL_INSTANTIATE_TEST_CASE_P(Arithm, Sqrt, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Normalize, Combine(OCL_ALL_DEPTHS, Values(Channels(1)), Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, InRange, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, ConvertScaleAbs, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl