From e8f3469096df0a65a8c38e57e8eb58632fb1e806 Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 3 Nov 2016 16:54:06 +0300 Subject: [PATCH] Added OpenVX based processing to Sobel --- modules/imgproc/src/deriv.cpp | 135 ++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index f8821f0ab1..c3c30cb354 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -43,6 +43,12 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#ifdef HAVE_OPENVX +#define IVX_HIDE_INFO_WARNINGS +#define IVX_USE_OPENCV +#include "ivx.hpp" +#endif + /****************************************************************************************\ Sobel & Scharr Derivative Filters \****************************************************************************************/ @@ -179,6 +185,130 @@ cv::Ptr cv::createDerivFilter(int srcType, int dstType, kx, ky, Point(-1,-1), 0, borderType ); } +#ifdef HAVE_OPENVX +namespace cv +{ + static bool openvx_sobel(InputArray _src, OutputArray _dst, + int dx, int dy, int ksize, + double scale, double delta, int borderType) + { + int stype = _src.type(); + int dtype = _dst.type(); + if (stype != CV_8UC1 || (dtype != CV_16SC1 && dtype != CV_8UC1) || + ksize < 3 || ksize % 2 != 1 || delta != 0.0) + return false; + + Mat src = _src.getMat(); + Mat dst = _dst.getMat(); + + if (src.cols < ksize || src.rows < ksize) + return false; + + int iscale = 1; + vx_uint32 cscale = 1; + if(scale != 1.0) + { + iscale = static_cast(scale); + if (std::abs(scale - iscale) >= DBL_EPSILON) + { + int exp = 0; + float significand = frexp(scale, &exp); + if ((significand == 0.5f) && (exp <= 0)) + { + iscale = 1; + cscale = 1 << (exp = -exp + 1); + } + else + return false; + } + } + + if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) + return false; //Process isolated borders only + vx_border_t border; + switch (borderType & ~BORDER_ISOLATED) + { + case BORDER_CONSTANT: + border.mode = VX_BORDER_CONSTANT; +#if VX_VERSION > VX_VERSION_1_0 + border.constant_value.U8 = (vx_uint8)(0); +#else + border.constant_value = (vx_uint32)(0); +#endif + break; + case BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return false; + } + + try + { + ivx::Context ctx = ivx::Context::create(); + if ((vx_size)ksize > ctx.convolutionMaxDimension()) + return false; + + Mat a; + if (dst.data != src.data) + a = src; + else + src.copyTo(a); + + ivx::Image + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data), + ib = ivx::Image::createFromHandle(ctx, dtype == CV_16SC1 ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8, + ivx::Image::createAddressing(dst.cols, dst.rows, dtype == CV_16SC1 ? 2 : 1, (vx_int32)(dst.step)), dst.data); + + //ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments + //since OpenVX standart says nothing about thread-safety for now + vx_border_t prevBorder = ctx.borderMode(); + ctx.setBorderMode(border); + if (dtype == CV_16SC1 && ksize == 3 && ((dx | dy) == 1) && (dx + dy) == 1) + { + if(dx) + ivx::IVX_CHECK_STATUS(vxuSobel3x3(ctx, ia, ib, NULL)); + else + ivx::IVX_CHECK_STATUS(vxuSobel3x3(ctx, ia, NULL, ib)); + } + else + { +#if VX_VERSION <= VX_VERSION_1_0 + if (ctx.vendorID() == VX_ID_KHRONOS && ((vx_size)(src.cols) <= ctx.convolutionMaxDimension() || (vx_size)(src.rows) <= ctx.convolutionMaxDimension())) + { + ctx.setBorderMode(prevBorder); + return false; + } +#endif + Mat kx, ky; + getDerivKernels(kx, ky, dx, dy, ksize, false); + flip(kx, kx, 0); + flip(ky, ky, 0); + Mat convData; + cv::Mat(ky*kx.t()).convertTo(convData, CV_16SC1, iscale); + ivx::Convolution cnv = ivx::Convolution::create(ctx, convData.cols, convData.rows); + cnv.copyFrom(convData); + cnv.setScale(cscale); + ivx::IVX_CHECK_STATUS(vxuConvolve(ctx, ia, cnv, ib)); + } + ctx.setBorderMode(prevBorder); + return true; + } + catch (ivx::RuntimeError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + catch (ivx::WrapperError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + } +} +#endif + #ifdef HAVE_IPP namespace cv { @@ -599,6 +729,11 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif +#ifdef HAVE_OPENVX + if (openvx_sobel(_src, _dst, dx, dy, ksize, scale, delta, borderType)) + return; +#endif + CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_sobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)); int ktype = std::max(CV_32F, std::max(ddepth, sdepth));