From be7d060ea4cfb8b022ae1ebe54f8296a7fd73c6b Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Wed, 21 Dec 2016 16:19:06 +0300 Subject: [PATCH] Merge pull request #7802 from terfendail:ovxhal_wrappers_migration * OpenVX HAL updated to use generic OpenVX wrappers * vxErr class from OpenVX HAL replaced with ivx::WrapperError * reduced usage of vxImage class from OpenVX HAL replaced with ivx::Image * vxImage class rewritten as ivx::Image subclass that calls swapHandle prior release * Fix OpenVX HAL build * Fix for review comments --- 3rdparty/openvx/hal/openvx_hal.cpp | 1086 ++++++++++++++++++++++++- 3rdparty/openvx/hal/openvx_hal.hpp | 1202 +--------------------------- 3rdparty/openvx/include/ivx.hpp | 46 +- modules/imgproc/src/deriv.cpp | 15 +- modules/imgproc/src/pyramids.cpp | 2 +- modules/imgproc/src/smooth.cpp | 31 +- 6 files changed, 1174 insertions(+), 1208 deletions(-) diff --git a/3rdparty/openvx/hal/openvx_hal.cpp b/3rdparty/openvx/hal/openvx_hal.cpp index e95bbb2b58..f7962d1eb5 100644 --- a/3rdparty/openvx/hal/openvx_hal.cpp +++ b/3rdparty/openvx/hal/openvx_hal.cpp @@ -1,8 +1,1088 @@ #include "openvx_hal.hpp" -vxContext * vxContext::getContext() +#define IVX_HIDE_INFO_WARNINGS +#include "ivx.hpp" + +#include +#include + +#include +#include +#include +#include + +//================================================================================================== +// utility +// ... + +#if 0 +#include +#define PRINT(...) printf(__VA_ARGS__) +#define PRINT_HALERR_MSG(type) PRINT("OpenVX HAL impl "#type" error: %s\n", e.what()) +#else +#define PRINT(...) +#define PRINT_HALERR_MSG(type) (void)e +#endif + + +#if __cplusplus >= 201103L +#include +struct Tick +{ + typedef std::chrono::time_point point_t; + point_t start; + point_t point; + Tick() + { + start = std::chrono::steady_clock::now(); + point = std::chrono::steady_clock::now(); + } + inline int one() + { + point_t old = point; + point = std::chrono::steady_clock::now(); + return std::chrono::duration_cast(point - old).count(); + } + inline int total() + { + return std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + } +}; +#endif + +inline ivx::Context& getOpenVXHALContext() { // not thread safe - static vxContext instance; - return &instance; + static ivx::Context instance = ivx::Context::create(); + return instance; +} + +inline bool dimTooBig(int size) +{ + static vx_uint16 current_vendor = getOpenVXHALContext().vendorID(); + + if (current_vendor == VX_ID_KHRONOS || current_vendor == VX_ID_DEFAULT) + { + //OpenVX use uint32_t for image addressing + return ((unsigned)size > (UINT_MAX / VX_SCALE_UNITY)); + } + else + return false; +} + +inline void setConstantBorder(ivx::border_t &border, vx_uint8 val) +{ + border.mode = VX_BORDER_CONSTANT; +#if VX_VERSION > VX_VERSION_1_0 + border.constant_value.U8 = val; +#else + border.constant_value = val; +#endif +} + +inline void refineStep(int w, int h, int imgType, size_t& step) +{ + if (h == 1) + step = w * ((imgType == VX_DF_IMAGE_RGBX || + imgType == VX_DF_IMAGE_U32 || imgType == VX_DF_IMAGE_S32) ? 4 : + imgType == VX_DF_IMAGE_RGB ? 3 : + (imgType == VX_DF_IMAGE_U16 || imgType == VX_DF_IMAGE_S16 || + imgType == VX_DF_IMAGE_UYVY || imgType == VX_DF_IMAGE_YUYV) ? 2 : 1); +} + +//================================================================================================== +// ivx::Image wrapped to simplify call to swapHandle prior to release +// TODO update ivx::Image to handle swapHandle prior to release on the own + +class vxImage: public ivx::Image +{ +public: + vxImage(const ivx::Image &_img) : ivx::Image(_img) {} + + ~vxImage() + { +#if VX_VERSION > VX_VERSION_1_0 + swapHandle(); +#endif + } +}; + +//================================================================================================== +// real code starts here +// ... + +#define OVX_BINARY_OP(hal_func, ovx_call) \ +template \ +int ovx_hal_##hal_func(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h) \ +{ \ + if(dimTooBig(w) || dimTooBig(h)) \ + return CV_HAL_ERROR_NOT_IMPLEMENTED; \ + refineStep(w, h, ivx::TypeToEnum::imgType, astep); \ + refineStep(w, h, ivx::TypeToEnum::imgType, bstep); \ + refineStep(w, h, ivx::TypeToEnum::imgType, cstep); \ + try \ + { \ + ivx::Context ctx = getOpenVXHALContext(); \ + vxImage \ + ia = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, \ + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(astep)), (void*)a), \ + ib = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, \ + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(bstep)), (void*)b), \ + ic = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, \ + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(cstep)), (void*)c); \ + ovx_call \ + } \ + catch (ivx::RuntimeError & e) \ + { \ + PRINT_HALERR_MSG(runtime); \ + return CV_HAL_ERROR_UNKNOWN; \ + } \ + catch (ivx::WrapperError & e) \ + { \ + PRINT_HALERR_MSG(wrapper); \ + return CV_HAL_ERROR_UNKNOWN; \ + } \ + return CV_HAL_ERROR_OK; \ +} + +OVX_BINARY_OP(add, { ivx::IVX_CHECK_STATUS(vxuAdd(ctx, ia, ib, VX_CONVERT_POLICY_SATURATE, ic)); }) +OVX_BINARY_OP(sub, { ivx::IVX_CHECK_STATUS(vxuSubtract(ctx, ia, ib, VX_CONVERT_POLICY_SATURATE, ic)); }) + +OVX_BINARY_OP(absdiff, { ivx::IVX_CHECK_STATUS(vxuAbsDiff(ctx, ia, ib, ic)); }) + +OVX_BINARY_OP(and, { ivx::IVX_CHECK_STATUS(vxuAnd(ctx, ia, ib, ic)); }) +OVX_BINARY_OP(or , { ivx::IVX_CHECK_STATUS(vxuOr(ctx, ia, ib, ic)); }) +OVX_BINARY_OP(xor, { ivx::IVX_CHECK_STATUS(vxuXor(ctx, ia, ib, ic)); }) + +template +int ovx_hal_mul(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, double scale) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, ivx::TypeToEnum::imgType, astep); + refineStep(w, h, ivx::TypeToEnum::imgType, bstep); + refineStep(w, h, ivx::TypeToEnum::imgType, cstep); +#ifdef _MSC_VER + const float MAGIC_SCALE = 0x0.01010102; +#else + const float MAGIC_SCALE = 0x1.010102p-8; +#endif + try + { + int rounding_policy = VX_ROUND_POLICY_TO_ZERO; + float fscale = (float)scale; + if (fabs(fscale - MAGIC_SCALE) > FLT_EPSILON) + { + int exp = 0; + double significand = frexp(fscale, &exp); + if ((significand != 0.5) || (exp > 1) || (exp < -14)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + else + { + fscale = MAGIC_SCALE; + rounding_policy = VX_ROUND_POLICY_TO_NEAREST_EVEN;// That's the only rounding that MUST be supported for 1/255 scale + } + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(bstep)), (void*)b), + ic = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum::imgType, + ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(cstep)), (void*)c); + ivx::IVX_CHECK_STATUS(vxuMultiply(ctx, ia, ib, fscale, VX_CONVERT_POLICY_SATURATE, rounding_policy, ic)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +template int ovx_hal_add(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); +template int ovx_hal_add(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h); +template int ovx_hal_sub(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); +template int ovx_hal_sub(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h); + +template int ovx_hal_absdiff(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); +template int ovx_hal_absdiff(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h); + +template int ovx_hal_and(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); +template int ovx_hal_or(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); +template int ovx_hal_xor(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h); + +template int ovx_hal_mul(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h, double scale); +template int ovx_hal_mul(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h, double scale); + +int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, VX_DF_IMAGE_U8, astep); + refineStep(w, h, VX_DF_IMAGE_U8, cstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a), + ic = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)(cstep)), (void*)c); + ivx::IVX_CHECK_STATUS(vxuNot(ctx, ia, ic)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int cn) +{ + if (dimTooBig(len)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (cn != 3 && cn != 4) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[0]), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[1]), + ic = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[2]), + id = ivx::Image::createFromHandle(ctx, cn == 4 ? VX_DF_IMAGE_RGBX : VX_DF_IMAGE_RGB, + ivx::Image::createAddressing(len, 1, cn, (vx_int32)(len*cn)), (void*)dst_data); + ivx::IVX_CHECK_STATUS(vxuChannelCombine(ctx, ia, ib, ic, + cn == 4 ? (vx_image)(ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[3])) : NULL, + id)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, double inv_scale_x, double inv_scale_y, int interpolation) +{ + if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(aw, ah, VX_DF_IMAGE_U8, astep); + refineStep(bw, bh, VX_DF_IMAGE_U8, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b); + + if (!((atype == CV_8UC1 || atype == CV_8SC1) && + inv_scale_x > 0 && inv_scale_y > 0 && + (bw - 0.5) / inv_scale_x - 0.5 < aw && (bh - 0.5) / inv_scale_y - 0.5 < ah && + (bw + 0.5) / inv_scale_x + 0.5 >= aw && (bh + 0.5) / inv_scale_y + 0.5 >= ah && + std::abs(bw / inv_scale_x - aw) < 0.1 && std::abs(bh / inv_scale_y - ah) < 0.1)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + { + mode = VX_INTERPOLATION_BILINEAR; + if (inv_scale_x > 1 || inv_scale_y > 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + else if (interpolation == CV_HAL_INTER_AREA) + return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + ivx::IVX_CHECK_STATUS(vxuScaleImage(ctx, ia, ib, mode)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int borderType, const double borderValue[4]) +{ + if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(aw, ah, VX_DF_IMAGE_U8, astep); + refineStep(bw, bh, VX_DF_IMAGE_U8, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b); + + if (!(atype == CV_8UC1 || atype == CV_8SC1)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if(borderType != CV_HAL_BORDER_CONSTANT) // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + //AREA interpolation is unsupported + //else if (interpolation == CV_HAL_INTER_AREA) + // mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + std::vector data; + data.reserve(6); + for (int j = 0; j < 3; ++j) + for (int i = 0; i < 2; ++i) + data.push_back((float)(M[i * 3 + j])); + + ivx::Matrix mtx = ivx::Matrix::create(ctx, VX_TYPE_FLOAT32, 2, 3); + mtx.copyFrom(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::IVX_CHECK_STATUS(vxuWarpAffine(ctx, ia, mtx, mode, ib)); + ctx.setImmediateBorder(prevBorder); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int borderType, const double borderValue[4]) +{ + if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(aw, ah, VX_DF_IMAGE_U8, astep); + refineStep(bw, bh, VX_DF_IMAGE_U8, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b); + + if (!(atype == CV_8UC1 || atype == CV_8SC1)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (borderType != CV_HAL_BORDER_CONSTANT) // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + //AREA interpolation is unsupported + //else if (interpolation == CV_HAL_INTER_AREA) + // mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + std::vector data; + data.reserve(9); + for (int j = 0; j < 3; ++j) + for (int i = 0; i < 3; ++i) + data.push_back((float)(M[i * 3 + j])); + + ivx::Matrix mtx = ivx::Matrix::create(ctx, VX_TYPE_FLOAT32, 3, 3); + mtx.copyFrom(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::IVX_CHECK_STATUS(vxuWarpPerspective(ctx, ia, mtx, mode, ib)); + ctx.setImmediateBorder(prevBorder); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +struct cvhalFilter2D; + +struct FilterCtx +{ + ivx::Convolution cnv; + int dst_type; + ivx::border_t border; + FilterCtx(ivx::Context &ctx, const std::vector data, int w, int h, int _dst_type, ivx::border_t & _border) : + cnv(ivx::Convolution::create(ctx, w, h)), dst_type(_dst_type), border(_border) { + cnv.copyFrom(data); + } +}; + +int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int, int, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace) +{ + if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || delta != 0 || + src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || + kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + ivx::border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + setConstantBorder(border, 0); + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + ivx::Context ctx = getOpenVXHALContext(); + + std::vector data; + data.reserve(kernel_width*kernel_height); + switch (kernel_type) + { + case CV_8UC1: + for (int j = 0; j < kernel_height; ++j) + { + uchar * row = (uchar*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + break; + case CV_8SC1: + for (int j = 0; j < kernel_height; ++j) + { + schar * row = (schar*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + break; + case CV_16SC1: + for (int j = 0; j < kernel_height; ++j) + { + short * row = (short*)(kernel_data + kernel_step*j); + for (int i = 0; i < kernel_width; ++i) + data.push_back(row[i]); + } + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + FilterCtx* cnv = new FilterCtx(ctx, data, kernel_width, kernel_height, dst_type, border); + if (!cnv) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(cnv); + return CV_HAL_ERROR_OK; +} + +int ovx_hal_filterFree(cvhalFilter2D *filter_context) +{ + if (filter_context) + { + delete (FilterCtx*)filter_context; + return CV_HAL_ERROR_OK; + } + else + { + return CV_HAL_ERROR_UNKNOWN; + } +} + +int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int, int, int, int) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + try + { + FilterCtx* cnv = (FilterCtx*)filter_context; + if (!cnv) + throw ivx::WrapperError("Bad HAL context"); + refineStep(w, h, VX_DF_IMAGE_U8, astep); + refineStep(w, h, cnv->dst_type == CV_16SC1 ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8, bstep); + + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, cnv->dst_type == CV_16SC1 ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, cnv->dst_type == CV_16SC1 ? 2 : 1, (vx_int32)(bstep)), (void*)b); + + //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(cnv->border); + ivx::IVX_CHECK_STATUS(vxuConvolve(ctx, ia, cnv->cnv, ib)); + ctx.setImmediateBorder(prevBorder); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_sepFilterInit(cvhalFilter2D **filter_context, int src_type, int dst_type, + int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, + int anchor_x, int anchor_y, double delta, int borderType) +{ + if (!filter_context || !kernelx_data || !kernely_data || delta != 0 || + src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || + kernelx_length % 2 == 0 || kernely_length % 2 == 0 || anchor_x != kernelx_length / 2 || anchor_y != kernely_length / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + ivx::border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + setConstantBorder(border, 0); + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + ivx::Context ctx = getOpenVXHALContext(); + + //At the moment OpenVX doesn't support separable filters natively so combine kernels to generic convolution + std::vector data; + data.reserve(kernelx_length*kernely_length); + switch (kernel_type) + { + case CV_8UC1: + for (int j = 0; j < kernely_length; ++j) + for (int i = 0; i < kernelx_length; ++i) + data.push_back((short)(kernely_data[j]) * kernelx_data[i]); + break; + case CV_8SC1: + for (int j = 0; j < kernely_length; ++j) + for (int i = 0; i < kernelx_length; ++i) + data.push_back((short)(((schar*)kernely_data)[j]) * ((schar*)kernelx_data)[i]); + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + FilterCtx* cnv = new FilterCtx(ctx, data, kernelx_length, kernely_length, dst_type, border); + if (!cnv) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(cnv); + return CV_HAL_ERROR_OK; +} + +#if VX_VERSION > VX_VERSION_1_0 + +struct MorphCtx +{ + ivx::Matrix mask; + int operation; + ivx::border_t border; + MorphCtx(ivx::Context &ctx, const std::vector data, int w, int h, int _operation, ivx::border_t & _border) : + mask(ivx::Matrix::create(ctx, ivx::TypeToEnum::value, w, h)), operation(_operation), border(_border) { + mask.copyFrom(data); + } +}; + +int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int, int, + int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) +{ + if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || iterations != 1 || + src_type != CV_8UC1 || dst_type != CV_8UC1 || + kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + ivx::border_t border; + switch (borderType) + { + case CV_HAL_BORDER_CONSTANT: + if (borderValue[0] == DBL_MAX && borderValue[1] == DBL_MAX && borderValue[2] == DBL_MAX && borderValue[3] == DBL_MAX) + { + if (operation == MORPH_ERODE) + setConstantBorder(border, UCHAR_MAX); + else + setConstantBorder(border, 0); + } + else + { + int rounded = (int)round(borderValue[0]); + setConstantBorder(border, (vx_uint8)((unsigned)rounded <= UCHAR_MAX ? rounded : rounded > 0 ? UCHAR_MAX : 0)); + } + break; + case CV_HAL_BORDER_REPLICATE: + border.mode = VX_BORDER_REPLICATE; + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + ivx::Context ctx = getOpenVXHALContext(); + + vx_size maxKernelDim = ctx.nonlinearMaxDimension(); + if ((vx_size)kernel_width > maxKernelDim || (vx_size)kernel_height > maxKernelDim) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + std::vector kernel_mat; + kernel_mat.reserve(kernel_width * kernel_height); + switch (CV_MAT_DEPTH(kernel_type)) + { + case CV_8U: + case CV_8S: + for (int j = 0; j < kernel_height; ++j) + { + uchar * kernel_row = kernel_data + j * kernel_step; + for (int i = 0; i < kernel_width; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_16U: + case CV_16S: + for (int j = 0; j < kernel_height; ++j) + { + short * kernel_row = (short*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_width; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_32S: + for (int j = 0; j < kernel_height; ++j) + { + int * kernel_row = (int*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_width; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_32F: + for (int j = 0; j < kernel_height; ++j) + { + float * kernel_row = (float*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_width; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + case CV_64F: + for (int j = 0; j < kernel_height; ++j) + { + double * kernel_row = (double*)(kernel_data + j * kernel_step); + for (int i = 0; i < kernel_width; ++i) + kernel_mat.push_back(kernel_row[i] ? 255 : 0); + } + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + MorphCtx* mat; + switch (operation) + { + case MORPH_ERODE: + mat = new MorphCtx(ctx, kernel_mat, kernel_width, kernel_height, VX_NONLINEAR_FILTER_MIN, border); + break; + case MORPH_DILATE: + mat = new MorphCtx(ctx, kernel_mat, kernel_width, kernel_height, VX_NONLINEAR_FILTER_MAX, border); + break; + default: + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + if (!mat) + return CV_HAL_ERROR_UNKNOWN; + + *filter_context = (cvhalFilter2D*)(mat); + return CV_HAL_ERROR_OK; +} + +int ovx_hal_morphFree(cvhalFilter2D *filter_context) +{ + if (filter_context) + { + delete (MorphCtx*)filter_context; + return CV_HAL_ERROR_OK; + } + else + { + return CV_HAL_ERROR_UNKNOWN; + } +} + +int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int, int, int, int, int, int, int, int) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, VX_DF_IMAGE_U8, astep); + refineStep(w, h, VX_DF_IMAGE_U8, bstep); + try + { + MorphCtx* mat = (MorphCtx*)filter_context; + if (!mat) + throw ivx::WrapperError("Bad HAL context"); + + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)(bstep)), (void*)b); + + //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(mat->border); + ivx::IVX_CHECK_STATUS(vxuNonLinearFilter(ctx, mat->operation, ia, mat->mask, ib)); + ctx.setImmediateBorder(prevBorder); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +#endif // 1.0 guard + +int ovx_hal_cvtBGRtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int acn, int bcn, bool swapBlue) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (depth != CV_8U || swapBlue || acn == bcn || (acn != 3 && acn != 4) || (bcn != 3 && bcn != 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (w & 1 || h & 1) // It's strange but sample implementation unable to convert odd sized images + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, astep); + refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, acn, (vx_int32)astep), (void*)a), + ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b); + ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int bcn) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (depth != CV_8U || (bcn != 3 && bcn != 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, VX_DF_IMAGE_U8, astep); + refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + ivx::Image + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)astep), const_cast(a)), + ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b); + ivx::IVX_CHECK_STATUS(vxuChannelCombine(ctx, ia, ia, ia, + bcn == 4 ? (vx_image)(ivx::Image::createUniform(ctx, w, h, VX_DF_IMAGE_U8, vx_uint8(255))) : NULL, + ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (!swapBlue || (bcn != 3 && bcn != 4)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, astep); + refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + + std::vector addr; + std::vector ptrs; + addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)astep)); + ptrs.push_back((void*)a); + addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 2, (vx_int32)astep)); + ptrs.push_back((void*)(a + h * astep)); + + vxImage + ia = ivx::Image::createFromHandle(ctx, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, addr, ptrs); + if (ia.range() == VX_CHANNEL_RANGE_FULL) + return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL + vxImage + ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b); + ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx || (size_t)w / 2 != astep - (size_t)w / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, VX_DF_IMAGE_IYUV, astep); + refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + + std::vector addr; + std::vector ptrs; + addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)astep)); + ptrs.push_back((void*)a); + addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2)); + ptrs.push_back((void*)(a + h * astep)); + if (addr[1].dim_x != (astep - addr[1].dim_x)) + throw ivx::WrapperError("UV planes use variable stride"); + addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2)); + ptrs.push_back((void*)(a + h * astep + addr[1].dim_y * addr[1].stride_y)); + + vxImage + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_IYUV, addr, ptrs); + if (ia.range() == VX_CHANNEL_RANGE_FULL) + return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL + vxImage + ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b); + ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (!swapBlue || (acn != 3 && acn != 4) || uIdx || (size_t)w / 2 != bstep - (size_t)w / 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, astep); + refineStep(w, h, VX_DF_IMAGE_IYUV, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, acn, (vx_int32)astep), (void*)a); + + std::vector addr; + std::vector ptrs; + addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)bstep)); + ptrs.push_back((void*)b); + addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2)); + ptrs.push_back((void*)(b + h * bstep)); + if (addr[1].dim_x != (bstep - addr[1].dim_x)) + throw ivx::WrapperError("UV planes use variable stride"); + addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2)); + ptrs.push_back((void*)(b + h * bstep + addr[1].dim_y * addr[1].stride_y)); + + vxImage + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_IYUV, addr, ptrs); + ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_cvtOnePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx, int ycn) +{ + if (dimTooBig(w) || dimTooBig(h)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if (w & 1) // It's not described in spec but sample implementation unable to convert odd sized images + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV, astep); + refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + vxImage + ia = ivx::Image::createFromHandle(ctx, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV, + ivx::Image::createAddressing(w, h, 2, (vx_int32)astep), (void*)a); + if (ia.range() == VX_CHANNEL_RANGE_FULL) + return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL + vxImage + ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, + ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b); + ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib)); + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +int ovx_hal_integral(int depth, int sdepth, int, const uchar * a, size_t astep, uchar * b, size_t bstep, uchar * c, size_t, uchar * d, size_t, int w, int h, int cn) +{ + if (depth != CV_8U || sdepth != CV_32S || c != NULL || d != NULL || cn != 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + refineStep(w, h, VX_DF_IMAGE_U8, astep); + try + { + ivx::Context ctx = getOpenVXHALContext(); + ivx::Image + ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(w, h, 1, (vx_int32)astep), const_cast(a)), + ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U32, + ivx::Image::createAddressing(w, h, 1, (vx_int32)bstep), (unsigned int *)(b + bstep + sizeof(unsigned int))); + ivx::IVX_CHECK_STATUS(vxuIntegralImage(ctx, ia, ib)); + memset(b, 0, (w + 1) * sizeof(unsigned int)); + b += bstep; + for (int i = 0; i < h; i++, b += bstep) + { + *((unsigned int*)b) = 0; + } + } + catch (ivx::RuntimeError & e) + { + PRINT_HALERR_MSG(runtime); + return CV_HAL_ERROR_UNKNOWN; + } + catch (ivx::WrapperError & e) + { + PRINT_HALERR_MSG(wrapper); + return CV_HAL_ERROR_UNKNOWN; + } + + return CV_HAL_ERROR_OK; } diff --git a/3rdparty/openvx/hal/openvx_hal.hpp b/3rdparty/openvx/hal/openvx_hal.hpp index 7dd89addb2..63da1fa5b3 100644 --- a/3rdparty/openvx/hal/openvx_hal.hpp +++ b/3rdparty/openvx/hal/openvx_hal.hpp @@ -5,1185 +5,55 @@ #include "opencv2/imgproc/hal/interface.h" #include "VX/vx.h" -#include "VX/vxu.h" - -#include -#include - -#include -#include -#include -#include - -#ifndef VX_VENDOR_ID -#define VX_VENDOR_ID VX_ID_DEFAULT -#endif - -#if VX_VERSION == VX_VERSION_1_0 - -static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST; -static const vx_enum VX_INTERPOLATION_BILINEAR = VX_INTERPOLATION_TYPE_BILINEAR; -static const vx_enum VX_INTERPOLATION_AREA = VX_INTERPOLATION_TYPE_AREA; -static const vx_enum VX_INTERPOLATION_NEAREST_NEIGHBOR = VX_INTERPOLATION_TYPE_NEAREST_NEIGHBOR; -static const vx_enum VX_IMAGE_RANGE = VX_IMAGE_ATTRIBUTE_RANGE; -static const vx_enum VX_IMAGE_SPACE = VX_IMAGE_ATTRIBUTE_SPACE; -typedef vx_border_mode_t vx_border_t; -static const vx_enum VX_BORDER_CONSTANT = VX_BORDER_MODE_CONSTANT; -static const vx_enum VX_BORDER_REPLICATE = VX_BORDER_MODE_REPLICATE; -static const vx_enum VX_CONTEXT_IMMEDIATE_BORDER = VX_CONTEXT_ATTRIBUTE_IMMEDIATE_BORDER_MODE; - -#endif - -//================================================================================================== -// utility -// ... - -#if 0 -#include -#define PRINT(...) printf(__VA_ARGS__) -#else -#define PRINT(...) -#endif - -#if __cplusplus >= 201103L -#include -struct Tick -{ - typedef std::chrono::time_point point_t; - point_t start; - point_t point; - Tick() - { - start = std::chrono::steady_clock::now(); - point = std::chrono::steady_clock::now(); - } - inline int one() - { - point_t old = point; - point = std::chrono::steady_clock::now(); - return std::chrono::duration_cast(point - old).count(); - } - inline int total() - { - return std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); - } -}; -#endif - -inline bool dimTooBig(int size) -{ - if (VX_VENDOR_ID == VX_ID_KHRONOS || VX_VENDOR_ID == VX_ID_DEFAULT) - { - //OpenVX use uint32_t for image addressing - return ((unsigned)size > (UINT_MAX / VX_SCALE_UNITY)); - } - else - return false; -} - -//================================================================================================== -// One more OpenVX C++ binding :-) -// ... template -struct VX_Traits -{ - enum { - ImgType = 0, - DataType = 0 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = VX_DF_IMAGE_U8, - DataType = VX_TYPE_UINT8 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = VX_DF_IMAGE_U16, - DataType = VX_TYPE_UINT16 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = VX_DF_IMAGE_S16, - DataType = VX_TYPE_INT16 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = VX_DF_IMAGE_U32, - DataType = VX_TYPE_UINT32 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = VX_DF_IMAGE_S32, - DataType = VX_TYPE_INT32 - }; -}; - -template <> -struct VX_Traits -{ - enum { - ImgType = 0, - DataType = VX_TYPE_FLOAT32 - }; -}; - - -struct vxContext; -struct vxImage; -struct vxErr; - - -struct vxErr -{ - vx_status status; - std::string msg; - vxErr(vx_status status_, const std::string & msg_) : status(status_), msg(msg_) {} - void check() - { - if (status != VX_SUCCESS) - throw *this; - } - void print() - { - PRINT("OpenVX HAL impl error: %d (%s)\n", status, msg.c_str()); - } - static void check(vx_context ctx) - { - vxErr(vxGetStatus((vx_reference)ctx), "context check").check(); - } - static void check(vx_image img) - { - vxErr(vxGetStatus((vx_reference)img), "image check").check(); - } - static void check(vx_matrix mtx) - { - vxErr(vxGetStatus((vx_reference)mtx), "matrix check").check(); - } - static void check(vx_convolution cnv) - { - vxErr(vxGetStatus((vx_reference)cnv), "convolution check").check(); - } - static void check(vx_status s) - { - vxErr(s, "status check").check(); - } -}; - - -struct vxContext -{ - vx_context ctx; - static vxContext * getContext(); -private: - vxContext() - { - ctx = vxCreateContext(); - vxErr::check(ctx); - } - ~vxContext() - { - vxReleaseContext(&ctx); - } -}; - - -struct vxImage -{ - vx_image img; - - template - vxImage(vxContext &ctx, const T *data, size_t step, int w, int h) - { - if (h == 1) - step = w * sizeof(T); - vx_imagepatch_addressing_t addr; - addr.dim_x = w; - addr.dim_y = h; - addr.stride_x = sizeof(T); - addr.stride_y = (vx_int32)step; - void *ptrs[] = { (void*)data }; - img = vxCreateImageFromHandle(ctx.ctx, VX_Traits::ImgType, &addr, ptrs, VX_MEMORY_TYPE_HOST); - vxErr::check(img); - swapMemory = true; - } - template - vxImage(vxContext &ctx, T value, int w, int h) - { -#if VX_VERSION > VX_VERSION_1_0 - vx_pixel_value_t pixel; - switch ((int)(VX_Traits::DataType)) - { - case VX_TYPE_UINT8:pixel.U8 = value; break; - case VX_TYPE_UINT16:pixel.U16 = value; break; - case VX_TYPE_INT16:pixel.S16 = value; break; - default:vxErr(VX_ERROR_INVALID_PARAMETERS, "uniform image creation").check(); - } - img = vxCreateUniformImage(ctx.ctx, w, h, VX_Traits::ImgType, &pixel); -#else - img = vxCreateUniformImage(ctx.ctx, w, h, VX_Traits::ImgType, &value); -#endif - vxErr::check(img); - swapMemory = false; - } - vxImage(vxContext &ctx, int imgType, const uchar *data, size_t step, int w, int h) - { - if (h == 1) - step = w * ((imgType == VX_DF_IMAGE_RGBX || - imgType == VX_DF_IMAGE_U32 || imgType == VX_DF_IMAGE_S32) ? 4 : - imgType == VX_DF_IMAGE_RGB ? 3 : - (imgType == VX_DF_IMAGE_U16 || imgType == VX_DF_IMAGE_S16 || - imgType == VX_DF_IMAGE_UYVY || imgType == VX_DF_IMAGE_YUYV) ? 2 : 1); - - vx_imagepatch_addressing_t addr[4]; - void *ptrs[4]; - switch (imgType) - { - case VX_DF_IMAGE_U8: - case VX_DF_IMAGE_U16: - case VX_DF_IMAGE_S16: - case VX_DF_IMAGE_U32: - case VX_DF_IMAGE_S32: - case VX_DF_IMAGE_RGB: - case VX_DF_IMAGE_RGBX: - case VX_DF_IMAGE_UYVY: - case VX_DF_IMAGE_YUYV: - addr[0].dim_x = w; - addr[0].dim_y = h; - addr[0].stride_x = imgType == VX_DF_IMAGE_U8 ? 1 : - imgType == VX_DF_IMAGE_RGB ? 3 : - (imgType == VX_DF_IMAGE_U16 || imgType == VX_DF_IMAGE_S16 || - imgType == VX_DF_IMAGE_UYVY || imgType == VX_DF_IMAGE_YUYV) ? 2 : 4; - addr[0].stride_y = (vx_int32)step; - ptrs[0] = (void*)data; - break; - case VX_DF_IMAGE_NV12: - case VX_DF_IMAGE_NV21: - addr[0].dim_x = w; - addr[0].dim_y = h; - addr[0].stride_x = 1; - addr[0].stride_y = (vx_int32)step; - ptrs[0] = (void*)data; - addr[1].dim_x = w / 2; - addr[1].dim_y = h / 2; - addr[1].stride_x = 2; - addr[1].stride_y = (vx_int32)step; - ptrs[1] = (void*)(data + h * step); - break; - case VX_DF_IMAGE_IYUV: - case VX_DF_IMAGE_YUV4: - addr[0].dim_x = w; - addr[0].dim_y = h; - addr[0].stride_x = 1; - addr[0].stride_y = (vx_int32)step; - ptrs[0] = (void*)data; - addr[1].dim_x = imgType == VX_DF_IMAGE_YUV4 ? w : w / 2; - addr[1].dim_y = imgType == VX_DF_IMAGE_YUV4 ? h : h / 2; - if (addr[1].dim_x != (step - addr[1].dim_x)) - vxErr(VX_ERROR_INVALID_PARAMETERS, "UV planes use variable stride").check(); - addr[1].stride_x = 1; - addr[1].stride_y = (vx_int32)addr[1].dim_x; - ptrs[1] = (void*)(data + h * step); - addr[2].dim_x = addr[1].dim_x; - addr[2].dim_y = addr[1].dim_y; - addr[2].stride_x = 1; - addr[2].stride_y = addr[1].stride_y; - ptrs[2] = (void*)(data + h * step + addr[1].dim_y * addr[1].stride_y); - break; - default: - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad image format").check(); - } - img = vxCreateImageFromHandle(ctx.ctx, imgType, addr, ptrs, VX_MEMORY_TYPE_HOST); - vxErr::check(img); - swapMemory = true; - } - ~vxImage() - { -#if VX_VERSION > VX_VERSION_1_0 - if (swapMemory) - vxErr::check(vxSwapImageHandle(img, NULL, NULL, 1)); -#endif - vxReleaseImage(&img); - } -private: - bool swapMemory; -}; - -struct vxMatrix -{ - vx_matrix mtx; - - template - vxMatrix(vxContext &ctx, const T *data, int w, int h) - { - mtx = vxCreateMatrix(ctx.ctx, VX_Traits::DataType, w, h); - vxErr::check(mtx); -#if VX_VERSION > VX_VERSION_1_0 - vxErr::check(vxCopyMatrix(mtx, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); -#else - vxErr::check(vxWriteMatrix(mtx, const_cast(data))); -#endif - } - ~vxMatrix() - { - vxReleaseMatrix(&mtx); - } -}; - -struct vxConvolution -{ - vx_convolution cnv; - - vxConvolution(vxContext &ctx, const short *data, int w, int h) - { - cnv = vxCreateConvolution(ctx.ctx, w, h); - vxErr::check(cnv); -#if VX_VERSION > VX_VERSION_1_0 - vxErr::check(vxCopyConvolutionCoefficients(cnv, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); -#else - vxErr::check(vxWriteConvolutionCoefficients(cnv, const_cast(data))); -#endif - } - ~vxConvolution() - { - vxReleaseConvolution(&cnv); - } -}; - -inline void setConstantBorder(vx_border_t &border, vx_uint8 val) -{ - border.mode = VX_BORDER_CONSTANT; -#if VX_VERSION > VX_VERSION_1_0 - border.constant_value.U8 = val; -#else - border.constant_value = val; -#endif -} - -//================================================================================================== -// real code starts here -// ... - -#define OVX_BINARY_OP(hal_func, ovx_call) \ -template \ -inline int ovx_hal_##hal_func(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h) \ -{ \ - if(dimTooBig(w) || dimTooBig(h)) \ - return CV_HAL_ERROR_NOT_IMPLEMENTED; \ - try \ - { \ - vxContext * ctx = vxContext::getContext(); \ - vxImage ia(*ctx, a, astep, w, h); \ - vxImage ib(*ctx, b, bstep, w, h); \ - vxImage ic(*ctx, c, cstep, w, h); \ - ovx_call \ - } \ - catch (vxErr & e) \ - { \ - e.print(); \ - return CV_HAL_ERROR_UNKNOWN; \ - } \ - return CV_HAL_ERROR_OK; \ -} - -OVX_BINARY_OP(add, {vxErr::check(vxuAdd(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img));}) -OVX_BINARY_OP(sub, {vxErr::check(vxuSubtract(ctx->ctx, ia.img, ib.img, VX_CONVERT_POLICY_SATURATE, ic.img));}) - -OVX_BINARY_OP(absdiff, {vxErr::check(vxuAbsDiff(ctx->ctx, ia.img, ib.img, ic.img));}) - -OVX_BINARY_OP(and, {vxErr::check(vxuAnd(ctx->ctx, ia.img, ib.img, ic.img));}) -OVX_BINARY_OP(or, {vxErr::check(vxuOr(ctx->ctx, ia.img, ib.img, ic.img));}) -OVX_BINARY_OP(xor, {vxErr::check(vxuXor(ctx->ctx, ia.img, ib.img, ic.img));}) +int ovx_hal_add(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); +template +int ovx_hal_sub(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); template -inline int ovx_hal_mul(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, double scale) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; -#ifdef _MSC_VER - const float MAGIC_SCALE = 0x0.01010102; -#else - const float MAGIC_SCALE = 0x1.010102p-8; -#endif - try - { - int rounding_policy = VX_ROUND_POLICY_TO_ZERO; - float fscale = (float)scale; - if (fabs(fscale - MAGIC_SCALE) > FLT_EPSILON) - { - int exp = 0; - double significand = frexp(fscale, &exp); - if((significand != 0.5) || (exp > 1) || (exp < -14)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - else - { - fscale = MAGIC_SCALE; - rounding_policy = VX_ROUND_POLICY_TO_NEAREST_EVEN;// That's the only rounding that MUST be supported for 1/255 scale - } - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - vxImage ib(*ctx, b, bstep, w, h); - vxImage ic(*ctx, c, cstep, w, h); - vxErr::check(vxuMultiply(ctx->ctx, ia.img, ib.img, fscale, VX_CONVERT_POLICY_SATURATE, rounding_policy, ic.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} +int ovx_hal_absdiff(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); -inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - vxImage ic(*ctx, c, cstep, w, h); - vxErr::check(vxuNot(ctx->ctx, ia.img, ic.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} +template +int ovx_hal_and(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); +template +int ovx_hal_or(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); +template +int ovx_hal_xor(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h); +int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h); -inline int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int cn) -{ - if(dimTooBig(len)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (cn != 3 && cn != 4) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, src_data[0], len, len, 1); - vxImage ib(*ctx, src_data[1], len, len, 1); - vxImage ic(*ctx, src_data[2], len, len, 1); - vxImage id(*ctx, cn == 4 ? VX_DF_IMAGE_RGBX : VX_DF_IMAGE_RGB, dst_data, len, len, 1); - vxErr::check(vxuChannelCombine(ctx->ctx, ia.img, ib.img, ic.img, - cn == 4 ? vxImage(*ctx, src_data[3], len, len, 1).img : NULL, - id.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} +template +int ovx_hal_mul(const T *a, size_t astep, const T *b, size_t bstep, T *c, size_t cstep, int w, int h, double scale); -inline int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, double inv_scale_x, double inv_scale_y, int interpolation) -{ - if(dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, aw, ah); - vxImage ib(*ctx, b, bstep, bw, bh); - - if(!((atype == CV_8UC1 || atype == CV_8SC1) && - inv_scale_x > 0 && inv_scale_y > 0 && - (bw - 0.5) / inv_scale_x - 0.5 < aw && (bh - 0.5) / inv_scale_y - 0.5 < ah && - (bw + 0.5) / inv_scale_x + 0.5 >= aw && (bh + 0.5) / inv_scale_y + 0.5 >= ah && - std::abs(bw / inv_scale_x - aw) < 0.1 && std::abs(bh / inv_scale_y - ah) < 0.1 )) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - int mode; - if (interpolation == CV_HAL_INTER_LINEAR) - { - mode = VX_INTERPOLATION_BILINEAR; - if (inv_scale_x > 1 || inv_scale_y > 1) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - else if (interpolation == CV_HAL_INTER_AREA) - return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_AREA; - else if (interpolation == CV_HAL_INTER_NEAREST) - return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; - else - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vxErr::check( vxuScaleImage(ctx->ctx, ia.img, ib.img, mode)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int borderType, const double borderValue[4]) -{ - if(dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, aw, ah); - vxImage ib(*ctx, b, bstep, bw, bh); - - if (!(atype == CV_8UC1 || atype == CV_8SC1)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vx_border_t border; - switch (borderType) - { - case CV_HAL_BORDER_CONSTANT: - setConstantBorder(border, (vx_uint8)borderValue[0]); - break; - case CV_HAL_BORDER_REPLICATE: - // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - int mode; - if (interpolation == CV_HAL_INTER_LINEAR) - mode = VX_INTERPOLATION_BILINEAR; - //AREA interpolation is unsupported - //else if (interpolation == CV_HAL_INTER_AREA) - // mode = VX_INTERPOLATION_AREA; - else if (interpolation == CV_HAL_INTER_NEAREST) - mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; - else - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - std::vector data; - data.reserve(6); - for (int j = 0; j < 3; ++j) - for (int i = 0; i < 2; ++i) - data.push_back((float)(M[i*3+j])); - - vxMatrix mtx(*ctx, data.data(), 2, 3); - //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; - vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border))); - vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int borderType, const double borderValue[4]) -{ - if(dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, aw, ah); - vxImage ib(*ctx, b, bstep, bw, bh); - - if (!(atype == CV_8UC1 || atype == CV_8SC1)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vx_border_t border; - switch (borderType) - { - case CV_HAL_BORDER_CONSTANT: - setConstantBorder(border, (vx_uint8)borderValue[0]); - break; - case CV_HAL_BORDER_REPLICATE: - // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - int mode; - if (interpolation == CV_HAL_INTER_LINEAR) - mode = VX_INTERPOLATION_BILINEAR; - //AREA interpolation is unsupported - //else if (interpolation == CV_HAL_INTER_AREA) - // mode = VX_INTERPOLATION_AREA; - else if (interpolation == CV_HAL_INTER_NEAREST) - mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; - else - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - std::vector data; - data.reserve(9); - for (int j = 0; j < 3; ++j) - for (int i = 0; i < 3; ++i) - data.push_back((float)(M[i * 3 + j])); - - vxMatrix mtx(*ctx, data.data(), 3, 3); - //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; - vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &border, sizeof(border))); - vxErr::check(vxuWarpPerspective(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} +int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int cn); +int ovx_hal_resize(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, double inv_scale_x, double inv_scale_y, int interpolation); +int ovx_hal_warpAffine(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[6], int interpolation, int borderType, const double borderValue[4]); +int ovx_hal_warpPerspectve(int atype, const uchar *a, size_t astep, int aw, int ah, uchar *b, size_t bstep, int bw, int bh, const double M[9], int interpolation, int borderType, const double borderValue[4]); struct cvhalFilter2D; - -struct FilterCtx -{ - vxConvolution cnv; - int dst_type; - vx_border_t border; - FilterCtx(vxContext &ctx, const short *data, int w, int h, int _dst_type, vx_border_t & _border) : - cnv(ctx, data, w, h), dst_type(_dst_type), border(_border) {} -}; - -inline int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, - int , int , int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace) -{ - if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || delta != 0 || - src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || - kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vx_border_t border; - switch (borderType) - { - case CV_HAL_BORDER_CONSTANT: - setConstantBorder(border, 0); - break; - case CV_HAL_BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - vxContext * ctx = vxContext::getContext(); - - std::vector data; - data.reserve(kernel_width*kernel_height); - switch (kernel_type) - { - case CV_8UC1: - for (int j = 0; j < kernel_height; ++j) - { - uchar * row = (uchar*)(kernel_data + kernel_step*j); - for (int i = 0; i < kernel_width; ++i) - data.push_back(row[i]); - } - break; - case CV_8SC1: - for (int j = 0; j < kernel_height; ++j) - { - schar * row = (schar*)(kernel_data + kernel_step*j); - for (int i = 0; i < kernel_width; ++i) - data.push_back(row[i]); - } - break; - case CV_16SC1: - for (int j = 0; j < kernel_height; ++j) - { - short * row = (short*)(kernel_data + kernel_step*j); - for (int i = 0; i < kernel_width; ++i) - data.push_back(row[i]); - } - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernel_width, kernel_height, dst_type, border); - if (!cnv) - return CV_HAL_ERROR_UNKNOWN; - - *filter_context = (cvhalFilter2D*)(cnv); - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_filterFree(cvhalFilter2D *filter_context) -{ - if (filter_context) - { - delete (FilterCtx*)filter_context; - return CV_HAL_ERROR_OK; - } - else - { - return CV_HAL_ERROR_UNKNOWN; - } -} - -inline int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int , int , int , int ) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - FilterCtx* cnv = (FilterCtx*)filter_context; - if(!cnv) - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); - - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - - //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; - vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &(cnv->border), sizeof(cnv->border))); - if (cnv->dst_type == CV_16SC1) - { - vxImage ib(*ctx, (short*)b, bstep, w, h); - vxErr::check(vxuConvolve(ctx->ctx, ia.img, cnv->cnv.cnv, ib.img)); - } - else - { - vxImage ib(*ctx, b, bstep, w, h); - vxErr::check(vxuConvolve(ctx->ctx, ia.img, cnv->cnv.cnv, ib.img)); - } - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_sepFilterInit(cvhalFilter2D **filter_context, int src_type, int dst_type, - int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, - int anchor_x, int anchor_y, double delta, int borderType) -{ - if (!filter_context || !kernelx_data || !kernely_data || delta != 0 || - src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) || - kernelx_length % 2 == 0 || kernely_length % 2 == 0 || anchor_x != kernelx_length / 2 || anchor_y != kernely_length / 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vx_border_t border; - switch (borderType) - { - case CV_HAL_BORDER_CONSTANT: - setConstantBorder(border, 0); - break; - case CV_HAL_BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - vxContext * ctx = vxContext::getContext(); - - //At the moment OpenVX doesn't support separable filters natively so combine kernels to generic convolution - std::vector data; - data.reserve(kernelx_length*kernely_length); - switch (kernel_type) - { - case CV_8UC1: - for (int j = 0; j < kernely_length; ++j) - for (int i = 0; i < kernelx_length; ++i) - data.push_back((short)(kernely_data[j]) * kernelx_data[i]); - break; - case CV_8SC1: - for (int j = 0; j < kernely_length; ++j) - for (int i = 0; i < kernelx_length; ++i) - data.push_back((short)(((schar*)kernely_data)[j]) * ((schar*)kernelx_data)[i]); - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - FilterCtx* cnv = new FilterCtx(*ctx, data.data(), kernelx_length, kernely_length, dst_type, border); - if (!cnv) - return CV_HAL_ERROR_UNKNOWN; - - *filter_context = (cvhalFilter2D*)(cnv); - return CV_HAL_ERROR_OK; -} +int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int, int, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace); +int ovx_hal_filterFree(cvhalFilter2D *filter_context); +int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int, int, int, int); +int ovx_hal_sepFilterInit(cvhalFilter2D **filter_context, int src_type, int dst_type, + int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length, + int anchor_x, int anchor_y, double delta, int borderType); #if VX_VERSION > VX_VERSION_1_0 - -struct MorphCtx -{ - vxMatrix mask; - int operation; - vx_border_t border; - MorphCtx(vxContext &ctx, const uchar *data, int w, int h, int _operation, vx_border_t & _border) : - mask(ctx, data, w, h), operation(_operation), border(_border) {} -}; - -inline int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int , int , - int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, - int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) -{ - if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || iterations != 1 || - src_type != CV_8UC1 || dst_type != CV_8UC1 || - kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - vx_border_t border; - switch (borderType) - { - case CV_HAL_BORDER_CONSTANT: - if (borderValue[0] == DBL_MAX && borderValue[1] == DBL_MAX && borderValue[2] == DBL_MAX && borderValue[3] == DBL_MAX) - { - if (operation == MORPH_ERODE) - setConstantBorder(border, UCHAR_MAX); - else - setConstantBorder(border, 0); - } - else - { - int rounded = (int)round(borderValue[0]); - setConstantBorder(border, (vx_uint8)((unsigned)rounded <= UCHAR_MAX ? rounded : rounded > 0 ? UCHAR_MAX : 0)); - } - break; - case CV_HAL_BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - vxContext * ctx = vxContext::getContext(); - - vx_size maxKernelDim; - vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_NONLINEAR_MAX_DIMENSION, &maxKernelDim, sizeof(maxKernelDim))); - if ((vx_size)kernel_width > maxKernelDim || (vx_size)kernel_height > maxKernelDim) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - std::vector kernel_mat; - kernel_mat.reserve(kernel_width * kernel_height); - switch (CV_MAT_DEPTH(kernel_type)) - { - case CV_8U: - case CV_8S: - for (int j = 0; j < kernel_height; ++j) - { - uchar * kernel_row = kernel_data + j * kernel_step; - for (int i = 0; i < kernel_width; ++i) - kernel_mat.push_back(kernel_row[i] ? 255 : 0); - } - break; - case CV_16U: - case CV_16S: - for (int j = 0; j < kernel_height; ++j) - { - short * kernel_row = (short*)(kernel_data + j * kernel_step); - for (int i = 0; i < kernel_width; ++i) - kernel_mat.push_back(kernel_row[i] ? 255 : 0); - } - break; - case CV_32S: - for (int j = 0; j < kernel_height; ++j) - { - int * kernel_row = (int*)(kernel_data + j * kernel_step); - for (int i = 0; i < kernel_width; ++i) - kernel_mat.push_back(kernel_row[i] ? 255 : 0); - } - break; - case CV_32F: - for (int j = 0; j < kernel_height; ++j) - { - float * kernel_row = (float*)(kernel_data + j * kernel_step); - for (int i = 0; i < kernel_width; ++i) - kernel_mat.push_back(kernel_row[i] ? 255 : 0); - } - break; - case CV_64F: - for (int j = 0; j < kernel_height; ++j) - { - double * kernel_row = (double*)(kernel_data + j * kernel_step); - for (int i = 0; i < kernel_width; ++i) - kernel_mat.push_back(kernel_row[i] ? 255 : 0); - } - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - MorphCtx* mat; - switch (operation) - { - case MORPH_ERODE: - mat = new MorphCtx(*ctx, kernel_mat.data(), kernel_width, kernel_height, VX_NONLINEAR_FILTER_MIN, border); - break; - case MORPH_DILATE: - mat = new MorphCtx(*ctx, kernel_mat.data(), kernel_width, kernel_height, VX_NONLINEAR_FILTER_MAX, border); - break; - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - if (!mat) - return CV_HAL_ERROR_UNKNOWN; - - *filter_context = (cvhalFilter2D*)(mat); - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_morphFree(cvhalFilter2D *filter_context) -{ - if (filter_context) - { - delete (MorphCtx*)filter_context; - return CV_HAL_ERROR_OK; - } - else - { - return CV_HAL_ERROR_UNKNOWN; - } -} - -inline int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int , int , int , int , int , int , int , int ) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - try - { - MorphCtx* mat = (MorphCtx*)filter_context; - if (!mat) - vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); - - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - vxImage ib(*ctx, b, bstep, w, h); - - //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; - vxErr::check(vxQueryContext(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &(mat->border), sizeof(mat->border))); - vxErr::check(vxuNonLinearFilter(ctx->ctx, mat->operation, ia.img, mat->mask.mtx, ib.img)); - vxErr::check(vxSetContextAttribute(ctx->ctx, VX_CONTEXT_IMMEDIATE_BORDER, &prevBorder, sizeof(prevBorder))); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - +int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int , int , + int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace); +int ovx_hal_morphFree(cvhalFilter2D *filter_context); +int ovx_hal_morph(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int , int , int , int , int , int , int , int ); #endif // 1.0 guard -inline int ovx_hal_cvtBGRtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int acn, int bcn, bool swapBlue) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (depth != CV_8U || swapBlue || acn == bcn || (acn != 3 && acn != 4) || (bcn != 3 && bcn != 4)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - if (w & 1 || h & 1) // It's strange but sample implementation unable to convert odd sized images - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, a, astep, w, h); - vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); - vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int bcn) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (depth != CV_8U || (bcn != 3 && bcn != 4)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); - vxErr::check(vxuChannelCombine(ctx->ctx, ia.img, ia.img, ia.img, - bcn == 4 ? vxImage(*ctx, uchar(255), w, h).img : NULL, - ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (!swapBlue || (bcn != 3 && bcn != 4)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, a, astep, w, h); - vx_channel_range_e cRange; - vxErr::check(vxQueryImage(ia.img, VX_IMAGE_RANGE, &cRange, sizeof(cRange))); - if (cRange == VX_CHANNEL_RANGE_FULL) - return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL - vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); - vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx || (size_t)w / 2 != astep - (size_t)w / 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, VX_DF_IMAGE_IYUV, a, astep, w, h); - vx_channel_range_e cRange; - vxErr::check(vxQueryImage(ia.img, VX_IMAGE_RANGE, &cRange, sizeof(cRange))); - if (cRange == VX_CHANNEL_RANGE_FULL) - return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL - vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); - vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (!swapBlue || (acn != 3 && acn != 4) || uIdx || (size_t)w / 2 != bstep - (size_t)w / 2) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, a, astep, w, h); - vxImage ib(*ctx, VX_DF_IMAGE_IYUV, b, bstep, w, h); - vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_cvtOnePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx, int ycn) -{ - if(dimTooBig(w) || dimTooBig(h)) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - if (w & 1) // It's not described in spec but sample implementation unable to convert odd sized images - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV, a, astep, w, h); - vx_channel_range_e cRange; - vxErr::check(vxQueryImage(ia.img, VX_IMAGE_RANGE, &cRange, sizeof(cRange))); - if (cRange == VX_CHANNEL_RANGE_FULL) - return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL - vxImage ib(*ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, b, bstep, w, h); - vxErr::check(vxuColorConvert(ctx->ctx, ia.img, ib.img)); - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} - -inline int ovx_hal_integral(int depth, int sdepth, int , const uchar * a, size_t astep, uchar * b, size_t bstep, uchar * c, size_t , uchar * d, size_t , int w, int h, int cn) -{ - if (depth != CV_8U || sdepth != CV_32S || c != NULL || d != NULL || cn != 1) - return CV_HAL_ERROR_NOT_IMPLEMENTED; - - try - { - vxContext * ctx = vxContext::getContext(); - vxImage ia(*ctx, a, astep, w, h); - vxImage ib(*ctx, (unsigned int *)(b+bstep+sizeof(unsigned int)), bstep, w, h); - vxErr::check(vxuIntegralImage(ctx->ctx, ia.img, ib.img)); - memset(b, 0, (w+1)*sizeof(unsigned int)); - b += bstep; - for (int i = 0; i < h; i++, b += bstep) - { - *((unsigned int*)b) = 0; - } - } - catch (vxErr & e) - { - e.print(); - return CV_HAL_ERROR_UNKNOWN; - } - return CV_HAL_ERROR_OK; -} +int ovx_hal_cvtBGRtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int acn, int bcn, bool swapBlue); +int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int bcn); +int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx); +int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx); +int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx); +int ovx_hal_cvtOnePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx, int ycn); +int ovx_hal_integral(int depth, int sdepth, int, const uchar * a, size_t astep, uchar * b, size_t bstep, uchar * c, size_t, uchar * d, size_t, int w, int h, int cn); //================================================================================================== // functions redefinition diff --git a/3rdparty/openvx/include/ivx.hpp b/3rdparty/openvx/include/ivx.hpp index e943961590..47213e6d5c 100644 --- a/3rdparty/openvx/include/ivx.hpp +++ b/3rdparty/openvx/include/ivx.hpp @@ -22,6 +22,18 @@ Details: TBD #include #include +#ifndef VX_VERSION_1_1 +// 1.1 to 1.0 backward compatibility defines + +static const vx_enum VX_INTERPOLATION_BILINEAR = VX_INTERPOLATION_TYPE_BILINEAR; +static const vx_enum VX_INTERPOLATION_AREA = VX_INTERPOLATION_TYPE_AREA; +static const vx_enum VX_INTERPOLATION_NEAREST_NEIGHBOR = VX_INTERPOLATION_TYPE_NEAREST_NEIGHBOR; + +static const vx_enum VX_BORDER_CONSTANT = VX_BORDER_MODE_CONSTANT; +static const vx_enum VX_BORDER_REPLICATE = VX_BORDER_MODE_REPLICATE; + +#endif + #ifndef IVX_USE_CXX98 // checking compiler #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1800) @@ -56,6 +68,7 @@ Details: TBD #include #include #include +#include #ifndef IVX_USE_CXX98 #include @@ -190,14 +203,14 @@ inline vx_size enumToTypeSize(vx_enum type) template struct TypeToEnum {}; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_CHAR; }; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT8; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT8; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT16; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT16; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT32; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT32; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT8, imgType = VX_DF_IMAGE_U8; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT16, imgType = VX_DF_IMAGE_S16; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT16, imgType = VX_DF_IMAGE_U16; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT32, imgType = VX_DF_IMAGE_S32; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT32, imgType = VX_DF_IMAGE_U32; }; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_INT64; }; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_UINT64; }; -template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_FLOAT32; }; +template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_FLOAT32, imgType = VX_DF_IMAGE('F', '0', '3', '2'); }; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_FLOAT64; }; template<> struct TypeToEnum { static const vx_enum value = VX_TYPE_BOOL; }; template<> struct TypeToEnum {static const vx_enum value = VX_TYPE_KEYPOINT; }; @@ -1376,6 +1389,25 @@ public: static Image createUniform(vx_context context, vx_uint32 width, vx_uint32 height, vx_df_image format, const void* value) { return Image(vxCreateUniformImage(context, width, height, format, value)); } #endif + template + static Image createUniform(vx_context context, vx_uint32 width, vx_uint32 height, vx_df_image format, const T value) + { +#if VX_VERSION > VX_VERSION_1_0 + vx_pixel_value_t pixel; + switch (format) + { + case VX_DF_IMAGE_U8:pixel.U8 = (vx_uint8)value; break; + case VX_DF_IMAGE_S16:pixel.S16 = (vx_int16)value; break; + case VX_DF_IMAGE_U16:pixel.U16 = (vx_uint16)value; break; + case VX_DF_IMAGE_S32:pixel.S32 = (vx_int32)value; break; + case VX_DF_IMAGE_U32:pixel.U32 = (vx_uint32)value; break; + default:throw ivx::WrapperError("uniform image type unsupported by this call"); + } + return Image(vxCreateUniformImage(context, width, height, format, &pixel)); +#else + return Image(vxCreateUniformImage(context, width, height, format, &value)); +#endif + } /// Planes number for the specified image format (fourcc) /// \return 0 for unknown formats @@ -1887,7 +1919,9 @@ public: swap(_planeIdx, p._planeIdx); #endif swap(_img, p._img); +#ifdef IVX_USE_OPENCV swap(_m, p._m); +#endif } #endif diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 24c5760a00..01352be333 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -221,19 +221,14 @@ namespace cv if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) return false; //Process isolated borders only - vx_border_t border; + vx_enum 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 + border = VX_BORDER_CONSTANT; break; case BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; + border = VX_BORDER_REPLICATE; break; default: return false; @@ -259,8 +254,8 @@ namespace cv //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.immediateBorder(); - ctx.setImmediateBorder(border); + ivx::border_t prevBorder = ctx.immediateBorder(); + ctx.setImmediateBorder(border, (vx_uint8)(0)); if (dtype == CV_16SC1 && ksize == 3 && ((dx | dy) == 1) && (dx + dy) == 1) { if(dx) diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 866a17f8eb..c0e18c13bf 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1278,7 +1278,7 @@ static bool openvx_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, // The only border mode which is supported by both cv::pyrDown() and OpenVX // and produces predictable results - vx_border_t borderMode; + ivx::border_t borderMode; borderMode.mode = VX_BORDER_REPLICATE; _dst.create( acceptableSize, srcMat.type() ); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 76444398ed..d8514da01b 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1662,19 +1662,14 @@ namespace cv if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) return false; //Process isolated borders only - vx_border_t border; + vx_enum 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 + border = VX_BORDER_CONSTANT; break; case BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; + border = VX_BORDER_REPLICATE; break; default: return false; @@ -1701,7 +1696,7 @@ namespace cv //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(border); + ctx.setImmediateBorder(border, (vx_uint8)(0)); if (ddepth == CV_8U && ksize.width == 3 && ksize.height == 3 && normalize) { ivx::IVX_CHECK_STATUS(vxuBox3x3(ctx, ia, ib)); @@ -2229,19 +2224,14 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) return false; //Process isolated borders only - vx_border_t border; + vx_enum 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 + border = VX_BORDER_CONSTANT; break; case BORDER_REPLICATE: - border.mode = VX_BORDER_REPLICATE; + border = VX_BORDER_REPLICATE; break; default: return false; @@ -2268,7 +2258,7 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, //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(border); + ctx.setImmediateBorder(border, (vx_uint8)(0)); if (ksize.width == 3 && ksize.height == 3 && (sigma1 == 0.0 || (sigma1 - 0.8) < DBL_EPSILON) && (sigma2 == 0.0 || (sigma2 - 0.8) < DBL_EPSILON)) { ivx::IVX_CHECK_STATUS(vxuGaussian3x3(ctx, ia, ib)); @@ -3369,9 +3359,6 @@ namespace cv Mat src = _src.getMat(); Mat dst = _dst.getMat(); - vx_border_t border; - border.mode = VX_BORDER_REPLICATE; - try { ivx::Context ctx = ivx::Context::create(); @@ -3395,7 +3382,7 @@ namespace cv //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(border); + ctx.setImmediateBorder(VX_BORDER_REPLICATE); #ifdef VX_VERSION_1_1 if (ksize == 3) #endif