From 3e1bec52486bab3002e39fd912727b1a85d0a30a Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 30 Dec 2013 01:21:04 +0400 Subject: [PATCH] added OpenCL version of cv::patchNaNs --- modules/core/src/mathfuncs.cpp | 23 +++++++++- modules/core/src/opencl/arithm.cl | 7 ++++ modules/core/test/ocl/test_arithm.cpp | 60 +++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 0b596071a9..90e0d74a49 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -2364,12 +2364,31 @@ bool checkRange(InputArray _src, bool quiet, Point* pt, double minVal, double ma return badPt.x < 0; } +static bool ocl_patchNaNs( InputOutputArray _a, float value ) +{ + ocl::Kernel k("KF", ocl::core::arithm_oclsrc, + format("-D UNARY_OP -D OP_PATCH_NANS -D dstT=int")); + if (k.empty()) + return false; + + UMat a = _a.getUMat(); + int cn = a.channels(); + + k.args(ocl::KernelArg::ReadOnlyNoSize(a), + ocl::KernelArg::WriteOnly(a), (float)value); + + size_t globalsize[2] = { a.cols * cn, a.rows }; + return k.run(2, globalsize, NULL, false); +} void patchNaNs( InputOutputArray _a, double _val ) { - Mat a = _a.getMat(); - CV_Assert( a.depth() == CV_32F ); + CV_Assert( _a.depth() == CV_32F ); + if (ocl::useOpenCL() && _a.isUMat() && _a.dims() <= 2 && ocl_patchNaNs(_a, (float)_val)) + return; + + Mat a = _a.getMat(); const Mat* arrays[] = {&a, 0}; int* ptrs[1]; NAryMatIterator it(arrays, (uchar**)ptrs); diff --git a/modules/core/src/opencl/arithm.cl b/modules/core/src/opencl/arithm.cl index 605fe4785b..c8fd99eeff 100644 --- a/modules/core/src/opencl/arithm.cl +++ b/modules/core/src/opencl/arithm.cl @@ -271,6 +271,13 @@ dstelem = v > (dstT)(0) ? log(v) : log(-v) dstelem = cos(alpha) * x; \ dstelem2 = sin(alpha) * x +#elif defined OP_PATCH_NANS +#undef EXTRA_PARAMS +#define EXTRA_PARAMS , int val +#define PROCESS_ELEM \ + if (( srcelem1 & 0x7fffffff) > 0x7f800000 ) \ + dstelem = val + #else #error "unknown op type" #endif diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index f2b9875143..03d8422182 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -42,6 +42,8 @@ #include "test_precomp.hpp" #include "opencv2/ts/ocl_test.hpp" +#include + #ifdef HAVE_OPENCL namespace cvtest { @@ -1357,6 +1359,63 @@ OCL_TEST_P(ScaleAdd, Mat) } } +//////////////////////////////// PatchNans //////////////////////////////////////////////// + +PARAM_TEST_CASE(PatchNaNs, Channels, bool) +{ + int cn; + bool use_roi; + double value; + + TEST_DECLARE_INPUT_PARAMETER(src) + + virtual void SetUp() + { + cn = GET_PARAM(0); + use_roi = GET_PARAM(1); + } + + virtual void generateTestData() + { + const int type = CV_MAKE_TYPE(CV_32F, cn); + + Size roiSize = randomSize(1, 10); + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, type, -40, 40); + + // generating NaNs + roiSize.width *= cn; + for (int y = 0; y < roiSize.height; ++y) + { + float * const ptr = src_roi.ptr(y); + for (int x = 0; x < roiSize.width; ++x) + ptr[x] = randomInt(-1, 1) == 0 ? std::numeric_limits::quiet_NaN() : ptr[x]; + } + + value = randomDouble(-100, 100); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + } + + void Near() + { + OCL_EXPECT_MATS_NEAR(src, 0) + } +}; + +OCL_TEST_P(PatchNaNs, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::patchNaNs(src_roi, value)); + OCL_ON(cv::patchNaNs(usrc_roi, value)); + + Near(); + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); @@ -1395,6 +1454,7 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Normalize, Combine(OCL_ALL_DEPTHS, Values(Ch 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())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, ScaleAdd, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, PatchNaNs, Combine(OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl