Path: blob/master/3rdparty/openvx/hal/openvx_hal.cpp
16337 views
#include "openvx_hal.hpp"1#include "opencv2/imgproc/hal/interface.h"23#define IVX_HIDE_INFO_WARNINGS4#include "ivx.hpp"56#include <string>7#include <vector>89#include <algorithm>10#include <cfloat>11#include <climits>12#include <cmath>13#include <cstring>1415//==================================================================================================16// utility17// ...1819#if 020#include <cstdio>21#define PRINT(...) printf(__VA_ARGS__)22#define PRINT_HALERR_MSG(type) PRINT("OpenVX HAL impl "#type" error: %s\n", e.what())23#else24#define PRINT(...)25#define PRINT_HALERR_MSG(type) (void)e26#endif272829#if __cplusplus >= 201103L30#include <chrono>31struct Tick32{33typedef std::chrono::time_point<std::chrono::steady_clock> point_t;34point_t start;35point_t point;36Tick()37{38start = std::chrono::steady_clock::now();39point = std::chrono::steady_clock::now();40}41inline int one()42{43point_t old = point;44point = std::chrono::steady_clock::now();45return std::chrono::duration_cast<std::chrono::microseconds>(point - old).count();46}47inline int total()48{49return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();50}51};52#endif5354inline ivx::Context& getOpenVXHALContext()55{56#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)57//CXX1158static thread_local ivx::Context instance = ivx::Context::create();59#else //__cplusplus >= 201103L || _MSC_VER >= 180060//CXX9861#ifdef _WIN3262static __declspec(thread) ivx::Context instance = ivx::Context::create();63#else64static __thread ivx::Context instance = ivx::Context::create();65#endif66#endif67return instance;68}6970inline bool dimTooBig(int size)71{72static vx_uint16 current_vendor = getOpenVXHALContext().vendorID();7374if (current_vendor == VX_ID_KHRONOS || current_vendor == VX_ID_DEFAULT)75{76//OpenVX use uint32_t for image addressing77return ((unsigned)size > (UINT_MAX / VX_SCALE_UNITY));78}79else80return false;81}8283//OpenVX calls have essential overhead so it make sense to skip them for small images84template <int kernel_id> inline bool skipSmallImages(int w, int h) { return w*h < 7680 * 4320; }85template <> inline bool skipSmallImages<VX_KERNEL_MULTIPLY>(int w, int h) { return w*h < 640 * 480; }86template <> inline bool skipSmallImages<VX_KERNEL_COLOR_CONVERT>(int w, int h) { return w*h < 2048 * 1536; }87template <> inline bool skipSmallImages<VX_KERNEL_INTEGRAL_IMAGE>(int w, int h) { return w*h < 640 * 480; }88template <> inline bool skipSmallImages<VX_KERNEL_WARP_AFFINE>(int w, int h) { return w*h < 1280 * 720; }89template <> inline bool skipSmallImages<VX_KERNEL_WARP_PERSPECTIVE>(int w, int h) { return w*h < 320 * 240; }90template <> inline bool skipSmallImages<VX_KERNEL_CUSTOM_CONVOLUTION>(int w, int h) { return w*h < 320 * 240; }9192inline void setConstantBorder(ivx::border_t &border, vx_uint8 val)93{94border.mode = VX_BORDER_CONSTANT;95#if VX_VERSION > VX_VERSION_1_096border.constant_value.U8 = val;97#else98border.constant_value = val;99#endif100}101102inline void refineStep(int w, int h, int imgType, size_t& step)103{104if (h == 1)105step = w * ((imgType == VX_DF_IMAGE_RGBX ||106imgType == VX_DF_IMAGE_U32 || imgType == VX_DF_IMAGE_S32) ? 4 :107imgType == VX_DF_IMAGE_RGB ? 3 :108(imgType == VX_DF_IMAGE_U16 || imgType == VX_DF_IMAGE_S16 ||109imgType == VX_DF_IMAGE_UYVY || imgType == VX_DF_IMAGE_YUYV) ? 2 : 1);110}111112//==================================================================================================113// ivx::Image wrapped to simplify call to swapHandle prior to release114// TODO update ivx::Image to handle swapHandle prior to release on the own115116class vxImage: public ivx::Image117{118public:119vxImage(const ivx::Image &_img) : ivx::Image(_img) {}120121~vxImage()122{123#if VX_VERSION > VX_VERSION_1_0124swapHandle();125#endif126}127};128129//==================================================================================================130// real code starts here131// ...132133#define OVX_BINARY_OP(hal_func, ovx_call, kernel_id) \134template <typename T> \135int 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) \136{ \137if(skipSmallImages<kernel_id>(w, h)) \138return CV_HAL_ERROR_NOT_IMPLEMENTED; \139if(dimTooBig(w) || dimTooBig(h)) \140return CV_HAL_ERROR_NOT_IMPLEMENTED; \141refineStep(w, h, ivx::TypeToEnum<T>::imgType, astep); \142refineStep(w, h, ivx::TypeToEnum<T>::imgType, bstep); \143refineStep(w, h, ivx::TypeToEnum<T>::imgType, cstep); \144try \145{ \146ivx::Context ctx = getOpenVXHALContext(); \147vxImage \148ia = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType, \149ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(astep)), (void*)a), \150ib = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType, \151ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(bstep)), (void*)b), \152ic = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType, \153ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(cstep)), (void*)c); \154ovx_call \155} \156catch (ivx::RuntimeError & e) \157{ \158PRINT_HALERR_MSG(runtime); \159return CV_HAL_ERROR_UNKNOWN; \160} \161catch (ivx::WrapperError & e) \162{ \163PRINT_HALERR_MSG(wrapper); \164return CV_HAL_ERROR_UNKNOWN; \165} \166return CV_HAL_ERROR_OK; \167}168169OVX_BINARY_OP(add, { ivx::IVX_CHECK_STATUS(vxuAdd(ctx, ia, ib, VX_CONVERT_POLICY_SATURATE, ic)); }, VX_KERNEL_ADD)170OVX_BINARY_OP(sub, { ivx::IVX_CHECK_STATUS(vxuSubtract(ctx, ia, ib, VX_CONVERT_POLICY_SATURATE, ic)); }, VX_KERNEL_SUBTRACT)171172OVX_BINARY_OP(absdiff, { ivx::IVX_CHECK_STATUS(vxuAbsDiff(ctx, ia, ib, ic)); }, VX_KERNEL_ABSDIFF)173174OVX_BINARY_OP(and, { ivx::IVX_CHECK_STATUS(vxuAnd(ctx, ia, ib, ic)); }, VX_KERNEL_AND)175OVX_BINARY_OP(or , { ivx::IVX_CHECK_STATUS(vxuOr(ctx, ia, ib, ic)); }, VX_KERNEL_OR)176OVX_BINARY_OP(xor, { ivx::IVX_CHECK_STATUS(vxuXor(ctx, ia, ib, ic)); }, VX_KERNEL_XOR)177178template <typename T>179int 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)180{181if(scale == 1.0 || sizeof(T) > 1 ?182skipSmallImages<VX_KERNEL_ADD>(w, h) : /*actually it could be any kernel with generic minimum size*/183skipSmallImages<VX_KERNEL_MULTIPLY>(w, h) )184return CV_HAL_ERROR_NOT_IMPLEMENTED;185if (dimTooBig(w) || dimTooBig(h))186return CV_HAL_ERROR_NOT_IMPLEMENTED;187refineStep(w, h, ivx::TypeToEnum<T>::imgType, astep);188refineStep(w, h, ivx::TypeToEnum<T>::imgType, bstep);189refineStep(w, h, ivx::TypeToEnum<T>::imgType, cstep);190#ifdef _MSC_VER191const float MAGIC_SCALE = 0x0.01010102;192#else193const float MAGIC_SCALE = 0x1.010102p-8;194#endif195try196{197int rounding_policy = VX_ROUND_POLICY_TO_ZERO;198float fscale = (float)scale;199if (fabs(fscale - MAGIC_SCALE) > FLT_EPSILON)200{201int exp = 0;202double significand = frexp(fscale, &exp);203if ((significand != 0.5) || (exp > 1) || (exp < -14))204return CV_HAL_ERROR_NOT_IMPLEMENTED;205}206else207{208fscale = MAGIC_SCALE;209rounding_policy = VX_ROUND_POLICY_TO_NEAREST_EVEN;// That's the only rounding that MUST be supported for 1/255 scale210}211ivx::Context ctx = getOpenVXHALContext();212vxImage213ia = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType,214ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(astep)), (void*)a),215ib = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType,216ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(bstep)), (void*)b),217ic = ivx::Image::createFromHandle(ctx, ivx::TypeToEnum<T>::imgType,218ivx::Image::createAddressing(w, h, sizeof(T), (vx_int32)(cstep)), (void*)c);219ivx::IVX_CHECK_STATUS(vxuMultiply(ctx, ia, ib, fscale, VX_CONVERT_POLICY_SATURATE, rounding_policy, ic));220}221catch (ivx::RuntimeError & e)222{223PRINT_HALERR_MSG(runtime);224return CV_HAL_ERROR_UNKNOWN;225}226catch (ivx::WrapperError & e)227{228PRINT_HALERR_MSG(wrapper);229return CV_HAL_ERROR_UNKNOWN;230}231return CV_HAL_ERROR_OK;232}233234template int ovx_hal_add<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);235template int ovx_hal_add<short>(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h);236template int ovx_hal_sub<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);237template int ovx_hal_sub<short>(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h);238239template int ovx_hal_absdiff<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);240template int ovx_hal_absdiff<short>(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h);241242template int ovx_hal_and<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);243template int ovx_hal_or<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);244template int ovx_hal_xor<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h);245246template int ovx_hal_mul<uchar>(const uchar *a, size_t astep, const uchar *b, size_t bstep, uchar *c, size_t cstep, int w, int h, double scale);247template int ovx_hal_mul<short>(const short *a, size_t astep, const short *b, size_t bstep, short *c, size_t cstep, int w, int h, double scale);248249int ovx_hal_not(const uchar *a, size_t astep, uchar *c, size_t cstep, int w, int h)250{251if (skipSmallImages<VX_KERNEL_NOT>(w, h))252return CV_HAL_ERROR_NOT_IMPLEMENTED;253if (dimTooBig(w) || dimTooBig(h))254return CV_HAL_ERROR_NOT_IMPLEMENTED;255refineStep(w, h, VX_DF_IMAGE_U8, astep);256refineStep(w, h, VX_DF_IMAGE_U8, cstep);257try258{259ivx::Context ctx = getOpenVXHALContext();260vxImage261ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,262ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a),263ic = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,264ivx::Image::createAddressing(w, h, 1, (vx_int32)(cstep)), (void*)c);265ivx::IVX_CHECK_STATUS(vxuNot(ctx, ia, ic));266}267catch (ivx::RuntimeError & e)268{269PRINT_HALERR_MSG(runtime);270return CV_HAL_ERROR_UNKNOWN;271}272catch (ivx::WrapperError & e)273{274PRINT_HALERR_MSG(wrapper);275return CV_HAL_ERROR_UNKNOWN;276}277return CV_HAL_ERROR_OK;278}279280int ovx_hal_merge8u(const uchar **src_data, uchar *dst_data, int len, int cn)281{282if (skipSmallImages<VX_KERNEL_CHANNEL_COMBINE>(len, 1))283return CV_HAL_ERROR_NOT_IMPLEMENTED;284if (dimTooBig(len))285return CV_HAL_ERROR_NOT_IMPLEMENTED;286if (cn != 3 && cn != 4)287return CV_HAL_ERROR_NOT_IMPLEMENTED;288try289{290ivx::Context ctx = getOpenVXHALContext();291vxImage292ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,293ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[0]),294ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,295ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[1]),296ic = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,297ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[2]),298id = ivx::Image::createFromHandle(ctx, cn == 4 ? VX_DF_IMAGE_RGBX : VX_DF_IMAGE_RGB,299ivx::Image::createAddressing(len, 1, cn, (vx_int32)(len*cn)), (void*)dst_data);300ivx::IVX_CHECK_STATUS(vxuChannelCombine(ctx, ia, ib, ic,301cn == 4 ? (vx_image)(ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,302ivx::Image::createAddressing(len, 1, 1, (vx_int32)(len)), (void*)src_data[3])) : NULL,303id));304}305catch (ivx::RuntimeError & e)306{307PRINT_HALERR_MSG(runtime);308return CV_HAL_ERROR_UNKNOWN;309}310catch (ivx::WrapperError & e)311{312PRINT_HALERR_MSG(wrapper);313return CV_HAL_ERROR_UNKNOWN;314}315return CV_HAL_ERROR_OK;316}317318int 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)319{320if (skipSmallImages<VX_KERNEL_SCALE_IMAGE>(aw, ah))321return CV_HAL_ERROR_NOT_IMPLEMENTED;322if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh))323return CV_HAL_ERROR_NOT_IMPLEMENTED;324refineStep(aw, ah, VX_DF_IMAGE_U8, astep);325refineStep(bw, bh, VX_DF_IMAGE_U8, bstep);326try327{328ivx::Context ctx = getOpenVXHALContext();329vxImage330ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,331ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a),332ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,333ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b);334335if (!((atype == CV_8UC1 || atype == CV_8SC1) &&336inv_scale_x > 0 && inv_scale_y > 0 &&337(bw - 0.5) / inv_scale_x - 0.5 < aw && (bh - 0.5) / inv_scale_y - 0.5 < ah &&338(bw + 0.5) / inv_scale_x + 0.5 >= aw && (bh + 0.5) / inv_scale_y + 0.5 >= ah &&339std::abs(bw / inv_scale_x - aw) < 0.1 && std::abs(bh / inv_scale_y - ah) < 0.1))340return CV_HAL_ERROR_NOT_IMPLEMENTED;341342int mode;343if (interpolation == CV_HAL_INTER_LINEAR)344{345mode = VX_INTERPOLATION_BILINEAR;346if (inv_scale_x > 1 || inv_scale_y > 1)347return CV_HAL_ERROR_NOT_IMPLEMENTED;348}349else if (interpolation == CV_HAL_INTER_AREA)350return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_AREA;351else if (interpolation == CV_HAL_INTER_NEAREST)352return CV_HAL_ERROR_NOT_IMPLEMENTED; //mode = VX_INTERPOLATION_NEAREST_NEIGHBOR;353else354return CV_HAL_ERROR_NOT_IMPLEMENTED;355356ivx::IVX_CHECK_STATUS(vxuScaleImage(ctx, ia, ib, mode));357}358catch (ivx::RuntimeError & e)359{360PRINT_HALERR_MSG(runtime);361return CV_HAL_ERROR_UNKNOWN;362}363catch (ivx::WrapperError & e)364{365PRINT_HALERR_MSG(wrapper);366return CV_HAL_ERROR_UNKNOWN;367}368return CV_HAL_ERROR_OK;369}370371int 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])372{373if (skipSmallImages<VX_KERNEL_WARP_AFFINE>(aw, ah))374return CV_HAL_ERROR_NOT_IMPLEMENTED;375if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh))376return CV_HAL_ERROR_NOT_IMPLEMENTED;377refineStep(aw, ah, VX_DF_IMAGE_U8, astep);378refineStep(bw, bh, VX_DF_IMAGE_U8, bstep);379try380{381ivx::Context ctx = getOpenVXHALContext();382vxImage383ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,384ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a),385ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,386ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b);387388if (!(atype == CV_8UC1 || atype == CV_8SC1))389return CV_HAL_ERROR_NOT_IMPLEMENTED;390391if(borderType != CV_HAL_BORDER_CONSTANT) // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings392return CV_HAL_ERROR_NOT_IMPLEMENTED;393394int mode;395if (interpolation == CV_HAL_INTER_LINEAR)396mode = VX_INTERPOLATION_BILINEAR;397//AREA interpolation is unsupported398//else if (interpolation == CV_HAL_INTER_AREA)399// mode = VX_INTERPOLATION_AREA;400else if (interpolation == CV_HAL_INTER_NEAREST)401mode = VX_INTERPOLATION_NEAREST_NEIGHBOR;402else403return CV_HAL_ERROR_NOT_IMPLEMENTED;404405std::vector<float> data;406data.reserve(6);407for (int j = 0; j < 3; ++j)408for (int i = 0; i < 2; ++i)409data.push_back((float)(M[i * 3 + j]));410411ivx::Matrix mtx = ivx::Matrix::create(ctx, VX_TYPE_FLOAT32, 2, 3);412mtx.copyFrom(data);413//ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments414//since OpenVX standart says nothing about thread-safety for now415ivx::border_t prevBorder = ctx.immediateBorder();416ctx.setImmediateBorder(VX_BORDER_CONSTANT, (vx_uint8)borderValue[0]);417ivx::IVX_CHECK_STATUS(vxuWarpAffine(ctx, ia, mtx, mode, ib));418ctx.setImmediateBorder(prevBorder);419}420catch (ivx::RuntimeError & e)421{422PRINT_HALERR_MSG(runtime);423return CV_HAL_ERROR_UNKNOWN;424}425catch (ivx::WrapperError & e)426{427PRINT_HALERR_MSG(wrapper);428return CV_HAL_ERROR_UNKNOWN;429}430return CV_HAL_ERROR_OK;431}432433int ovx_hal_warpPerspective(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])434{435if (skipSmallImages<VX_KERNEL_WARP_PERSPECTIVE>(aw, ah))436return CV_HAL_ERROR_NOT_IMPLEMENTED;437if (dimTooBig(aw) || dimTooBig(ah) || dimTooBig(bw) || dimTooBig(bh))438return CV_HAL_ERROR_NOT_IMPLEMENTED;439refineStep(aw, ah, VX_DF_IMAGE_U8, astep);440refineStep(bw, bh, VX_DF_IMAGE_U8, bstep);441try442{443ivx::Context ctx = getOpenVXHALContext();444vxImage445ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,446ivx::Image::createAddressing(aw, ah, 1, (vx_int32)(astep)), (void*)a),447ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,448ivx::Image::createAddressing(bw, bh, 1, (vx_int32)(bstep)), (void*)b);449450if (!(atype == CV_8UC1 || atype == CV_8SC1))451return CV_HAL_ERROR_NOT_IMPLEMENTED;452453if (borderType != CV_HAL_BORDER_CONSTANT) // Neither 1.0 nor 1.1 OpenVX support BORDER_REPLICATE for warpings454return CV_HAL_ERROR_NOT_IMPLEMENTED;455456int mode;457if (interpolation == CV_HAL_INTER_LINEAR)458mode = VX_INTERPOLATION_BILINEAR;459//AREA interpolation is unsupported460//else if (interpolation == CV_HAL_INTER_AREA)461// mode = VX_INTERPOLATION_AREA;462else if (interpolation == CV_HAL_INTER_NEAREST)463mode = VX_INTERPOLATION_NEAREST_NEIGHBOR;464else465return CV_HAL_ERROR_NOT_IMPLEMENTED;466467std::vector<float> data;468data.reserve(9);469for (int j = 0; j < 3; ++j)470for (int i = 0; i < 3; ++i)471data.push_back((float)(M[i * 3 + j]));472473ivx::Matrix mtx = ivx::Matrix::create(ctx, VX_TYPE_FLOAT32, 3, 3);474mtx.copyFrom(data);475//ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments476//since OpenVX standart says nothing about thread-safety for now477ivx::border_t prevBorder = ctx.immediateBorder();478ctx.setImmediateBorder(VX_BORDER_CONSTANT, (vx_uint8)borderValue[0]);479ivx::IVX_CHECK_STATUS(vxuWarpPerspective(ctx, ia, mtx, mode, ib));480ctx.setImmediateBorder(prevBorder);481}482catch (ivx::RuntimeError & e)483{484PRINT_HALERR_MSG(runtime);485return CV_HAL_ERROR_UNKNOWN;486}487catch (ivx::WrapperError & e)488{489PRINT_HALERR_MSG(wrapper);490return CV_HAL_ERROR_UNKNOWN;491}492return CV_HAL_ERROR_OK;493}494495struct cvhalFilter2D;496497struct FilterCtx498{499ivx::Convolution cnv;500int dst_type;501ivx::border_t border;502FilterCtx(ivx::Context &ctx, const std::vector<short> data, int w, int h, int _dst_type, ivx::border_t & _border) :503cnv(ivx::Convolution::create(ctx, w, h)), dst_type(_dst_type), border(_border) {504cnv.copyFrom(data);505}506};507508int ovx_hal_filterInit(cvhalFilter2D **filter_context, uchar *kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height,509int, int, int src_type, int dst_type, int borderType, double delta, int anchor_x, int anchor_y, bool allowSubmatrix, bool allowInplace)510{511if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || delta != 0 ||512src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) ||513kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2)514return CV_HAL_ERROR_NOT_IMPLEMENTED;515516ivx::border_t border;517switch (borderType)518{519case CV_HAL_BORDER_CONSTANT:520setConstantBorder(border, 0);521break;522case CV_HAL_BORDER_REPLICATE:523border.mode = VX_BORDER_REPLICATE;524break;525default:526return CV_HAL_ERROR_NOT_IMPLEMENTED;527}528529ivx::Context ctx = getOpenVXHALContext();530531std::vector<short> data;532data.reserve(kernel_width*kernel_height);533switch (kernel_type)534{535case CV_8UC1:536for (int j = 0; j < kernel_height; ++j)537{538uchar * row = (uchar*)(kernel_data + kernel_step*j);539for (int i = 0; i < kernel_width; ++i)540data.push_back(row[i]);541}542break;543case CV_8SC1:544for (int j = 0; j < kernel_height; ++j)545{546schar * row = (schar*)(kernel_data + kernel_step*j);547for (int i = 0; i < kernel_width; ++i)548data.push_back(row[i]);549}550break;551case CV_16SC1:552for (int j = 0; j < kernel_height; ++j)553{554short * row = (short*)(kernel_data + kernel_step*j);555for (int i = 0; i < kernel_width; ++i)556data.push_back(row[i]);557}558break;559default:560return CV_HAL_ERROR_NOT_IMPLEMENTED;561}562563FilterCtx* cnv = new FilterCtx(ctx, data, kernel_width, kernel_height, dst_type, border);564if (!cnv)565return CV_HAL_ERROR_UNKNOWN;566567*filter_context = (cvhalFilter2D*)(cnv);568return CV_HAL_ERROR_OK;569}570571int ovx_hal_filterFree(cvhalFilter2D *filter_context)572{573if (filter_context)574{575delete (FilterCtx*)filter_context;576return CV_HAL_ERROR_OK;577}578else579{580return CV_HAL_ERROR_UNKNOWN;581}582}583584int ovx_hal_filter(cvhalFilter2D *filter_context, uchar *a, size_t astep, uchar *b, size_t bstep, int w, int h, int, int, int, int)585{586if (skipSmallImages<VX_KERNEL_CUSTOM_CONVOLUTION>(w, h))587return CV_HAL_ERROR_NOT_IMPLEMENTED;588if (dimTooBig(w) || dimTooBig(h))589return CV_HAL_ERROR_NOT_IMPLEMENTED;590try591{592FilterCtx* cnv = (FilterCtx*)filter_context;593if (!cnv)594throw ivx::WrapperError("Bad HAL context");595refineStep(w, h, VX_DF_IMAGE_U8, astep);596refineStep(w, h, cnv->dst_type == CV_16SC1 ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8, bstep);597598ivx::Context ctx = getOpenVXHALContext();599vxImage600ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,601ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a),602ib = ivx::Image::createFromHandle(ctx, cnv->dst_type == CV_16SC1 ? VX_DF_IMAGE_S16 : VX_DF_IMAGE_U8,603ivx::Image::createAddressing(w, h, cnv->dst_type == CV_16SC1 ? 2 : 1, (vx_int32)(bstep)), (void*)b);604605//ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments606//since OpenVX standart says nothing about thread-safety for now607ivx::border_t prevBorder = ctx.immediateBorder();608ctx.setImmediateBorder(cnv->border);609ivx::IVX_CHECK_STATUS(vxuConvolve(ctx, ia, cnv->cnv, ib));610ctx.setImmediateBorder(prevBorder);611}612catch (ivx::RuntimeError & e)613{614PRINT_HALERR_MSG(runtime);615return CV_HAL_ERROR_UNKNOWN;616}617catch (ivx::WrapperError & e)618{619PRINT_HALERR_MSG(wrapper);620return CV_HAL_ERROR_UNKNOWN;621}622return CV_HAL_ERROR_OK;623}624625int ovx_hal_sepFilterInit(cvhalFilter2D **filter_context, int src_type, int dst_type,626int kernel_type, uchar *kernelx_data, int kernelx_length, uchar *kernely_data, int kernely_length,627int anchor_x, int anchor_y, double delta, int borderType)628{629if (!filter_context || !kernelx_data || !kernely_data || delta != 0 ||630src_type != CV_8UC1 || (dst_type != CV_8UC1 && dst_type != CV_16SC1) ||631kernelx_length != 3 || kernely_length != 3 || anchor_x != 1 || anchor_y != 1)632return CV_HAL_ERROR_NOT_IMPLEMENTED;633634ivx::border_t border;635switch (borderType)636{637case CV_HAL_BORDER_CONSTANT:638setConstantBorder(border, 0);639break;640case CV_HAL_BORDER_REPLICATE:641border.mode = VX_BORDER_REPLICATE;642break;643default:644return CV_HAL_ERROR_NOT_IMPLEMENTED;645}646647ivx::Context ctx = getOpenVXHALContext();648649//At the moment OpenVX doesn't support separable filters natively so combine kernels to generic convolution650std::vector<short> data;651data.reserve(kernelx_length*kernely_length);652switch (kernel_type)653{654case CV_8UC1:655for (int j = 0; j < kernely_length; ++j)656for (int i = 0; i < kernelx_length; ++i)657data.push_back((short)(kernely_data[j]) * kernelx_data[i]);658break;659case CV_8SC1:660for (int j = 0; j < kernely_length; ++j)661for (int i = 0; i < kernelx_length; ++i)662data.push_back((short)(((schar*)kernely_data)[j]) * ((schar*)kernelx_data)[i]);663break;664default:665return CV_HAL_ERROR_NOT_IMPLEMENTED;666}667668FilterCtx* cnv = new FilterCtx(ctx, data, kernelx_length, kernely_length, dst_type, border);669if (!cnv)670return CV_HAL_ERROR_UNKNOWN;671672*filter_context = (cvhalFilter2D*)(cnv);673return CV_HAL_ERROR_OK;674}675676#if VX_VERSION > VX_VERSION_1_0677678struct MorphCtx679{680ivx::Matrix mask;681int operation;682ivx::border_t border;683MorphCtx(ivx::Context &ctx, const std::vector<vx_uint8> data, int w, int h, int _operation, ivx::border_t & _border) :684mask(ivx::Matrix::create(ctx, ivx::TypeToEnum<vx_uint8>::value, w, h)), operation(_operation), border(_border) {685mask.copyFrom(data);686}687};688689int ovx_hal_morphInit(cvhalFilter2D **filter_context, int operation, int src_type, int dst_type, int, int,690int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y,691int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace)692{693if (!filter_context || !kernel_data || allowSubmatrix || allowInplace || iterations != 1 ||694src_type != CV_8UC1 || dst_type != CV_8UC1 ||695kernel_width % 2 == 0 || kernel_height % 2 == 0 || anchor_x != kernel_width / 2 || anchor_y != kernel_height / 2)696return CV_HAL_ERROR_NOT_IMPLEMENTED;697698ivx::border_t border;699switch (borderType)700{701case CV_HAL_BORDER_CONSTANT:702if (borderValue[0] == DBL_MAX && borderValue[1] == DBL_MAX && borderValue[2] == DBL_MAX && borderValue[3] == DBL_MAX)703{704if (operation == CV_HAL_MORPH_ERODE)705setConstantBorder(border, UCHAR_MAX);706else707setConstantBorder(border, 0);708}709else710{711int rounded = (int)round(borderValue[0]);712setConstantBorder(border, (vx_uint8)((unsigned)rounded <= UCHAR_MAX ? rounded : rounded > 0 ? UCHAR_MAX : 0));713}714break;715case CV_HAL_BORDER_REPLICATE:716border.mode = VX_BORDER_REPLICATE;717break;718default:719return CV_HAL_ERROR_NOT_IMPLEMENTED;720}721722ivx::Context ctx = getOpenVXHALContext();723724vx_size maxKernelDim = ctx.nonlinearMaxDimension();725if ((vx_size)kernel_width > maxKernelDim || (vx_size)kernel_height > maxKernelDim)726return CV_HAL_ERROR_NOT_IMPLEMENTED;727728std::vector<vx_uint8> kernel_mat;729kernel_mat.reserve(kernel_width * kernel_height);730switch (CV_MAT_DEPTH(kernel_type))731{732case CV_8U:733case CV_8S:734for (int j = 0; j < kernel_height; ++j)735{736uchar * kernel_row = kernel_data + j * kernel_step;737for (int i = 0; i < kernel_width; ++i)738kernel_mat.push_back(kernel_row[i] ? 255 : 0);739}740break;741case CV_16U:742case CV_16S:743for (int j = 0; j < kernel_height; ++j)744{745short * kernel_row = (short*)(kernel_data + j * kernel_step);746for (int i = 0; i < kernel_width; ++i)747kernel_mat.push_back(kernel_row[i] ? 255 : 0);748}749break;750case CV_32S:751for (int j = 0; j < kernel_height; ++j)752{753int * kernel_row = (int*)(kernel_data + j * kernel_step);754for (int i = 0; i < kernel_width; ++i)755kernel_mat.push_back(kernel_row[i] ? 255 : 0);756}757break;758case CV_32F:759for (int j = 0; j < kernel_height; ++j)760{761float * kernel_row = (float*)(kernel_data + j * kernel_step);762for (int i = 0; i < kernel_width; ++i)763kernel_mat.push_back(kernel_row[i] ? 255 : 0);764}765break;766case CV_64F:767for (int j = 0; j < kernel_height; ++j)768{769double * kernel_row = (double*)(kernel_data + j * kernel_step);770for (int i = 0; i < kernel_width; ++i)771kernel_mat.push_back(kernel_row[i] ? 255 : 0);772}773break;774default:775return CV_HAL_ERROR_NOT_IMPLEMENTED;776}777778MorphCtx* mat;779switch (operation)780{781case CV_HAL_MORPH_ERODE:782mat = new MorphCtx(ctx, kernel_mat, kernel_width, kernel_height, VX_NONLINEAR_FILTER_MIN, border);783break;784case CV_HAL_MORPH_DILATE:785mat = new MorphCtx(ctx, kernel_mat, kernel_width, kernel_height, VX_NONLINEAR_FILTER_MAX, border);786break;787default:788return CV_HAL_ERROR_NOT_IMPLEMENTED;789}790if (!mat)791return CV_HAL_ERROR_UNKNOWN;792793*filter_context = (cvhalFilter2D*)(mat);794return CV_HAL_ERROR_OK;795}796797int ovx_hal_morphFree(cvhalFilter2D *filter_context)798{799if (filter_context)800{801delete (MorphCtx*)filter_context;802return CV_HAL_ERROR_OK;803}804else805{806return CV_HAL_ERROR_UNKNOWN;807}808}809810int 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)811{812if (skipSmallImages<VX_KERNEL_DILATE_3x3>(w, h))//Actually it make sense to separate checks if implementations of dilation and erosion have different performance gain813return CV_HAL_ERROR_NOT_IMPLEMENTED;814if (dimTooBig(w) || dimTooBig(h))815return CV_HAL_ERROR_NOT_IMPLEMENTED;816refineStep(w, h, VX_DF_IMAGE_U8, astep);817refineStep(w, h, VX_DF_IMAGE_U8, bstep);818try819{820MorphCtx* mat = (MorphCtx*)filter_context;821if (!mat)822throw ivx::WrapperError("Bad HAL context");823824ivx::Context ctx = getOpenVXHALContext();825vxImage826ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,827ivx::Image::createAddressing(w, h, 1, (vx_int32)(astep)), (void*)a),828ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,829ivx::Image::createAddressing(w, h, 1, (vx_int32)(bstep)), (void*)b);830831//ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments832//since OpenVX standart says nothing about thread-safety for now833ivx::border_t prevBorder = ctx.immediateBorder();834ctx.setImmediateBorder(mat->border);835ivx::IVX_CHECK_STATUS(vxuNonLinearFilter(ctx, mat->operation, ia, mat->mask, ib));836ctx.setImmediateBorder(prevBorder);837}838catch (ivx::RuntimeError & e)839{840PRINT_HALERR_MSG(runtime);841return CV_HAL_ERROR_UNKNOWN;842}843catch (ivx::WrapperError & e)844{845PRINT_HALERR_MSG(wrapper);846return CV_HAL_ERROR_UNKNOWN;847}848return CV_HAL_ERROR_OK;849}850851#endif // 1.0 guard852853int 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)854{855if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))856return CV_HAL_ERROR_NOT_IMPLEMENTED;857if (dimTooBig(w) || dimTooBig(h))858return CV_HAL_ERROR_NOT_IMPLEMENTED;859if (depth != CV_8U || swapBlue || acn == bcn || (acn != 3 && acn != 4) || (bcn != 3 && bcn != 4))860return CV_HAL_ERROR_NOT_IMPLEMENTED;861862if (w & 1 || h & 1) // It's strange but sample implementation unable to convert odd sized images863return CV_HAL_ERROR_NOT_IMPLEMENTED;864refineStep(w, h, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, astep);865refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);866try867{868ivx::Context ctx = getOpenVXHALContext();869vxImage870ia = ivx::Image::createFromHandle(ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,871ivx::Image::createAddressing(w, h, acn, (vx_int32)astep), (void*)a),872ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,873ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);874ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));875}876catch (ivx::RuntimeError & e)877{878PRINT_HALERR_MSG(runtime);879return CV_HAL_ERROR_UNKNOWN;880}881catch (ivx::WrapperError & e)882{883PRINT_HALERR_MSG(wrapper);884return CV_HAL_ERROR_UNKNOWN;885}886return CV_HAL_ERROR_OK;887}888889int ovx_hal_cvtGraytoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int depth, int bcn)890{891if (skipSmallImages<VX_KERNEL_CHANNEL_COMBINE>(w, h))892return CV_HAL_ERROR_NOT_IMPLEMENTED;893if (dimTooBig(w) || dimTooBig(h))894return CV_HAL_ERROR_NOT_IMPLEMENTED;895if (depth != CV_8U || (bcn != 3 && bcn != 4))896return CV_HAL_ERROR_NOT_IMPLEMENTED;897refineStep(w, h, VX_DF_IMAGE_U8, astep);898refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);899try900{901ivx::Context ctx = getOpenVXHALContext();902ivx::Image903ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,904ivx::Image::createAddressing(w, h, 1, (vx_int32)astep), const_cast<uchar*>(a)),905ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,906ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);907ivx::IVX_CHECK_STATUS(vxuChannelCombine(ctx, ia, ia, ia,908bcn == 4 ? (vx_image)(ivx::Image::createUniform(ctx, w, h, VX_DF_IMAGE_U8, vx_uint8(255))) : NULL,909ib));910}911catch (ivx::RuntimeError & e)912{913PRINT_HALERR_MSG(runtime);914return CV_HAL_ERROR_UNKNOWN;915}916catch (ivx::WrapperError & e)917{918PRINT_HALERR_MSG(wrapper);919return CV_HAL_ERROR_UNKNOWN;920}921return CV_HAL_ERROR_OK;922}923924int ovx_hal_cvtTwoPlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx)925{926if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))927return CV_HAL_ERROR_NOT_IMPLEMENTED;928if (dimTooBig(w) || dimTooBig(h))929return CV_HAL_ERROR_NOT_IMPLEMENTED;930if (!swapBlue || (bcn != 3 && bcn != 4))931return CV_HAL_ERROR_NOT_IMPLEMENTED;932933if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images934return CV_HAL_ERROR_NOT_IMPLEMENTED;935refineStep(w, h, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, astep);936refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);937try938{939ivx::Context ctx = getOpenVXHALContext();940941std::vector<vx_imagepatch_addressing_t> addr;942std::vector<void *> ptrs;943addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)astep));944ptrs.push_back((void*)a);945addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 2, (vx_int32)astep));946ptrs.push_back((void*)(a + h * astep));947948vxImage949ia = ivx::Image::createFromHandle(ctx, uIdx ? VX_DF_IMAGE_NV21 : VX_DF_IMAGE_NV12, addr, ptrs);950if (ia.range() == VX_CHANNEL_RANGE_FULL)951return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL952vxImage953ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,954ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);955ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));956}957catch (ivx::RuntimeError & e)958{959PRINT_HALERR_MSG(runtime);960return CV_HAL_ERROR_UNKNOWN;961}962catch (ivx::WrapperError & e)963{964PRINT_HALERR_MSG(wrapper);965return CV_HAL_ERROR_UNKNOWN;966}967return CV_HAL_ERROR_OK;968}969970int ovx_hal_cvtThreePlaneYUVtoBGR(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int bcn, bool swapBlue, int uIdx)971{972if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))973return CV_HAL_ERROR_NOT_IMPLEMENTED;974if (dimTooBig(w) || dimTooBig(h))975return CV_HAL_ERROR_NOT_IMPLEMENTED;976if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx || (size_t)w / 2 != astep - (size_t)w / 2)977return CV_HAL_ERROR_NOT_IMPLEMENTED;978979if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images980return CV_HAL_ERROR_NOT_IMPLEMENTED;981refineStep(w, h, VX_DF_IMAGE_IYUV, astep);982refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);983try984{985ivx::Context ctx = getOpenVXHALContext();986987std::vector<vx_imagepatch_addressing_t> addr;988std::vector<void *> ptrs;989addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)astep));990ptrs.push_back((void*)a);991addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2));992ptrs.push_back((void*)(a + h * astep));993if (addr[1].dim_x != (astep - addr[1].dim_x))994throw ivx::WrapperError("UV planes use variable stride");995addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2));996ptrs.push_back((void*)(a + h * astep + addr[1].dim_y * addr[1].stride_y));997998vxImage999ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_IYUV, addr, ptrs);1000if (ia.range() == VX_CHANNEL_RANGE_FULL)1001return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL1002vxImage1003ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,1004ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);1005ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));1006}1007catch (ivx::RuntimeError & e)1008{1009PRINT_HALERR_MSG(runtime);1010return CV_HAL_ERROR_UNKNOWN;1011}1012catch (ivx::WrapperError & e)1013{1014PRINT_HALERR_MSG(wrapper);1015return CV_HAL_ERROR_UNKNOWN;1016}1017return CV_HAL_ERROR_OK;1018}10191020int ovx_hal_cvtBGRtoThreePlaneYUV(const uchar * a, size_t astep, uchar * b, size_t bstep, int w, int h, int acn, bool swapBlue, int uIdx)1021{1022if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))1023return CV_HAL_ERROR_NOT_IMPLEMENTED;1024if (dimTooBig(w) || dimTooBig(h))1025return CV_HAL_ERROR_NOT_IMPLEMENTED;1026if (!swapBlue || (acn != 3 && acn != 4) || uIdx || (size_t)w / 2 != bstep - (size_t)w / 2)1027return CV_HAL_ERROR_NOT_IMPLEMENTED;10281029if (w & 1 || h & 1) // It's not described in spec but sample implementation unable to convert odd sized images1030return CV_HAL_ERROR_NOT_IMPLEMENTED;1031refineStep(w, h, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, astep);1032refineStep(w, h, VX_DF_IMAGE_IYUV, bstep);1033try1034{1035ivx::Context ctx = getOpenVXHALContext();1036vxImage1037ia = ivx::Image::createFromHandle(ctx, acn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,1038ivx::Image::createAddressing(w, h, acn, (vx_int32)astep), (void*)a);10391040std::vector<vx_imagepatch_addressing_t> addr;1041std::vector<void *> ptrs;1042addr.push_back(ivx::Image::createAddressing(w, h, 1, (vx_int32)bstep));1043ptrs.push_back((void*)b);1044addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2));1045ptrs.push_back((void*)(b + h * bstep));1046if (addr[1].dim_x != (bstep - addr[1].dim_x))1047throw ivx::WrapperError("UV planes use variable stride");1048addr.push_back(ivx::Image::createAddressing(w / 2, h / 2, 1, w / 2));1049ptrs.push_back((void*)(b + h * bstep + addr[1].dim_y * addr[1].stride_y));10501051vxImage1052ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_IYUV, addr, ptrs);1053ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));1054}1055catch (ivx::RuntimeError & e)1056{1057PRINT_HALERR_MSG(runtime);1058return CV_HAL_ERROR_UNKNOWN;1059}1060catch (ivx::WrapperError & e)1061{1062PRINT_HALERR_MSG(wrapper);1063return CV_HAL_ERROR_UNKNOWN;1064}1065return CV_HAL_ERROR_OK;1066}10671068int 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)1069{1070if (skipSmallImages<VX_KERNEL_COLOR_CONVERT>(w, h))1071return CV_HAL_ERROR_NOT_IMPLEMENTED;1072if (dimTooBig(w) || dimTooBig(h))1073return CV_HAL_ERROR_NOT_IMPLEMENTED;1074if (!swapBlue || (bcn != 3 && bcn != 4) || uIdx)1075return CV_HAL_ERROR_NOT_IMPLEMENTED;10761077if (w & 1) // It's not described in spec but sample implementation unable to convert odd sized images1078return CV_HAL_ERROR_NOT_IMPLEMENTED;1079refineStep(w, h, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV, astep);1080refineStep(w, h, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX, bstep);1081try1082{1083ivx::Context ctx = getOpenVXHALContext();1084vxImage1085ia = ivx::Image::createFromHandle(ctx, ycn ? VX_DF_IMAGE_UYVY : VX_DF_IMAGE_YUYV,1086ivx::Image::createAddressing(w, h, 2, (vx_int32)astep), (void*)a);1087if (ia.range() == VX_CHANNEL_RANGE_FULL)1088return CV_HAL_ERROR_NOT_IMPLEMENTED; // OpenCV store NV12/NV21 as RANGE_RESTRICTED while OpenVX expect RANGE_FULL1089vxImage1090ib = ivx::Image::createFromHandle(ctx, bcn == 3 ? VX_DF_IMAGE_RGB : VX_DF_IMAGE_RGBX,1091ivx::Image::createAddressing(w, h, bcn, (vx_int32)bstep), b);1092ivx::IVX_CHECK_STATUS(vxuColorConvert(ctx, ia, ib));1093}1094catch (ivx::RuntimeError & e)1095{1096PRINT_HALERR_MSG(runtime);1097return CV_HAL_ERROR_UNKNOWN;1098}1099catch (ivx::WrapperError & e)1100{1101PRINT_HALERR_MSG(wrapper);1102return CV_HAL_ERROR_UNKNOWN;1103}1104return CV_HAL_ERROR_OK;1105}11061107int 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)1108{1109if (skipSmallImages<VX_KERNEL_INTEGRAL_IMAGE>(w, h))1110return CV_HAL_ERROR_NOT_IMPLEMENTED;1111if (depth != CV_8U || sdepth != CV_32S || c != NULL || d != NULL || cn != 1)1112return CV_HAL_ERROR_NOT_IMPLEMENTED;1113refineStep(w, h, VX_DF_IMAGE_U8, astep);1114try1115{1116ivx::Context ctx = getOpenVXHALContext();1117ivx::Image1118ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,1119ivx::Image::createAddressing(w, h, 1, (vx_int32)astep), const_cast<uchar*>(a)),1120ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U32,1121ivx::Image::createAddressing(w, h, 4, (vx_int32)bstep), (unsigned int *)(b + bstep + sizeof(unsigned int)));1122ivx::IVX_CHECK_STATUS(vxuIntegralImage(ctx, ia, ib));1123std::memset(b, 0, (w + 1) * sizeof(unsigned int));1124b += bstep;1125for (int i = 0; i < h; i++, b += bstep)1126{1127*((unsigned int*)b) = 0;1128}1129}1130catch (ivx::RuntimeError & e)1131{1132PRINT_HALERR_MSG(runtime);1133return CV_HAL_ERROR_UNKNOWN;1134}1135catch (ivx::WrapperError & e)1136{1137PRINT_HALERR_MSG(wrapper);1138return CV_HAL_ERROR_UNKNOWN;1139}11401141return CV_HAL_ERROR_OK;1142}114311441145