From faefbf93bc91a9fad25bf015d3e2e47b05a35199 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Fri, 16 Dec 2016 14:48:58 +0400 Subject: [PATCH] Merge pull request #7793 from savuor:openvx_pyrDown OpenVX pyrDown wrappers (#7793) * wrappers for vx_pyramid added * initial version of pyrDown() wrapper added * disabled for Khronos * rewritten for new macro use; border mode added to node --- modules/imgproc/src/pyramids.cpp | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index d774396509..866a17f8eb 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -44,6 +44,8 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#include "opencv2/core/openvx/ovx_defs.hpp" + namespace cv { @@ -1254,6 +1256,82 @@ static bool ipp_pyrdown( InputArray _src, OutputArray _dst, const Size& _dsz, in } #endif +#ifdef HAVE_OPENVX +namespace cv +{ +static bool openvx_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) +{ + using namespace ivx; + + Mat srcMat = _src.getMat(); + + CV_Assert(!srcMat.empty()); + + Size ssize = _src.size(); + Size acceptableSize = Size((ssize.width + 1) / 2, (ssize.height + 1) / 2); + + // OpenVX limitations + if((srcMat.type() != CV_8U) || + (borderType != BORDER_REPLICATE) || + (_dsz != acceptableSize && _dsz.area() != 0)) + return false; + + // The only border mode which is supported by both cv::pyrDown() and OpenVX + // and produces predictable results + vx_border_t borderMode; + borderMode.mode = VX_BORDER_REPLICATE; + + _dst.create( acceptableSize, srcMat.type() ); + Mat dstMat = _dst.getMat(); + + CV_Assert( ssize.width > 0 && ssize.height > 0 && + std::abs(acceptableSize.width*2 - ssize.width) <= 2 && + std::abs(acceptableSize.height*2 - ssize.height) <= 2 ); + + try + { + Context context = Context::create(); + if(context.vendorID() == VX_ID_KHRONOS) + { + // This implementation performs floor-like rounding + // (OpenCV uses floor(x+0.5)-like rounding) + // and ignores border mode (and loses 1px size border) + return false; + } + + Image srcImg = Image::createFromHandle(context, Image::matTypeToFormat(srcMat.type()), + Image::createAddressing(srcMat), (void*)srcMat.data); + Image dstImg = Image::createFromHandle(context, Image::matTypeToFormat(dstMat.type()), + Image::createAddressing(dstMat), (void*)dstMat.data); + + ivx::Scalar kernelSize = ivx::Scalar::create(context, 5); + Graph graph = Graph::create(context); + ivx::Node halfNode = ivx::Node::create(graph, VX_KERNEL_HALFSCALE_GAUSSIAN, srcImg, dstImg, kernelSize); + halfNode.setBorder(borderMode); + graph.verify(); + graph.process(); + +#ifdef VX_VERSION_1_1 + //we should take user memory back before release + //(it's not done automatically according to standard) + srcImg.swapHandle(); dstImg.swapHandle(); +#endif + } + catch (RuntimeError & e) + { + VX_DbgThrow(e.what()); + } + catch (WrapperError & e) + { + VX_DbgThrow(e.what()); + } + + return true; +} + +} +#endif + void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { CV_INSTRUMENT_REGION() @@ -1263,6 +1341,9 @@ void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borde CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), ocl_pyrDown(_src, _dst, _dsz, borderType)) + CV_OVX_RUN(_src.dims() <= 2, + openvx_pyrDown(_src, _dst, _dsz, borderType)) + Mat src = _src.getMat(); Size dsz = _dsz.area() == 0 ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz; _dst.create( dsz, src.type() );