From 6d55e9929171f0b53b74946e18d7da1e1191377b Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Thu, 13 Oct 2016 14:05:07 +0300 Subject: [PATCH] Added OpenVX based processing to boxFilter --- modules/imgproc/src/smooth.cpp | 115 +++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index e7860b8807..9527b4563d 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -44,6 +44,11 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#ifdef HAVE_OPENVX +#define IVX_HIDE_INFO_WARNINGS +#define IVX_USE_OPENCV +#include "ivx.hpp" +#endif /* * This file includes the code, contributed by Simon Perreault * (the function icvMedianBlur_8u_O1) @@ -1634,6 +1639,111 @@ cv::Ptr cv::createBoxFilter( int srcType, int dstType, Size ks srcType, dstType, sumType, borderType ); } +#ifdef HAVE_OPENVX +namespace cv +{ + static bool openvx_boxfilter(InputArray _src, OutputArray _dst, int ddepth, + Size ksize, Point anchor, + bool normalize, int borderType) + { + int stype = _src.type(); + if (ddepth < 0) + ddepth = CV_8UC1; + if (stype != CV_8UC1 || (ddepth != CV_8U && ddepth != CV_16S) || + (anchor.x >= 0 && anchor.x != ksize.width / 2) || + (anchor.y >= 0 && anchor.y != ksize.height / 2) || + ksize.width % 2 != 1 || ksize.height % 2 != 1 || + ksize.width < 3 || ksize.height < 3) + return false; + + Mat src = _src.getMat(); + _dst.create(src.size(), CV_MAKETYPE(ddepth, 1)); + Mat dst = _dst.getMat(); + + if (src.cols < ksize.width || src.rows < ksize.height) + 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.width) > ctx.convolutionMaxDimension() || (vx_size)(ksize.height) > 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, ddepth == CV_16S ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8, + ivx::Image::createAddressing(dst.cols, dst.rows, ddepth == CV_16S ? 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 (ddepth == CV_8U && ksize.width == 3 && ksize.height == 3 && normalize) + { + ivx::IVX_CHECK_STATUS(vxuBox3x3(ctx, ia, 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 convData(ksize, CV_16SC1); + convData = normalize ? (1 << 15) / (ksize.width * ksize.height) : 1; + ivx::Convolution cnv = ivx::Convolution::create(ctx, convData.cols, convData.rows); + cnv.copyFrom(convData); + if (normalize) + cnv.setScale(1 << 15); + ivx::IVX_CHECK_STATUS(vxuConvolve(ctx, ia, cnv, ib)); + } + ctx.setBorderMode(prevBorder); + } + catch (ivx::RuntimeError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + catch (ivx::WrapperError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + + return true; + } +} +#endif + // TODO: IPP performance regression #if defined(HAVE_IPP) && IPP_DISABLE_BLOCK namespace cv @@ -1745,6 +1855,11 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize)) +#ifdef HAVE_OPENVX + if (openvx_boxfilter(_src, _dst, ddepth, ksize, anchor, normalize, borderType)) + return; +#endif + Mat src = _src.getMat(); int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if( ddepth < 0 )