diff --git a/3rdparty/openvx/include/ivx.hpp b/3rdparty/openvx/include/ivx.hpp index 04304be390..c808361b28 100644 --- a/3rdparty/openvx/include/ivx.hpp +++ b/3rdparty/openvx/include/ivx.hpp @@ -352,6 +352,15 @@ template <> struct RefTypeTraits static vx_status release(vxType& ref) { return vxReleaseDistribution(&ref); } }; +class Remap; +template <> struct RefTypeTraits +{ + typedef vx_remap vxType; + typedef Remap wrapperType; + static const vx_enum vxTypeEnum = VX_TYPE_REMAP; + static vx_status release(vxType& ref) { return vxReleaseRemap(&ref); } +}; + #ifdef IVX_USE_CXX98 /// Casting to vx_reference with compile-time check @@ -909,6 +918,34 @@ public: void setImmediateBorder(vx_enum mode, const vx_pixel_value_t& val) { border_t bm = {mode, val}; setImmediateBorder(bm); } + /// vxSetContextAttribute(BORDER) wrapper + template + void setImmediateBorder(vx_enum mode, const T& _val) + { + vx_pixel_value_t val; + switch (TypeToEnum::value) + { + case VX_TYPE_UINT8: + val.U8 = _val; + break; + case VX_TYPE_INT16: + val.S16 = _val; + break; + case VX_TYPE_UINT16: + val.U16 = _val; + break; + case VX_TYPE_INT32: + val.S32 = _val; + break; + case VX_TYPE_UINT32: + val.U32 = _val; + break; + default: + throw WrapperError("Unsupported constant border value type"); + } + setImmediateBorder(mode, val); + } + /// vxSetContextAttribute(BORDER) wrapper void setImmediateBorder(vx_enum mode) { vx_pixel_value_t val = {}; setImmediateBorder(mode, val); } @@ -1264,6 +1301,34 @@ static const vx_enum void setBorder(vx_enum mode, const vx_pixel_value_t& val) { vx_border_t bm = {mode, val}; setBorder(bm); } + /// vxSetNodeAttribute(BORDER) wrapper + template + void setBorder(vx_enum mode, const T& _val) + { + vx_pixel_value_t val; + switch (TypeToEnum::value) + { + case VX_TYPE_UINT8: + val.U8 = _val; + break; + case VX_TYPE_INT16: + val.S16 = _val; + break; + case VX_TYPE_UINT16: + val.U16 = _val; + break; + case VX_TYPE_INT32: + val.S32 = _val; + break; + case VX_TYPE_UINT32: + val.U32 = _val; + break; + default: + throw WrapperError("Unsupported constant border value type"); + } + setBorder(mode, val); + } + /// vxSetNodeAttribute(BORDER) wrapper void setBorder(vx_enum mode) { vx_pixel_value_t val = {}; setBorder(mode, val); } @@ -2914,6 +2979,148 @@ public: #endif //IVX_USE_OPENCV }; +/* +* Remap +*/ +class Remap : public RefWrapper +{ +public: + IVX_REF_STD_CTORS_AND_ASSIGNMENT(Remap); + + static Remap create(vx_context context, vx_uint32 src_width, vx_uint32 src_height, vx_uint32 dst_width, vx_uint32 dst_height) + { + return Remap(vxCreateRemap(context, src_width, src_height, dst_width, dst_height)); + } + +#ifndef VX_VERSION_1_1 + static const vx_enum + VX_REMAP_SOURCE_WIDTH = VX_REMAP_ATTRIBUTE_SOURCE_WIDTH, + VX_REMAP_SOURCE_HEIGHT = VX_REMAP_ATTRIBUTE_SOURCE_HEIGHT, + VX_REMAP_DESTINATION_WIDTH = VX_REMAP_ATTRIBUTE_DESTINATION_WIDTH, + VX_REMAP_DESTINATION_HEIGHT = VX_REMAP_ATTRIBUTE_DESTINATION_HEIGHT; +#endif + + template + void query(vx_enum att, T& value) const + { IVX_CHECK_STATUS(vxQueryRemap(ref, att, &value, sizeof(value))); } + + vx_uint32 srcWidth() const + { + vx_uint32 v; + query(VX_REMAP_SOURCE_WIDTH, v); + return v; + } + + vx_uint32 srcHeight() const + { + vx_uint32 v; + query(VX_REMAP_SOURCE_HEIGHT, v); + return v; + } + + vx_uint32 dstWidth() const + { + vx_uint32 v; + query(VX_REMAP_DESTINATION_WIDTH, v); + return v; + } + + vx_uint32 dstHeight() const + { + vx_uint32 v; + query(VX_REMAP_DESTINATION_HEIGHT, v); + return v; + } + + vx_uint32 srcCoordType() const + { return VX_TYPE_FLOAT32; } + + vx_uint32 dstCoordType() const + { return VX_TYPE_UINT32; } + + void setMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 src_x, vx_float32 src_y) + { IVX_CHECK_STATUS(vxSetRemapPoint(ref, dst_x, dst_y, src_x, src_y)); } + + void getMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 &src_x, vx_float32 &src_y) const + { IVX_CHECK_STATUS(vxGetRemapPoint(ref, dst_x, dst_y, &src_x, &src_y)); } + +#ifdef IVX_USE_OPENCV + void setMappings(const cv::Mat& map_x, const cv::Mat& map_y) + { + if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType())) + throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); + if ((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth()) + throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); + if ((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth()) + throw WrapperError(std::string(__func__) + "(): y mapping size is wrong"); + + for (vx_uint32 y = 0; y < dstHeight(); y++) + { + const vx_float32* map_x_line = map_x.ptr(y); + const vx_float32* map_y_line = map_y.ptr(y); + for (vx_uint32 x = 0; x < dstWidth(); x++) + setMapping(x, y, map_x_line[x], map_y_line[x]); + } + } + + void setMappings(const cv::Mat& map) + { + if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2) + throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); + if ((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth()) + throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); + + for (vx_uint32 y = 0; y < dstHeight(); y++) + { + const vx_float32* map_line = map.ptr(y); + for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2) + setMapping(x, y, map_line[x], map_line[x+1]); + } + } + + void getMappings(cv::Mat& map_x, cv::Mat& map_y) const + { + if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType())) + throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); + if (((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth()) && !map_x.empty()) + throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); + if (((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth()) && !map_y.empty()) + throw WrapperError(std::string(__func__) + "(): y mapping size is wrong"); + + if (map_x.empty()) + map_x = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType())); + if (map_y.empty()) + map_y = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType())); + + for (vx_uint32 y = 0; y < dstHeight(); y++) + { + vx_float32* map_x_line = map_x.ptr(y); + vx_float32* map_y_line = map_y.ptr(y); + for (vx_uint32 x = 0; x < dstWidth(); x++) + getMapping(x, y, map_x_line[x], map_y_line[x]); + } + } + + void getMappings(cv::Mat& map) const + { + if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2) + throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); + if (((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth()) && !map.empty()) + throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); + + if (map.empty()) + map = cv::Mat((int)dstHeight(), (int)dstWidth(), CV_MAKETYPE(CV_MAT_DEPTH(enumToCVType(srcCoordType())),2)); + + for (vx_uint32 y = 0; y < dstHeight(); y++) + { + vx_float32* map_line = map.ptr(y); + for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2) + getMapping(x, y, map_line[x], map_line[x+1]); + } + } +#endif //IVX_USE_OPENCV +}; + /// Standard nodes namespace nodes { diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index b027b9c39a..c7f5b3c31b 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -51,6 +51,8 @@ #include "opencl_kernels_imgproc.hpp" #include "hal_replacement.hpp" +#include "opencv2/core/openvx/ovx_defs.hpp" + using namespace cv; namespace cv @@ -4750,6 +4752,78 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst, } #endif +#ifdef HAVE_OPENVX +static bool openvx_remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, const Scalar& borderValue) +{ + vx_interpolation_type_e inter_type; + switch (interpolation) + { + case INTER_LINEAR: +#if VX_VERSION > VX_VERSION_1_0 + inter_type = VX_INTERPOLATION_BILINEAR; +#else + inter_type = VX_INTERPOLATION_TYPE_BILINEAR; +#endif + break; + case INTER_NEAREST: +#if VX_VERSION > VX_VERSION_1_0 + inter_type = VX_INTERPOLATION_NEAREST_NEIGHBOR; +#else + inter_type = VX_INTERPOLATION_TYPE_NEAREST_NEIGHBOR; +#endif + break; + case INTER_AREA://AREA interpolation mode is unsupported + default: + return false; + } + + try + { + ivx::Context ctx = ivx::Context::create(); + + 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, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(dst.cols, dst.rows, 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 + ivx::border_t prevBorder = ctx.immediateBorder(); + ctx.setImmediateBorder(VX_BORDER_CONSTANT, (vx_uint8)(borderValue[0])); + + ivx::Remap map = ivx::Remap::create(ctx, src.cols, src.rows, dst.cols, dst.rows); + if (map1.empty()) map.setMappings(map2); + else if (map2.empty()) map.setMappings(map1); + else map.setMappings(map1, map2); + ivx::IVX_CHECK_STATUS(vxuRemap(ctx, ia, map, inter_type, ib)); +#ifdef VX_VERSION_1_1 + ib.swapHandle(); + ia.swapHandle(); +#endif + + ctx.setImmediateBorder(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 + #if defined HAVE_IPP && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, @@ -4852,6 +4926,17 @@ void cv::remap( InputArray _src, OutputArray _dst, Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat(); _dst.create( map1.size(), src.type() ); Mat dst = _dst.getMat(); + + + CV_OVX_RUN( + src.type() == CV_8UC1 && dst.type() == CV_8UC1 && + (borderType& ~BORDER_ISOLATED) == BORDER_CONSTANT && + ((map1.type() == CV_32FC2 && map2.empty() && map1.size == dst.size) || + (map1.type() == CV_32FC1 && map2.type() == CV_32FC1 && map1.size == dst.size && map2.size == dst.size) || + (map1.empty() && map2.type() == CV_32FC2 && map2.size == dst.size)) && + ((borderType & BORDER_ISOLATED) != 0 || !src.isSubmatrix()), + openvx_remap(src, dst, map1, map2, interpolation, borderValue)); + CV_Assert( dst.cols < SHRT_MAX && dst.rows < SHRT_MAX && src.cols < SHRT_MAX && src.rows < SHRT_MAX ); if( dst.data == src.data )