From c9229f754325a89de3553ad2190ffcc0879d8ace Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov <terfendail@mediana.jetos.com> Date: Wed, 31 Aug 2016 17:10:45 +0300 Subject: [PATCH] Resize, Warp and Filter HAL API functions are implemented as immediate mode OpenVX calls --- 3rdparty/openvx/include/openvx_hal.hpp | 306 ++++++++++++++++++++++++- 1 file changed, 301 insertions(+), 5 deletions(-) diff --git a/3rdparty/openvx/include/openvx_hal.hpp b/3rdparty/openvx/include/openvx_hal.hpp index 33de4bf834..6dbec79af0 100644 --- a/3rdparty/openvx/include/openvx_hal.hpp +++ b/3rdparty/openvx/include/openvx_hal.hpp @@ -7,6 +7,7 @@ #include "VX/vxu.h" #include <string> +#include <vector> //================================================================================================== // utility @@ -52,7 +53,8 @@ template <typename T> struct VX_Traits { enum { - Type = 0 + ImgType = 0, + DataType = 0 }; }; @@ -60,7 +62,8 @@ template <> struct VX_Traits<uchar> { enum { - Type = VX_DF_IMAGE_U8 + ImgType = VX_DF_IMAGE_U8, + DataType = VX_TYPE_UINT8 }; }; @@ -68,7 +71,8 @@ template <> struct VX_Traits<ushort> { enum { - Type = VX_DF_IMAGE_U16 + ImgType = VX_DF_IMAGE_U16, + DataType = VX_TYPE_UINT16 }; }; @@ -76,7 +80,17 @@ template <> struct VX_Traits<short> { enum { - Type = VX_DF_IMAGE_S16 + ImgType = VX_DF_IMAGE_S16, + DataType = VX_TYPE_INT16 + }; +}; + +template <> +struct VX_Traits<float> +{ + enum { + ImgType = 0, + DataType = VX_TYPE_FLOAT32 }; }; @@ -108,6 +122,14 @@ struct vxErr { 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(); @@ -151,7 +173,7 @@ struct vxImage addr.step_x = 1; addr.step_y = 1; void *ptrs[] = { (void*)data }; - img = vxCreateImageFromHandle(ctx.ctx, VX_Traits<T>::Type, &addr, ptrs, VX_MEMORY_TYPE_HOST); + img = vxCreateImageFromHandle(ctx.ctx, VX_Traits<T>::ImgType, &addr, ptrs, VX_MEMORY_TYPE_HOST); vxErr::check(img); } ~vxImage() @@ -161,6 +183,39 @@ struct vxImage } }; +struct vxMatrix +{ + vx_matrix mtx; + + template <typename T> + vxMatrix(vxContext &ctx, const T *data, int w, int h) + { + mtx = vxCreateMatrix(ctx.ctx, VX_Traits<T>::DataType, w, h); + vxErr::check(mtx); + vxErr::check(vxCopyMatrix(mtx, data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + } + ~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); + vxErr::check(vxCopyConvolutionCoefficients(cnv, (void*)data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST); + } + ~vxConvolution() + { + vxReleaseConvolution(&cnv); + } +}; + //================================================================================================== // real code starts here // ... @@ -213,6 +268,229 @@ inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int return CV_HAL_ERROR_OK; } +#if defined OPENCV_IMGPROC_HAL_INTERFACE_H +#define CV_HAL_INTER_NEAREST 0 +#define CV_HAL_INTER_LINEAR 1 +#define CV_HAL_INTER_CUBIC 2 +#define CV_HAL_INTER_AREA 3 +#define CV_HAL_INTER_LANCZOS4 4 +#define MORPH_ERODE 0 +#define MORPH_DILATE 1 + +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) +{ + 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 )) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad scale").check(); + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + 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, const double*) +{ + 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)) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + vxMatrix mtx(*ctx, std::vector<float>(M, M + 6).data(), 2, 3); + vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + } + 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, const double*) +{ + 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)) + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad input type").check(); + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + int mode; + if (interpolation == CV_HAL_INTER_LINEAR) + mode = VX_INTERPOLATION_BILINEAR; + else if (interpolation == CV_HAL_INTER_AREA) + mode = VX_INTERPOLATION_AREA; + else if (interpolation == CV_HAL_INTER_NEAREST) + mode = VX_INTERPOLATION_NEAREST_NEIGHBOR; + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad interpolation mode").check(); + + vxMatrix mtx(*ctx, std::vector<float>(M, M + 9).data(), 3, 3); + vxErr::check(vxuWarpAffine(ctx->ctx, ia.img, mtx.mtx, mode, ib.img)); + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +struct cvhalFilter2D; + +struct FilterCtx +{ + vxConvolution cnv; + int dst_type; + FilterCtx(vxContext &ctx, const short *data, int w, int h, int _dst_type) : + cnv(ctx, data, w, h), dst_type(_dst_type) {} +}; + +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 max_width, int max_height, 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; + + // It make sense to check border mode as well, but it's impossible to set border mode for immediate OpenVX calls + // So the only supported modes should be UNDEFINED(there is no such for HAL) and probably ISOLATED + + vxContext * ctx = vxContext::getContext(); + + std::vector<short> 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); + 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 full_w, int full_h, int offset_x, int offset_y) +{ + try + { + FilterCtx* cnv = (FilterCtx*)filter_context; + if(cnv) + vxErr::check(cnv->cnv.cnv); + else + vxErr(VX_ERROR_INVALID_PARAMETERS, "Bad HAL context").check(); + + vxContext * ctx = vxContext::getContext(); + vxImage ia(*ctx, a, astep, w, h); + + 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)); + } + } + catch (vxErr & e) + { + e.print(); + return CV_HAL_ERROR_UNKNOWN; + } + return CV_HAL_ERROR_OK; +} + +#endif + //================================================================================================== // functions redefinition // ... @@ -245,4 +523,22 @@ inline int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int #undef cv_hal_mul16s #define cv_hal_mul16s ovx_hal_mul<short> +#if defined OPENCV_IMGPROC_HAL_INTERFACE_H + +#undef cv_hal_resize +#define cv_hal_resize ovx_hal_resize +#undef cv_hal_warpAffine +#define cv_hal_warpAffine ovx_hal_warpAffine +#undef cv_hal_warpPerspective +#define cv_hal_warpPerspective ovx_hal_warpPerspectve + +#undef cv_hal_filterInit +#define cv_hal_filterInit ovx_hal_filterInit +#undef cv_hal_filter +#define cv_hal_filter ovx_hal_filter +#undef cv_hal_filterFree +#define cv_hal_filterFree ovx_hal_filterFree + +#endif + #endif