// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // Copyright (C) 2016, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. /* C++ wrappers over OpenVX 1.x C API Details: TBD */ #pragma once #ifndef IVX_HPP #define IVX_HPP #ifndef __cplusplus #error This file has to be compiled with C++ compiler #endif #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; #else #ifdef IVX_RENAMED_REFS static const vx_enum VX_REF_ATTRIBUTE_TYPE = VX_REFERENCE_TYPE; #endif #endif #ifndef IVX_USE_CXX98 // checking compiler #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1800) #define IVX_USE_CXX98 #endif #endif // IVX_USE_CXX98 #if defined(IVX_USE_CXX98) && !defined(IVX_HIDE_INFO_WARNINGS) #ifdef _MSC_VER #pragma message ("ivx.hpp: The ISO C++ 2011 standard is not enabled, switching to C++98 fallback implementation.") #else #warning The ISO C++ 2011 standard is not enabled, switching to C++98 fallback implementation. #endif #endif // IVX_USE_CXX98 #ifndef IVX_USE_EXTERNAL_REFCOUNT // checking OpenVX version #ifndef VX_VERSION_1_1 #define IVX_USE_EXTERNAL_REFCOUNT #endif #endif // IVX_USE_CXX98 #if defined(IVX_USE_EXTERNAL_REFCOUNT) && !defined(IVX_HIDE_INFO_WARNINGS) #ifdef _MSC_VER #pragma message ("ivx.hpp: OpenVX version < 1.1, switching to external refcounter implementation.") #else #warning OpenVX version < 1.1, switching to external refcounter implementation. #endif #endif // IVX_USE_EXTERNAL_REFCOUNT #include #include #include #include #include #ifndef IVX_USE_CXX98 #include namespace ivx { using std::is_same; using std::is_pointer; } #else namespace ivx { // helpers for compile-time type checking template struct is_same { static const bool value = false; }; template struct is_same { static const bool value = true; }; template struct is_pointer { static const bool value = false; }; template struct is_pointer { static const bool value = true; }; template struct is_pointer { static const bool value = true; }; } #endif #ifdef IVX_USE_OPENCV #include "opencv2/core.hpp" #endif // disabling false alarm warnings #if defined(_MSC_VER) #pragma warning(push) //#pragma warning( disable : 4??? ) #elif defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-local-typedef" #pragma clang diagnostic ignored "-Wmissing-prototypes" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-value" #pragma GCC diagnostic ignored "-Wmissing-declarations" #endif // compiler macro namespace ivx { inline vx_uint16 compiledWithVersion() { return VX_VERSION; } /// Exception class for OpenVX runtime errors class RuntimeError : public std::runtime_error { public: /// Constructor explicit RuntimeError(vx_status st, const std::string& msg = "") : runtime_error(msg), _status(st) {} /// OpenVX error code vx_status status() const { return _status; } private: vx_status _status; }; /// Exception class for wrappers logic errors class WrapperError : public std::logic_error { public: /// Constructor explicit WrapperError(const std::string& msg) : logic_error(msg) {} }; inline void checkVxStatus(vx_status status, const std::string& func, const std::string& msg) { if(status != VX_SUCCESS) throw RuntimeError( status, func + "() : " + msg ); } /// Helper macro for turning a runtime error in the provided code into a \RuntimeError #define IVX_CHECK_STATUS(code) checkVxStatus(code, __func__, #code) /// OpenVX enum to type compile-time converter (TODO: add more types) template struct EnumToType {}; template<> struct EnumToType { typedef vx_char type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_int8 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_uint8 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_int16 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_uint16 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_int32 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_uint32 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_int64 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_uint64 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_float32 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_float64 type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_enum type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_size type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_df_image type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_bool type; static const vx_size bytes = sizeof(type); }; template<> struct EnumToType { typedef vx_keypoint_t type;static const vx_size bytes = sizeof(type); }; #ifndef IVX_USE_CXX98 template using EnumToType_t = typename EnumToType::type; #endif /// Gets size in bytes for the provided OpenVX type enum inline vx_size enumToTypeSize(vx_enum type) { switch (type) { case VX_TYPE_CHAR: return EnumToType::bytes; case VX_TYPE_INT8: return EnumToType::bytes; case VX_TYPE_UINT8: return EnumToType::bytes; case VX_TYPE_INT16: return EnumToType::bytes; case VX_TYPE_UINT16: return EnumToType::bytes; case VX_TYPE_INT32: return EnumToType::bytes; case VX_TYPE_UINT32: return EnumToType::bytes; case VX_TYPE_INT64: return EnumToType::bytes; case VX_TYPE_UINT64: return EnumToType::bytes; case VX_TYPE_FLOAT32: return EnumToType::bytes; case VX_TYPE_FLOAT64: return EnumToType::bytes; case VX_TYPE_ENUM: return EnumToType::bytes; case VX_TYPE_SIZE: return EnumToType::bytes; case VX_TYPE_DF_IMAGE: return EnumToType::bytes; case VX_TYPE_BOOL: return EnumToType::bytes; case VX_TYPE_KEYPOINT: return EnumToType::bytes; default: throw WrapperError(std::string(__func__) + ": unsupported type enum"); } } /// type to enum compile-time converter (TODO: add more types) 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, 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, 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; }; // the commented types are aliases (of integral tyes) and have conflicts with the types above //template<> struct TypeToEnum { static const vx_enum val = VX_TYPE_ENUM; }; //template<> struct TypeToEnum { static const vx_enum val = VX_TYPE_SIZE; }; //template<> struct TypeToEnum { static const vx_enum val = VX_TYPE_DF_IMAGE; }; inline bool areTypesCompatible(const vx_enum a, const vx_enum b) { return enumToTypeSize(a) == enumToTypeSize(b); } #ifdef IVX_USE_OPENCV inline int enumToCVType(vx_enum type) { switch (type) { case VX_TYPE_CHAR: return CV_8UC1;//While OpenCV support 8S as well, 8U is supported wider case VX_TYPE_INT8: return CV_8SC1; case VX_TYPE_UINT8: return CV_8UC1; case VX_TYPE_INT16: return CV_16SC1; case VX_TYPE_UINT16: return CV_16UC1; case VX_TYPE_INT32: return CV_32SC1; case VX_TYPE_UINT32: return CV_32SC1;//That's not the best option but there is CV_32S type only case VX_TYPE_FLOAT32: return CV_32FC1; case VX_TYPE_FLOAT64: return CV_64FC1; case VX_TYPE_ENUM: return CV_32SC1; case VX_TYPE_BOOL: return CV_32SC1; default: throw WrapperError(std::string(__func__) + ": unsupported type enum"); } } #endif /// Helper type, provides info for OpenVX 'objects' (vx_reference extending) types template struct RefTypeTraits {}; class Context; template <> struct RefTypeTraits { typedef vx_context vxType; typedef Context wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_CONTEXT; static vx_status release(vxType& ref) { return vxReleaseContext(&ref); } }; class Graph; template <> struct RefTypeTraits { typedef vx_graph vxType; typedef Graph wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_GRAPH; static vx_status release(vxType& ref) { return vxReleaseGraph(&ref); } }; class Node; template <> struct RefTypeTraits { typedef vx_node vxType; typedef Node wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_NODE; static vx_status release(vxType& ref) { return vxReleaseNode(&ref); } }; class Kernel; template <> struct RefTypeTraits { typedef vx_kernel vxType; typedef Kernel wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_KERNEL; static vx_status release(vxType& ref) { return vxReleaseKernel(&ref); } }; class Param; template <> struct RefTypeTraits { typedef vx_parameter vxType; typedef Param wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_PARAMETER; static vx_status release(vxType& ref) { return vxReleaseParameter(&ref); } }; class Image; template <> struct RefTypeTraits { typedef vx_image vxType; typedef Image wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_IMAGE; static vx_status release(vxType& ref) { return vxReleaseImage(&ref); } }; class Scalar; template <> struct RefTypeTraits { typedef vx_scalar vxType; typedef Scalar wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_SCALAR; static vx_status release(vxType& ref) { return vxReleaseScalar(&ref); } }; class Array; template <> struct RefTypeTraits { typedef vx_array vxType; typedef Array wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_ARRAY; static vx_status release(vxType& ref) { return vxReleaseArray(&ref); } }; class Threshold; template <> struct RefTypeTraits { typedef vx_threshold vxType; typedef Threshold wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_THRESHOLD; static vx_status release(vxType& ref) { return vxReleaseThreshold(&ref); } }; class Convolution; template <> struct RefTypeTraits { typedef vx_convolution vxType; typedef Convolution wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_CONVOLUTION; static vx_status release(vxType& ref) { return vxReleaseConvolution(&ref); } }; class Matrix; template <> struct RefTypeTraits { typedef vx_matrix vxType; typedef Matrix wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_MATRIX; static vx_status release(vxType& ref) { return vxReleaseMatrix(&ref); } }; class LUT; template <> struct RefTypeTraits { typedef vx_lut vxType; typedef LUT wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_LUT; static vx_status release(vxType& ref) { return vxReleaseLUT(&ref); } }; class Pyramid; template <> struct RefTypeTraits { typedef vx_pyramid vxType; typedef Pyramid wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_PYRAMID; static vx_status release(vxType& ref) { return vxReleasePyramid(&ref); } }; class Distribution; template <> struct RefTypeTraits { typedef vx_distribution vxType; typedef Distribution wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_DISTRIBUTION; static vx_status release(vxType& ref) { return vxReleaseDistribution(&ref); } }; class Remap; template <> struct RefTypeTraits { typedef vx_remap vxType; typedef Remap wrapperType; static const vx_enum vxTypeEnum = VX_TYPE_REMAP; static vx_status release(vxType& ref) { return vxReleaseRemap(&ref); } }; #ifdef IVX_USE_CXX98 /// Casting to vx_reference with compile-time check // takes 'vx_reference' itself and RefWrapper via 'operator vx_reference()' inline vx_reference castToReference(vx_reference ref) { return ref; } // takes vx_reference extensions that have RefTypeTraits specializations template inline vx_reference castToReference(const T& ref, typename RefTypeTraits::vxType dummy = 0) { (void)dummy; return (vx_reference)ref; } #else template struct is_ref : std::is_same{}; // allow vx_reference // allow RefWrapper<> types template #ifndef _MSC_VER struct is_ref : std::true_type {}; #else // workarounding VC14 compiler crash struct is_ref : std::true_type {}; #endif // allow vx_reference extensions template struct is_ref::vxTypeEnum, void())> : std::true_type {}; /// Casting to vx_reference with compile-time check template inline vx_reference castToReference(const T& obj) { static_assert(is_ref::value, "unsupported conversion"); return (vx_reference) obj; } #endif // IVX_USE_CXX98 inline void checkVxRef(vx_reference ref, const std::string& func, const std::string& msg) { vx_status status = vxGetStatus(ref); if(status != VX_SUCCESS) throw RuntimeError( status, func + "() : " + msg ); } /// Helper macro for checking the provided OpenVX 'object' and throwing a \RuntimeError in case of error #define IVX_CHECK_REF(code) checkVxRef(castToReference(code), __func__, #code) #ifdef IVX_USE_EXTERNAL_REFCOUNT /// Base class for OpenVX 'objects' wrappers template class RefWrapper { public: typedef T vxType; static const vx_enum vxTypeEnum = RefTypeTraits ::vxTypeEnum; /// Default constructor RefWrapper() : ref(0), refcount(0) {} /// Constructor /// \param r OpenVX 'object' (e.g. vx_image) /// \param retainRef flag indicating whether to increase ref counter in constructor (false by default) explicit RefWrapper(T r, bool retainRef = false) : ref(0), refcount(0) { reset(r, retainRef); } /// Copy constructor RefWrapper(const RefWrapper& r) : ref(r.ref), refcount(r.refcount) { addRef(); } #ifndef IVX_USE_CXX98 /// Move constructor RefWrapper(RefWrapper&& rw) noexcept : RefWrapper() { using std::swap; swap(ref, rw.ref); swap(refcount, rw.refcount); } #endif /// Casting to the wrapped OpenVX 'object' operator T() const { return ref; } /// Casting to vx_reference since every OpenVX 'object' extends it operator vx_reference() const { return castToReference(ref); } /// Assigning a new value (decreasing ref counter for the old one) /// \param r OpenVX 'object' (e.g. vx_image) /// \param retainRef flag indicating whether to increase ref counter in constructor (false by default) void reset(T r, bool retainRef = false) { release(); ref = r; #ifdef VX_VERSION_1_1 if(retainRef) addRef(); #else // if 'retainRef' -just don't use ref-counting for v 1.0 if(!retainRef) refcount = new int(1); #endif checkRef(); } /// Assigning an empty value (decreasing ref counter for the old one) void reset() { release(); } /// Dropping kept value without releas decreasing ref counter /// \return the value being dropped T detach() { T tmp = ref; ref = 0; release(); return tmp; } /// Unified assignment operator (covers both copy and move cases) RefWrapper& operator=(RefWrapper r) { using std::swap; swap(ref, r.ref); swap(refcount, r.refcount); return *this; } /// Checking for non-empty bool operator !() const { return ref == 0; } #ifndef IVX_USE_CXX98 /// Explicit boolean evaluation (called automatically inside conditional operators only) explicit operator bool() const { return ref != 0; } #endif /// Getting a context that is kept in each OpenVX 'object' (call get()) template C get() const { typedef int static_assert_context[is_same::value ? 1 : -1]; vx_context c = vxGetContext(castToReference(ref)); // vxGetContext doesn't increment ref count, let do it in wrapper c-tor return C(c, true); } #ifndef IVX_USE_CXX98 /// Getting a context that is kept in each OpenVX 'object' template::value>::type> C getContext() const { vx_context c = vxGetContext(castToReference(ref)); // vxGetContext doesn't increment ref count, let do it in wrapper c-tor return C(c, true); } #endif // IVX_USE_CXX98 protected: T ref; int* refcount; void addRef() { #ifdef VX_VERSION_1_1 if(ref) IVX_CHECK_STATUS(vxRetainReference(castToReference(ref))); #else //TODO: make thread-safe if(refcount) ++(*refcount); #endif } void release() { #ifdef VX_VERSION_1_1 if(ref) RefTypeTraits::release(ref); #else //TODO: make thread-safe if(refcount && --(*refcount) == 0) { if(ref) RefTypeTraits::release(ref); ref = 0; delete refcount; refcount = 0; } #endif } void checkRef() const { IVX_CHECK_REF(ref); vx_enum type; IVX_CHECK_STATUS(vxQueryReference((vx_reference)ref, VX_REF_ATTRIBUTE_TYPE, &type, sizeof(type))); if (type != vxTypeEnum) throw WrapperError("incompatible reference type"); } ~RefWrapper() { release(); } }; #ifdef IVX_USE_CXX98 #define IVX_REF_STD_CTORS_AND_ASSIGNMENT(Class) \ Class() : RefWrapper() {} \ explicit Class(Class::vxType _ref, bool retainRef = false) : RefWrapper(_ref, retainRef) {} \ Class(const Class& _obj) : RefWrapper(_obj) {} \ \ Class& operator=(Class _obj) { using std::swap; swap(ref, _obj.ref); swap(refcount, _obj.refcount); return *this; } #else #define IVX_REF_STD_CTORS_AND_ASSIGNMENT(Class) \ Class() : RefWrapper() {} \ explicit Class(Class::vxType _ref, bool retainRef = false) : RefWrapper(_ref, retainRef) {} \ Class(const Class& _obj) : RefWrapper(_obj) {} \ Class(Class&& _obj) : RefWrapper(std::move(_obj)) {} \ \ Class& operator=(Class _obj) { using std::swap; swap(ref, _obj.ref); swap(refcount, _obj.refcount); return *this; } #endif // IVX_USE_CXX98 #else // not IVX_USE_EXTERNAL_REFCOUNT /// Base class for OpenVX 'objects' wrappers template class RefWrapper { public: typedef T vxType; static const vx_enum vxTypeEnum = RefTypeTraits ::vxTypeEnum; /// Default constructor RefWrapper() : ref(0) {} /// Constructor /// \param r OpenVX 'object' (e.g. vx_image) /// \param retainRef flag indicating whether to increase ref counter in constructor (false by default) explicit RefWrapper(T r, bool retainRef = false) : ref(0) { reset(r, retainRef); } /// Copy constructor RefWrapper(const RefWrapper& r) : ref(r.ref) { addRef(); } #ifndef IVX_USE_CXX98 /// Move constructor RefWrapper(RefWrapper&& rw) noexcept : RefWrapper() { using std::swap; swap(ref, rw.ref); } #endif /// Casting to the wrapped OpenVX 'object' operator T() const { return ref; } /// Casting to vx_reference since every OpenVX 'object' extends it operator vx_reference() const { return castToReference(ref); } /// Getting a context that is kept in each OpenVX 'object' (call get()) template C get() const { typedef int static_assert_context[is_same::value ? 1 : -1]; vx_context c = vxGetContext(castToReference(ref)); // vxGetContext doesn't increment ref count, let do it in wrapper c-tor return C(c, true); } #ifndef IVX_USE_CXX98 /// Getting a context that is kept in each OpenVX 'object' template::value>::type> C getContext() const { vx_context c = vxGetContext(castToReference(ref)); // vxGetContext doesn't increment ref count, let do it in wrapper c-tor return C(c, true); } #endif // IVX_USE_CXX98 /// Assigning a new value (decreasing ref counter for the old one) /// \param r OpenVX 'object' (e.g. vx_image) /// \param retainRef flag indicating whether to increase ref counter in constructor (false by default) void reset(T r, bool retainRef = false) { release(); ref = r; if (retainRef) addRef(); checkRef(); } /// Assigning an empty value (decreasing ref counter for the old one) void reset() { release(); } /// Dropping kept value without releas decreasing ref counter /// \return the value being dropped T detach() { T tmp = ref; ref = 0; return tmp; } /// Unified assignment operator (covers both copy and move cases) RefWrapper& operator=(RefWrapper r) { using std::swap; swap(ref, r.ref); return *this; } /// Checking for non-empty bool operator !() const { return ref == 0; } #ifndef IVX_USE_CXX98 /// Explicit boolean evaluation (called automatically inside conditional operators only) explicit operator bool() const { return ref != 0; } #endif protected: T ref; void addRef() { if (ref) IVX_CHECK_STATUS(vxRetainReference((vx_reference)ref)); } void release() { if (ref) RefTypeTraits::release(ref); ref = 0; } void checkRef() const { IVX_CHECK_REF(ref); vx_enum type; IVX_CHECK_STATUS(vxQueryReference((vx_reference)ref, VX_REF_ATTRIBUTE_TYPE, &type, sizeof(type))); if (type != vxTypeEnum) throw WrapperError("incompatible reference type"); } ~RefWrapper() { release(); } }; #ifdef IVX_USE_CXX98 #define IVX_REF_STD_CTORS_AND_ASSIGNMENT(Class) \ Class() : RefWrapper() {} \ explicit Class(Class::vxType _ref, bool retainRef = false) : RefWrapper(_ref, retainRef) {} \ Class(const Class& _obj) : RefWrapper(_obj) {} \ \ Class& operator=(Class _obj) { using std::swap; swap(ref, _obj.ref); return *this; } #else #define IVX_REF_STD_CTORS_AND_ASSIGNMENT(Class) \ Class() : RefWrapper() {} \ explicit Class(Class::vxType _ref, bool retainRef = false) : RefWrapper(_ref, retainRef) {} \ Class(const Class& _obj) : RefWrapper(_obj) {} \ Class(Class&& _obj) : RefWrapper(std::move(_obj)) {} \ \ Class& operator=(Class _obj) { using std::swap; swap(ref, _obj.ref); return *this; } #endif // IVX_USE_CXX98 #endif // IVX_USE_EXTERNAL_REFCOUNT #ifndef VX_VERSION_1_1 typedef vx_border_mode_t border_t; #else typedef vx_border_t border_t; #endif /// vx_context wrapper class Context : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Context) /// vxCreateContext() wrapper static Context create() { return Context(vxCreateContext()); } /// vxGetContext() wrapper template static Context getFrom(const T& ref) { vx_context c = vxGetContext(castToReference(ref)); // vxGetContext doesn't increment ref count, let do it in wrapper c-tor return Context(c, true); } /// vxLoadKernels() wrapper void loadKernels(const std::string& module) { IVX_CHECK_STATUS( vxLoadKernels(ref, module.c_str()) ); } /// vxQueryContext() wrapper template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS(vxQueryContext(ref, att, &value, sizeof(value))); } #ifndef VX_VERSION_1_1 static const vx_enum VX_CONTEXT_VENDOR_ID = VX_CONTEXT_ATTRIBUTE_VENDOR_ID, VX_CONTEXT_VERSION = VX_CONTEXT_ATTRIBUTE_VERSION, VX_CONTEXT_UNIQUE_KERNELS = VX_CONTEXT_ATTRIBUTE_UNIQUE_KERNELS, VX_CONTEXT_MODULES = VX_CONTEXT_ATTRIBUTE_MODULES, VX_CONTEXT_REFERENCES = VX_CONTEXT_ATTRIBUTE_REFERENCES, VX_CONTEXT_IMPLEMENTATION = VX_CONTEXT_ATTRIBUTE_IMPLEMENTATION, VX_CONTEXT_EXTENSIONS_SIZE = VX_CONTEXT_ATTRIBUTE_EXTENSIONS_SIZE, VX_CONTEXT_EXTENSIONS = VX_CONTEXT_ATTRIBUTE_EXTENSIONS, VX_CONTEXT_CONVOLUTION_MAX_DIMENSION = VX_CONTEXT_ATTRIBUTE_CONVOLUTION_MAXIMUM_DIMENSION, VX_CONTEXT_OPTICAL_FLOW_MAX_WINDOW_DIMENSION = VX_CONTEXT_ATTRIBUTE_OPTICAL_FLOW_WINDOW_MAXIMUM_DIMENSION, VX_CONTEXT_IMMEDIATE_BORDER = VX_CONTEXT_ATTRIBUTE_IMMEDIATE_BORDER_MODE, VX_CONTEXT_UNIQUE_KERNEL_TABLE = VX_CONTEXT_ATTRIBUTE_UNIQUE_KERNEL_TABLE; #endif /// vxQueryContext(VX_CONTEXT_VENDOR_ID) wrapper vx_uint16 vendorID() const { vx_uint16 v; query(VX_CONTEXT_VENDOR_ID, v); return v; } /// vxQueryContext(VX_CONTEXT_VERSION) wrapper vx_uint16 version() const { vx_uint16 v; query(VX_CONTEXT_VERSION, v); return v; } /// vxQueryContext(VX_CONTEXT_UNIQUE_KERNELS) wrapper vx_uint32 uniqueKernelsNum() const { vx_uint32 v; query(VX_CONTEXT_UNIQUE_KERNELS, v); return v; } /// vxQueryContext(VX_CONTEXT_MODULES) wrapper vx_uint32 modulesNum() const { vx_uint32 v; query(VX_CONTEXT_MODULES, v); return v; } /// vxQueryContext(VX_CONTEXT_REFERENCES) wrapper vx_uint32 refsNum() const { vx_uint32 v; query(VX_CONTEXT_REFERENCES, v); return v; } /// vxQueryContext(VX_CONTEXT_EXTENSIONS_SIZE) wrapper vx_size extensionsSize() const { vx_size v; query(VX_CONTEXT_EXTENSIONS_SIZE, v); return v; } /// vxQueryContext(VX_CONTEXT_CONVOLUTION_MAX_DIMENSION) wrapper vx_size convolutionMaxDimension() const { vx_size v; query(VX_CONTEXT_CONVOLUTION_MAX_DIMENSION, v); return v; } /// vxQueryContext(VX_CONTEXT_OPTICAL_FLOW_MAX_WINDOW_DIMENSION) wrapper vx_size opticalFlowMaxWindowSize() const { vx_size v; query(VX_CONTEXT_OPTICAL_FLOW_MAX_WINDOW_DIMENSION, v); return v; } /// vxQueryContext(VX_CONTEXT_IMMEDIATE_BORDER) wrapper border_t immediateBorder() const { border_t v; query(VX_CONTEXT_IMMEDIATE_BORDER, v); return v; } /// vxQueryContext(VX_CONTEXT_IMPLEMENTATION) wrapper std::string implName() const { std::vector v(VX_MAX_IMPLEMENTATION_NAME); IVX_CHECK_STATUS(vxQueryContext(ref, VX_CONTEXT_IMPLEMENTATION, &v[0], v.size() * sizeof(vx_char))); return std::string(v.data()); } /// vxQueryContext(VX_CONTEXT_EXTENSIONS) wrapper std::string extensionsStr() const { std::vector v(extensionsSize()); IVX_CHECK_STATUS(vxQueryContext(ref, VX_CONTEXT_EXTENSIONS, &v[0], v.size() * sizeof(vx_char))); return std::string(v.data()); } /// vxQueryContext(VX_CONTEXT_UNIQUE_KERNEL_TABLE) wrapper std::vector kernelTable() const { std::vector v(uniqueKernelsNum()); IVX_CHECK_STATUS(vxQueryContext(ref, VX_CONTEXT_UNIQUE_KERNEL_TABLE, &v[0], v.size() * sizeof(vx_kernel_info_t))); return v; } #ifdef VX_VERSION_1_1 /// vxQueryContext(VX_CONTEXT_IMMEDIATE_BORDER_POLICY) wrapper vx_enum immediateBorderPolicy() const { vx_enum v; query(VX_CONTEXT_IMMEDIATE_BORDER_POLICY, v); return v; } /// vxQueryContext(VX_CONTEXT_NONLINEAR_MAX_DIMENSION) wrapper vx_size nonlinearMaxDimension() const { vx_size v; query(VX_CONTEXT_NONLINEAR_MAX_DIMENSION, v); return v; } #endif /// vxSetContextAttribute() wrapper template void setAttribute(vx_enum att, const T& value) { IVX_CHECK_STATUS( vxSetContextAttribute(ref, att, &value, sizeof(value)) ); } /// vxSetContextAttribute(BORDER) wrapper void setImmediateBorder(const border_t& bm) { setAttribute(VX_CONTEXT_IMMEDIATE_BORDER, bm); } #ifndef VX_VERSION_1_1 /// vxSetContextAttribute(BORDER) wrapper void setImmediateBorder(vx_enum mode, vx_uint32 val = 0) { border_t bm = {mode, val}; setImmediateBorder(bm); } #else /// vxSetContextAttribute(BORDER) wrapper void setImmediateBorder(vx_enum mode, const vx_pixel_value_t& val) { border_t bm = {mode, val}; setImmediateBorder(bm); } /// vxSetContextAttribute(BORDER) wrapper template void setImmediateBorder(vx_enum mode, const T& _val) { vx_pixel_value_t val; switch (TypeToEnum::value) { case VX_TYPE_UINT8: val.U8 = _val; break; case VX_TYPE_INT16: val.S16 = _val; break; case VX_TYPE_UINT16: val.U16 = _val; break; case VX_TYPE_INT32: val.S32 = _val; break; case VX_TYPE_UINT32: val.U32 = _val; break; default: throw WrapperError("Unsupported constant border value type"); } setImmediateBorder(mode, val); } /// vxSetContextAttribute(BORDER) wrapper void setImmediateBorder(vx_enum mode) { vx_pixel_value_t val = {}; setImmediateBorder(mode, val); } #endif }; /// vx_graph wrapper class Graph : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Graph); /// vxCreateGraph() wrapper static Graph create(vx_context c) { return Graph(vxCreateGraph(c)); } /// vxVerifyGraph() wrapper void verify() { IVX_CHECK_STATUS( vxVerifyGraph(ref) ); } /// vxProcessGraph() wrapper void process() { IVX_CHECK_STATUS( vxProcessGraph(ref) ); } /// vxScheduleGraph() wrapper void schedule() { IVX_CHECK_STATUS(vxScheduleGraph(ref) ); } /// vxWaitGraph() wrapper void wait() { IVX_CHECK_STATUS(vxWaitGraph(ref)); } }; /// vx_kernel wrapper class Kernel : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Kernel); /// vxGetKernelByEnum() wrapper static Kernel getByEnum(vx_context c, vx_enum kernelID) { return Kernel(vxGetKernelByEnum(c, kernelID)); } /// vxGetKernelByName() wrapper static Kernel getByName(vx_context c, const std::string& name) { return Kernel(vxGetKernelByName(c, name.c_str())); } }; /// vx_node wrapper class Node : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Node); /// vxCreateGenericNode() wrapper static Node create(vx_graph g, vx_kernel k) { return Node(vxCreateGenericNode(g, k)); } /// Create node for the kernel and set the parameters static Node create(vx_graph graph, vx_kernel kernel, const std::vector& params) { Node node = Node::create(graph, kernel); vx_uint32 i = 0; for (std::vector::const_iterator p = params.begin(); p != params.end(); ++p) node.setParameterByIndex(i++, *p); return node; } /// Create node for the kernel ID and set the parameters static Node create(vx_graph graph, vx_enum kernelID, const std::vector& params) { return Node::create(graph, Kernel::getByEnum(Context::getFrom(graph), kernelID), params); } #ifdef IVX_USE_CXX98 /// Create node for the kernel ID and set one parameter template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0) { std::vector params; params.push_back(castToReference(arg0)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set two parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set three parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set four parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set five parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set six parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); params.push_back(castToReference(arg5)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set seven parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); params.push_back(castToReference(arg5)); params.push_back(castToReference(arg6)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set eight parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); params.push_back(castToReference(arg5)); params.push_back(castToReference(arg6)); params.push_back(castToReference(arg7)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set nine parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7, const T8& arg8) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); params.push_back(castToReference(arg5)); params.push_back(castToReference(arg6)); params.push_back(castToReference(arg7)); params.push_back(castToReference(arg8)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } /// Create node for the kernel ID and set ten parameters template static Node create(vx_graph g, vx_enum kernelID, const T0& arg0, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7, const T8& arg8, const T9& arg9) { std::vector params; params.push_back(castToReference(arg0)); params.push_back(castToReference(arg1)); params.push_back(castToReference(arg2)); params.push_back(castToReference(arg3)); params.push_back(castToReference(arg4)); params.push_back(castToReference(arg5)); params.push_back(castToReference(arg6)); params.push_back(castToReference(arg7)); params.push_back(castToReference(arg8)); params.push_back(castToReference(arg9)); return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), params); } #else // not IVX_USE_CXX98 /// Create node for the kernel ID and set the specified parameters template static Node create(vx_graph g, vx_enum kernelID, const Ts&...args) { return create(g, Kernel::getByEnum(Context::getFrom(g), kernelID), { castToReference(args)... }); } #endif // IVX_USE_CXX98 /// vxSetParameterByIndex() wrapper void setParameterByIndex(vx_uint32 index, vx_reference value) { IVX_CHECK_STATUS(vxSetParameterByIndex(ref, index, value)); } /// vxQueryNode() wrapper template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryNode(ref, att, &value, sizeof(value)) ); } #ifndef VX_VERSION_1_1 static const vx_enum VX_NODE_STATUS = VX_NODE_ATTRIBUTE_STATUS, VX_NODE_PERFORMANCE = VX_NODE_ATTRIBUTE_PERFORMANCE, VX_NODE_BORDER = VX_NODE_ATTRIBUTE_BORDER_MODE, VX_NODE_LOCAL_DATA_SIZE = VX_NODE_ATTRIBUTE_LOCAL_DATA_SIZE, VX_NODE_LOCAL_DATA_PTR = VX_NODE_ATTRIBUTE_LOCAL_DATA_PTR, VX_BORDER_UNDEFINED = VX_BORDER_MODE_UNDEFINED; #endif /// vxQueryNode(STATUS) wrapper vx_status status() const { vx_status v; query(VX_NODE_STATUS, v); return v; } /// vxQueryNode(PERFORMANCE) wrapper vx_perf_t performance() const { vx_perf_t v; query(VX_NODE_PERFORMANCE, v); return v; } /// vxQueryNode(BORDER) wrapper border_t border() const { border_t v; v.mode = VX_BORDER_UNDEFINED; query(VX_NODE_BORDER, v); return v; } /// vxQueryNode(LOCAL_DATA_SIZE) wrapper vx_size dataSize() const { vx_size v; query(VX_NODE_LOCAL_DATA_SIZE, v); return v; } /// vxQueryNode(LOCAL_DATA_PTR) wrapper void* dataPtr() const { void* v; query(VX_NODE_LOCAL_DATA_PTR, v); return v; } #ifdef VX_VERSION_1_1 /// vxQueryNode(PARAMETERS) wrapper vx_uint32 paramsNum() const { vx_uint32 v; query(VX_NODE_PARAMETERS, v); return v; } /// vxQueryNode(REPLICATED) wrapper vx_bool isReplicated() const { vx_bool v; query(VX_NODE_IS_REPLICATED, v); return v; } /// vxQueryNode(REPLICATE_FLAGS) wrapper void replicateFlags(std::vector& flags) const { if(flags.empty()) flags.resize(paramsNum(), vx_false_e); IVX_CHECK_STATUS( vxQueryNode(ref, VX_NODE_REPLICATE_FLAGS, &flags[0], flags.size()*sizeof(flags[0])) ); } /// vxQueryNode(VX_NODE_VALID_RECT_RESET) wrapper vx_bool resetValidRect() const { vx_bool v; query(VX_NODE_VALID_RECT_RESET, v); return v; } #endif // VX_VERSION_1_1 /// vxSetNodeAttribute() wrapper template void setAttribute(vx_enum att, const T& value) { IVX_CHECK_STATUS( vxSetNodeAttribute(ref, att, &value, sizeof(value)) ); } /// vxSetNodeAttribute(BORDER) wrapper void setBorder(const border_t& bm) { setAttribute(VX_NODE_BORDER, bm); } #ifndef VX_VERSION_1_1 /// vxSetNodeAttribute(BORDER) wrapper void setBorder(vx_enum mode, vx_uint32 val = 0) { vx_border_mode_t bm = {mode, val}; setBorder(bm); } #else /// vxSetNodeAttribute(BORDER) wrapper void setBorder(vx_enum mode, const vx_pixel_value_t& val) { vx_border_t bm = {mode, val}; setBorder(bm); } /// vxSetNodeAttribute(BORDER) wrapper template void setBorder(vx_enum mode, const T& _val) { vx_pixel_value_t val; switch (TypeToEnum::value) { case VX_TYPE_UINT8: val.U8 = _val; break; case VX_TYPE_INT16: val.S16 = _val; break; case VX_TYPE_UINT16: val.U16 = _val; break; case VX_TYPE_INT32: val.S32 = _val; break; case VX_TYPE_UINT32: val.U32 = _val; break; default: throw WrapperError("Unsupported constant border value type"); } setBorder(mode, val); } /// vxSetNodeAttribute(BORDER) wrapper void setBorder(vx_enum mode) { vx_pixel_value_t val = {}; setBorder(mode, val); } #endif /// vxSetNodeAttribute(LOCAL_DATA_SIZE) wrapper void setDataSize(vx_size size) { setAttribute(VX_NODE_LOCAL_DATA_SIZE, size); } /// vxSetNodeAttribute(LOCAL_DATA_PTR) wrapper void setDataPtr(void* ptr) { setAttribute(VX_NODE_LOCAL_DATA_PTR, ptr); } }; /// vx_image wrapper class Image : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Image); /// vxCreateImage() wrapper static Image create(vx_context context, vx_uint32 width, vx_uint32 height, vx_df_image format) { return Image(vxCreateImage(context, width, height, format)); } /// vxCreateVirtualImage() wrapper static Image createVirtual(vx_graph graph, vx_uint32 width = 0, vx_uint32 height = 0, vx_df_image format = VX_DF_IMAGE_VIRT) { return Image(vxCreateVirtualImage(graph, width, height, format)); } #ifdef VX_VERSION_1_1 /// vxCreateUniformImage() wrapper static Image createUniform(vx_context context, vx_uint32 width, vx_uint32 height, vx_df_image format, const vx_pixel_value_t& value) { return Image(vxCreateUniformImage(context, width, height, format, &value)); } #else /// vxCreateUniformImage() wrapper 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 static vx_size planes(vx_df_image format) { switch (format) { case VX_DF_IMAGE_IYUV: case VX_DF_IMAGE_YUV4: return 3; case VX_DF_IMAGE_NV12: case VX_DF_IMAGE_NV21: return 2; case VX_DF_IMAGE_RGB: case VX_DF_IMAGE_RGBX: case VX_DF_IMAGE_UYVY: case VX_DF_IMAGE_YUYV: 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_F32*/VX_DF_IMAGE('F', '0', '3', '2'): return 1; default: return 0; } } /// Create vx_imagepatch_addressing_t structure with default values static vx_imagepatch_addressing_t createAddressing() { vx_imagepatch_addressing_t ipa = VX_IMAGEPATCH_ADDR_INIT; return ipa; } /// Create vx_imagepatch_addressing_t structure with the provided values static vx_imagepatch_addressing_t createAddressing( vx_uint32 dimX, vx_uint32 dimY, vx_int32 strideX, vx_int32 strideY, vx_uint32 scaleX = VX_SCALE_UNITY, vx_uint32 scaleY = VX_SCALE_UNITY ) { if (std::abs(strideY) < std::abs(strideX*(vx_int32)dimX)) throw WrapperError(std::string(__func__)+"(): invalid arguments"); vx_imagepatch_addressing_t ipa = VX_IMAGEPATCH_ADDR_INIT; ipa.dim_x = dimX; ipa.dim_y = dimY; ipa.stride_x = strideX; ipa.stride_y = strideY; ipa.scale_x = scaleX; ipa.scale_y = scaleY; return ipa; } /// Create vx_imagepatch_addressing_t structure for the specified image plane and its valid region vx_imagepatch_addressing_t createAddressing(vx_uint32 planeIdx) { return createAddressing(planeIdx, getValidRegion()); } /// Create vx_imagepatch_addressing_t structure for the specified image plane and the provided region vx_imagepatch_addressing_t createAddressing(vx_uint32 planeIdx, const vx_rectangle_t& rect) { vx_uint32 w = rect.end_x-rect.start_x, h = rect.end_y-rect.start_y; vx_size patchBytes = computePatchSize(planeIdx, rect); vx_imagepatch_addressing_t ipa = createAddressing(w, h, (vx_int32)(patchBytes/w/h), (vx_int32)(patchBytes/h)); return ipa; } #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST; #endif /// vxCreateImageFromHandle() wrapper static Image createFromHandle( vx_context context, vx_df_image format, const std::vector& addrs, const std::vector& ptrs, vx_enum memType = VX_MEMORY_TYPE_HOST ) { vx_size num = planes(format); if(num == 0) throw WrapperError(std::string(__func__)+"(): unknown/unexpected planes number for the requested format"); if (addrs.size() != num || ptrs.size() != num) throw WrapperError(std::string(__func__)+"(): incomplete input"); #ifdef VX_VERSION_1_1 return Image(vxCreateImageFromHandle(context, format, &addrs[0], &ptrs[0], memType)); #else return Image( vxCreateImageFromHandle(context, format, const_cast(&addrs[0]), const_cast(&ptrs[0]), memType) ); #endif } /// vxCreateImageFromHandle() wrapper for a single plane image static Image createFromHandle(vx_context context, vx_df_image format,const vx_imagepatch_addressing_t& addr, void* ptr) { if(planes(format) != 1) throw WrapperError(std::string(__func__)+"(): not a single plane format"); return Image(vxCreateImageFromHandle(context, format, const_cast (&addr), &ptr, VX_MEMORY_TYPE_HOST)); } #ifdef VX_VERSION_1_1 /// vxSwapImageHandle() wrapper /// \param newPtrs keeps addresses of new image planes data, can be of image planes size or empty when new pointers are not provided /// \param prevPtrs storage for the previous addresses of image planes data, can be of image planes size or empty when previous pointers are not needed void swapHandle(const std::vector& newPtrs, std::vector& prevPtrs) { vx_size num = planes(); if(num == 0) throw WrapperError(std::string(__func__)+"(): unexpected planes number"); if (!newPtrs.empty() && newPtrs.size() != num) throw WrapperError(std::string(__func__)+"(): unexpected number of input pointers"); if (!prevPtrs.empty() && prevPtrs.size() != num) throw WrapperError(std::string(__func__)+"(): unexpected number of output pointers"); IVX_CHECK_STATUS( vxSwapImageHandle( ref, newPtrs.empty() ? 0 : &newPtrs[0], prevPtrs.empty() ? 0 : &prevPtrs[0], num ) ); } /// vxSwapImageHandle() wrapper for a single plane image /// \param newPtr an address of new image data, can be zero when new pointer is not provided /// \return the previuos address of image data void* swapHandle(void* newPtr) { if(planes() != 1) throw WrapperError(std::string(__func__)+"(): not a single plane image"); void* prevPtr = 0; IVX_CHECK_STATUS( vxSwapImageHandle(ref, &newPtr, &prevPtr, 1) ); return prevPtr; } /// vxSwapImageHandle() wrapper for the case when no new pointers provided and previous ones are not needed (retrive memory back) void swapHandle() { IVX_CHECK_STATUS( vxSwapImageHandle(ref, 0, 0, 0) ); } /// vxCreateImageFromChannel() wrapper Image createFromChannel(vx_enum channel) { return Image(vxCreateImageFromChannel(ref, channel)); } #endif // VX_VERSION_1_1 /// vxQueryImage() wrapper template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryImage(ref, att, &value, sizeof(value)) ); } #ifndef VX_VERSION_1_1 static const vx_enum VX_IMAGE_WIDTH = VX_IMAGE_ATTRIBUTE_WIDTH, VX_IMAGE_HEIGHT = VX_IMAGE_ATTRIBUTE_HEIGHT, VX_IMAGE_FORMAT = VX_IMAGE_ATTRIBUTE_FORMAT, VX_IMAGE_PLANES = VX_IMAGE_ATTRIBUTE_PLANES, VX_IMAGE_SPACE = VX_IMAGE_ATTRIBUTE_SPACE, VX_IMAGE_RANGE = VX_IMAGE_ATTRIBUTE_RANGE, VX_IMAGE_SIZE = VX_IMAGE_ATTRIBUTE_SIZE; #endif /// vxQueryImage(VX_IMAGE_WIDTH) wrapper vx_uint32 width() const { vx_uint32 v; query(VX_IMAGE_WIDTH, v); return v; } /// vxQueryImage(VX_IMAGE_HEIGHT) wrapper vx_uint32 height() const { vx_uint32 v; query(VX_IMAGE_HEIGHT, v); return v; } /// vxQueryImage(VX_IMAGE_FORMAT) wrapper vx_df_image format() const { vx_df_image v; query(VX_IMAGE_FORMAT, v); return v; } /// vxQueryImage(VX_IMAGE_PLANES) wrapper vx_size planes() const { vx_size v; query(VX_IMAGE_PLANES, v); return v; } /// vxQueryImage(VX_IMAGE_SPACE) wrapper vx_enum space() const { vx_enum v; query(VX_IMAGE_SPACE, v); return v; } /// vxQueryImage(VX_IMAGE_RANGE) wrapper vx_enum range() const { vx_enum v; query(VX_IMAGE_RANGE, v); return v; } /// vxQueryImage(VX_IMAGE_SIZE) wrapper vx_size size() const { vx_size v; query(VX_IMAGE_SIZE, v); return v; } #ifdef VX_VERSION_1_1 /// vxQueryImage(VX_IMAGE_MEMORY_TYPE) wrapper vx_memory_type_e memType() const { vx_memory_type_e v; query(VX_IMAGE_MEMORY_TYPE, v); return v; } #endif // VX_VERSION_1_1 /// vxSetImageAttribute() wrapper template void setAttribute(vx_enum att, T& value) const { IVX_CHECK_STATUS(vxSetImageAttribute(ref, att, &value, sizeof(value))); } /// vxSetImageAttribute(SPACE) wrapper void setColorSpace(const vx_enum& sp) { setAttribute(VX_IMAGE_SPACE, sp); } /// vxGetValidRegionImage() wrapper vx_rectangle_t getValidRegion() const { vx_rectangle_t rect; IVX_CHECK_STATUS( vxGetValidRegionImage(ref, &rect) ); return rect; } /// vxComputeImagePatchSize(valid region) wrapper vx_size computePatchSize(vx_uint32 planeIdx) { return computePatchSize(planeIdx, getValidRegion()); } /// vxComputeImagePatchSize() wrapper vx_size computePatchSize(vx_uint32 planeIdx, const vx_rectangle_t& rect) { vx_size bytes = vxComputeImagePatchSize(ref, &rect, planeIdx); if (bytes == 0) throw WrapperError(std::string(__func__)+"(): vxComputeImagePatchSize returned 0"); return bytes; } #ifdef VX_VERSION_1_1 /// vxSetImageValidRectangle() wrapper void setValidRectangle(const vx_rectangle_t& rect) { IVX_CHECK_STATUS( vxSetImageValidRectangle(ref, &rect) ); } #endif // VX_VERSION_1_1 /// Copy image plane content to the provided memory void copyTo(vx_uint32 planeIdx, const vx_imagepatch_addressing_t& addr, void* data) { if(!data) throw WrapperError(std::string(__func__)+"(): output pointer is 0"); vx_rectangle_t r = getValidRegion(); // TODO: add sizes consistency checks /* vx_uint32 w = r.end_x - r.start_x, h = r.end_y - r.start_y; if (w != addr.dim_x) throw WrapperError("Image::copyTo(): inconsistent dimension X"); if (h != addr.dim_y) throw WrapperError("Image::copyTo(): inconsistent dimension Y"); */ #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyImagePatch(ref, &r, planeIdx, &addr, data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else vx_imagepatch_addressing_t* a = const_cast(&addr); IVX_CHECK_STATUS(vxAccessImagePatch(ref, &r, planeIdx, a, &data, VX_READ_ONLY)); IVX_CHECK_STATUS(vxCommitImagePatch(ref, 0, planeIdx, a, data)); #endif } /// Copy the provided memory data to the specified image plane void copyFrom(vx_uint32 planeIdx, const vx_imagepatch_addressing_t& addr, const void* data) { if (!data) throw WrapperError(std::string(__func__)+"(): input pointer is 0"); vx_rectangle_t r = getValidRegion(); // TODO: add sizes consistency checks /* vx_uint32 w = r.end_x - r.start_x, h = r.end_y - r.start_y; //vx_size patchBytes = vxComputeImagePatchSize(ref, &r, planeIdx); if (w != addr.dim_x) throw WrapperError("Image::copyFrom(): inconsistent dimension X"); if (h != addr.dim_y) throw WrapperError("Image::copyFrom(): inconsistent dimension Y"); */ #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyImagePatch(ref, &r, planeIdx, &addr, (void*)data, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else vx_imagepatch_addressing_t* a = const_cast(&addr); IVX_CHECK_STATUS(vxAccessImagePatch(ref, &r, planeIdx, a, const_cast(&data), VX_WRITE_ONLY)); IVX_CHECK_STATUS(vxCommitImagePatch(ref, &r, planeIdx, a, data)); #endif } /// vxCopyImagePatch() wrapper (or vxAccessImagePatch() + vxCommitImagePatch() for OpenVX 1.0) void copy( vx_uint32 planeIdx, vx_rectangle_t rect, const vx_imagepatch_addressing_t& addr, void* data, vx_enum usage, vx_enum memoryType = VX_MEMORY_TYPE_HOST ) { #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyImagePatch(ref, &rect, planeIdx, &addr, (void*)data, usage, memoryType)); #else (void)memoryType; vx_imagepatch_addressing_t* a = const_cast(&addr); IVX_CHECK_STATUS(vxAccessImagePatch(ref, &rect, planeIdx, a, &data, usage)); IVX_CHECK_STATUS(vxCommitImagePatch(ref, &rect, planeIdx, a, data)); #endif } #ifdef IVX_USE_OPENCV /// Convert image format (fourcc) to cv::Mat type, throws WrapperError if not possible static int formatToMatType(vx_df_image format, vx_uint32 planeIdx = 0) { switch (format) { case VX_DF_IMAGE_RGB: return CV_8UC3; case VX_DF_IMAGE_RGBX: return CV_8UC4; case VX_DF_IMAGE_U8: return CV_8UC1; case VX_DF_IMAGE_U16: return CV_16UC1; case VX_DF_IMAGE_S16: return CV_16SC1; case VX_DF_IMAGE_U32: case VX_DF_IMAGE_S32: return CV_32SC1; case VX_DF_IMAGE('F', '0', '3', '2'): return CV_32FC1; case VX_DF_IMAGE_YUV4: case VX_DF_IMAGE_IYUV: return CV_8UC1; case VX_DF_IMAGE_UYVY: case VX_DF_IMAGE_YUYV: return CV_8UC2; case VX_DF_IMAGE_NV12: case VX_DF_IMAGE_NV21: return planeIdx == 0 ? CV_8UC1 : CV_8UC2; default: throw WrapperError(std::string(__func__)+"(): unsupported image format"); } } /// Convert cv::Mat type to standard image format (fourcc), throws WrapperError if not possible static vx_df_image matTypeToFormat(int matType) { switch (matType) { case CV_8UC4: return VX_DF_IMAGE_RGBX; case CV_8UC3: return VX_DF_IMAGE_RGB; case CV_8UC1: return VX_DF_IMAGE_U8; case CV_16UC1: return VX_DF_IMAGE_U16; case CV_16SC1: return VX_DF_IMAGE_S16; case CV_32SC1: return VX_DF_IMAGE_S32; case CV_32FC1: return VX_DF_IMAGE('F', '0', '3', '2'); default: throw WrapperError(std::string(__func__)+"(): unsupported cv::Mat type"); } } /// Initialize cv::Mat shape to fit the specified image plane data void createMatForPlane(cv::Mat& m, vx_uint32 planeIdx) { vx_df_image f = format(); //vx_uint32 w = width(), h = height(); vx_rectangle_t r = getValidRegion(); vx_int32 w = vx_int32(r.end_x - r.start_x), h = vx_int32(r.end_y - r.start_y); switch (f) { case VX_DF_IMAGE_IYUV: if (planeIdx == 0u) m.create(h, w, formatToMatType(f)); else if (planeIdx == 1u || planeIdx == 2u) m.create(h/2, w/2, formatToMatType(f)); else throw WrapperError(std::string(__func__)+"(): wrong plane index"); break; case VX_DF_IMAGE_YUV4: if (planeIdx == 0u || planeIdx == 1u || planeIdx == 2u) m.create(h, w, formatToMatType(f)); else throw WrapperError(std::string(__func__)+"(): wrong plane index"); break; case VX_DF_IMAGE_NV12: case VX_DF_IMAGE_NV21: if (planeIdx == 0u) m.create(h, w, formatToMatType(f, 0)); else if (planeIdx == 1u) m.create(h/2, w/2, formatToMatType(f, 1)); else throw WrapperError(std::string(__func__)+"(): wrong plane index"); break; case VX_DF_IMAGE_RGB: case VX_DF_IMAGE_RGBX: case VX_DF_IMAGE_UYVY: case VX_DF_IMAGE_YUYV: 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_F32*/VX_DF_IMAGE('F', '0', '3', '2'): if(planeIdx == 0u) m.create(h, w, formatToMatType(f)); else throw WrapperError(std::string(__func__)+"(): wrong plane index"); break; default: throw WrapperError(std::string(__func__)+"(): unsupported color format"); } } /// Create vx_imagepatch_addressing_t corresponding to the provided cv::Mat static vx_imagepatch_addressing_t createAddressing(const cv::Mat& m) { if(m.empty()) throw WrapperError(std::string(__func__)+"(): empty input Mat"); return createAddressing((vx_uint32)m.cols, (vx_uint32)m.rows, (vx_int32)m.elemSize(), (vx_int32)m.step); } /// Copy image plane content to the provided cv::Mat (reallocate if needed) void copyTo(vx_uint32 planeIdx, cv::Mat& m) { createMatForPlane(m, planeIdx); copyTo(planeIdx, createAddressing((vx_uint32)m.cols, (vx_uint32)m.rows, (vx_int32)m.elemSize(), (vx_int32)m.step), m.ptr()); } /// Copy the provided cv::Mat data to the specified image plane void copyFrom(vx_uint32 planeIdx, const cv::Mat& m) { if(m.empty()) throw WrapperError(std::string(__func__)+"(): empty input Mat"); // TODO: add sizes consistency checks //vx_rectangle_t r = getValidRegion(); copyFrom(planeIdx, createAddressing((vx_uint32)m.cols, (vx_uint32)m.rows, (vx_int32)m.elemSize(), (vx_int32)m.step), m.ptr()); } /* private: cv::Mat _mat; // TODO: update copy/move-c-tors, operator=() and swapHandles() public: static Image createFromHandle(vx_context context, const cv::Mat& mat) { if(mat.empty()) throw WrapperError(std::string(__func__)+"(): empty cv::Mat"); Image res = createFromHandle(context, matTypeToFormat(mat.type()), createAddressing(mat), mat.data ); res._mat = mat; return res; } */ #endif //IVX_USE_OPENCV struct Patch; }; /// Helper class for a mapping vx_image patch struct Image::Patch { public: /// reference to the current vx_imagepatch_addressing_t const vx_imagepatch_addressing_t& addr() const { return _addr;} /// current pixels data pointer void* data() const { return _data; } #ifdef VX_VERSION_1_1 /// vx_memory_type_e for the current data pointer vx_memory_type_e memType() const { return _memType; } /// vx_map_id for the current mapping vx_map_id mapId() const { return _mapId; } #else /// reference to vx_rectangle_t for the current mapping const vx_rectangle_t& rectangle() const { return _rect; } /// Image plane index for the current mapping vx_uint32 planeIndex() const { return _planeIdx; } #endif // VX_VERSION_1_1 /// vx_image for the current mapping vx_image image() const { return _img; } /// where this patch is mapped bool isMapped() const { return _img != 0; } #ifdef IVX_USE_OPENCV /// Reference to cv::Mat instance wrapping the mapped image data, becomes invalid after unmap() cv::Mat& getMat() { return _m; } #endif //IVX_USE_OPENCV protected: vx_imagepatch_addressing_t _addr; void* _data; vx_image _img; #ifdef VX_VERSION_1_1 vx_memory_type_e _memType; vx_map_id _mapId; #else vx_rectangle_t _rect; vx_uint32 _planeIdx; #endif #ifdef IVX_USE_OPENCV cv::Mat _m; #endif public: /// Default constructor Patch() : _addr(createAddressing()), _data(0), _img(0) #ifdef VX_VERSION_1_1 , _memType(VX_MEMORY_TYPE_HOST), _mapId(0) {} #else , _planeIdx(-1) { _rect.start_x = _rect.end_x = _rect.start_y = _rect.end_y = 0u; } #endif #ifndef IVX_USE_CXX98 /// Move constructor Patch(Patch&& p) : Patch() { using std::swap; swap(_addr, p._addr); swap(_data, p._data); #ifdef VX_VERSION_1_1 swap(_memType, p._memType); swap(_mapId, p._mapId); #else swap(_rect, p._rect); swap(_planeIdx, p._planeIdx); #endif swap(_img, p._img); #ifdef IVX_USE_OPENCV swap(_m, p._m); #endif } #endif /// vxMapImagePatch(VX_READ_ONLY, planeIdx valid region) void map(vx_image img, vx_uint32 planeIdx) { map(img, planeIdx, Image(img, true).getValidRegion()); } /// vxMapImagePatch() wrapper (or vxAccessImagePatch() for 1.0) void map(vx_image img, vx_uint32 planeIdx, const vx_rectangle_t& rect, vx_enum usage = VX_READ_ONLY, vx_uint32 flags = 0) { if (isMapped()) throw WrapperError(std::string(__func__)+"(): already mapped"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxMapImagePatch(img, &rect, planeIdx, &_mapId, &_addr, &_data, usage, _memType, flags) ); #else IVX_CHECK_STATUS(vxAccessImagePatch(img, &rect, planeIdx, &_addr, &_data, usage)); (void)flags; _rect = rect; _planeIdx = planeIdx; #endif if (_data == 0) throw WrapperError(std::string(__func__)+"(): mapped address is null"); _img = img; #ifdef IVX_USE_OPENCV vx_df_image format; IVX_CHECK_STATUS( vxQueryImage(_img, VX_IMAGE_FORMAT, &format, sizeof(format)) ); int matType = formatToMatType(format); _m = cv::Mat( vx_int32((vx_int64)_addr.dim_y * VX_SCALE_UNITY / _addr.scale_y), vx_int32((vx_int64)_addr.dim_x * VX_SCALE_UNITY / _addr.scale_x), matType, _data, std::size_t(_addr.stride_y) ); #endif } /// vxUnmapImagePatch() wrapper (or vxCommitImagePatch() for 1.0) void unmap() { #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxUnmapImagePatch(_img, _mapId)); _mapId = 0; #else IVX_CHECK_STATUS(vxCommitImagePatch(_img, &_rect, _planeIdx, &_addr, _data)); _rect.start_x = _rect.end_x = _rect.start_y = _rect.end_y = 0u; _planeIdx = -1; #endif _img = 0; _data = 0; _addr = createAddressing(); #ifdef IVX_USE_OPENCV _m.release(); #endif } /// Destructor ~Patch() { try { if (_img) unmap(); } catch(...) {; /*ignore*/} } /// Pointer to the specified pixel data (vxFormatImagePatchAddress2d) void* pixelPtr(vx_uint32 x, vx_uint32 y) { if (!_data) throw WrapperError(std::string(__func__)+"(): base pointer is NULL"); if (x >= _addr.dim_x) throw WrapperError(std::string(__func__)+"(): X out of range"); if (y >= _addr.dim_y) throw WrapperError(std::string(__func__)+"(): Y out of range"); return vxFormatImagePatchAddress2d(_data, x, y, &_addr); } private: Patch(const Patch& p); // = delete Patch& operator=(const Patch&); // = delete #ifndef IVX_USE_CXX98 Patch& operator=(Patch&&); // = delete #endif }; /// vx_parameter wrapper class Param : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Param); // NYI }; /// vx_scalar wrapper class Scalar : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Scalar); /// vxCreateScalar() wrapper static Scalar create(vx_context c, vx_enum dataType, const void *ptr) { return Scalar( vxCreateScalar(c, dataType, ptr) ); } /// vxCreateScalar() wrapper, value is passed as a value not as a pointer template static Scalar create(vx_context c, vx_enum dataType, T value) { typedef int static_assert_not_pointer[is_pointer::value ? -1 : 1]; return Scalar( vxCreateScalar(c, dataType, &value) ); } /// vxCreateScalar() wrapper, data type is guessed based on the passed value template static Scalar create(vx_context c, typename EnumToType::type value) { return Scalar( vxCreateScalar(c, E, &value) ); } #ifndef VX_VERSION_1_1 static const vx_enum VX_SCALAR_TYPE = VX_SCALAR_ATTRIBUTE_TYPE; #endif /// Get scalar data type vx_enum type() { vx_enum val; IVX_CHECK_STATUS( vxQueryScalar(ref, VX_SCALAR_TYPE, &val, sizeof(val)) ); return val; } /// Get scalar value template void getValue(T& val) { if (!areTypesCompatible(TypeToEnum::value, type())) throw WrapperError(std::string(__func__)+"(): incompatible types"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS( vxCopyScalar(ref, &val, VX_READ_ONLY, VX_MEMORY_TYPE_HOST) ); #else IVX_CHECK_STATUS( vxReadScalarValue(ref, &val) ); #endif } /// Get scalar value template T getValue() { T val; getValue(val); return val; } /// Set scalar value template void setValue(T val) { if (!areTypesCompatible(TypeToEnum::value, type())) throw WrapperError(std::string(__func__)+"(): incompatible types"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyScalar(ref, &val, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS( vxWriteScalarValue(ref, &val) ); #endif } }; /// vx_threshold wrapper class Threshold : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Threshold); /// vxCreateThreshold() wrapper static Threshold create(vx_context c, vx_enum threshType, vx_enum dataType) { return Threshold(vxCreateThreshold(c, threshType, dataType)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_THRESHOLD_TYPE = VX_THRESHOLD_ATTRIBUTE_TYPE, VX_THRESHOLD_THRESHOLD_VALUE = VX_THRESHOLD_ATTRIBUTE_THRESHOLD_VALUE, VX_THRESHOLD_THRESHOLD_LOWER = VX_THRESHOLD_ATTRIBUTE_THRESHOLD_LOWER, VX_THRESHOLD_THRESHOLD_UPPER = VX_THRESHOLD_ATTRIBUTE_THRESHOLD_UPPER, VX_THRESHOLD_TRUE_VALUE = VX_THRESHOLD_ATTRIBUTE_TRUE_VALUE, VX_THRESHOLD_FALSE_VALUE = VX_THRESHOLD_ATTRIBUTE_FALSE_VALUE, VX_THRESHOLD_DATA_TYPE = VX_THRESHOLD_ATTRIBUTE_DATA_TYPE; #endif /// Create binary threshold with the provided value static Threshold createBinary(vx_context c, vx_enum dataType, vx_int32 val) { Threshold thr = create(c, VX_THRESHOLD_TYPE_BINARY, dataType); IVX_CHECK_STATUS( vxSetThresholdAttribute(thr.ref, VX_THRESHOLD_THRESHOLD_VALUE, &val, sizeof(val)) ); return thr; } /// Create range threshold with the provided low and high values static Threshold createRange(vx_context c, vx_enum dataType, vx_int32 valLower, vx_int32 valUpper) { Threshold thr = create(c, VX_THRESHOLD_TYPE_RANGE, dataType); IVX_CHECK_STATUS( vxSetThresholdAttribute(thr.ref, VX_THRESHOLD_THRESHOLD_LOWER, &valLower, sizeof(valLower)) ); IVX_CHECK_STATUS( vxSetThresholdAttribute(thr.ref, VX_THRESHOLD_THRESHOLD_UPPER, &valUpper, sizeof(valUpper)) ); return thr; } /// vxQueryThreshold() wrapper template void query(vx_enum att, T& val) const { IVX_CHECK_STATUS( vxQueryThreshold(ref, att, &val, sizeof(val)) ); } /// vxQueryThreshold(VX_THRESHOLD_TYPE) wrapper vx_enum type() const { vx_enum v; query(VX_THRESHOLD_TYPE, v); return v; } /// vxQueryThreshold(DATA_TYPE) wrapper vx_enum dataType() const { vx_enum v; query(VX_THRESHOLD_DATA_TYPE, v); return v; } /// vxQueryThreshold(THRESHOLD_VALUE) wrapper vx_int32 value() const { vx_int32 v; query(VX_THRESHOLD_THRESHOLD_VALUE, v); return v; } /// vxQueryThreshold(THRESHOLD_LOWER) wrapper vx_int32 valueLower() const { vx_int32 v; query(VX_THRESHOLD_THRESHOLD_LOWER, v); return v; } /// vxQueryThreshold(THRESHOLD_UPPER) wrapper vx_int32 valueUpper() const { vx_int32 v; query(VX_THRESHOLD_THRESHOLD_UPPER, v); return v; } /// vxQueryThreshold(TRUE_VALUE) wrapper vx_int32 valueTrue() const { vx_int32 v; query(VX_THRESHOLD_TRUE_VALUE, v); return v; } /// vxQueryThreshold(FALSE_VALUE) wrapper vx_int32 valueFalse() const { vx_int32 v; query(VX_THRESHOLD_FALSE_VALUE, v); return v; } /// vxSetThresholdAttribute(THRESHOLD_VALUE) wrapper void setValue(vx_int32 &val) { IVX_CHECK_STATUS(vxSetThresholdAttribute(ref, VX_THRESHOLD_THRESHOLD_VALUE, &val, sizeof(val))); } /// vxSetThresholdAttribute(THRESHOLD_LOWER) wrapper void setValueLower(vx_int32 &val) { IVX_CHECK_STATUS(vxSetThresholdAttribute(ref, VX_THRESHOLD_THRESHOLD_LOWER, &val, sizeof(val))); } /// vxSetThresholdAttribute(THRESHOLD_UPPER) wrapper void setValueUpper(vx_int32 &val) { IVX_CHECK_STATUS(vxSetThresholdAttribute(ref, VX_THRESHOLD_THRESHOLD_UPPER, &val, sizeof(val))); } /// vxSetThresholdAttribute(TRUE_VALUE) wrapper void setValueTrue(vx_int32 &val) { IVX_CHECK_STATUS(vxSetThresholdAttribute(ref, VX_THRESHOLD_TRUE_VALUE, &val, sizeof(val))); } /// vxSetThresholdAttribute(FALSE_VALUE) wrapper void setValueFalse(vx_int32 &val) { IVX_CHECK_STATUS(vxSetThresholdAttribute(ref, VX_THRESHOLD_FALSE_VALUE, &val, sizeof(val))); } }; /// vx_array wrapper class Array : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Array); /// vxCreateArray() wrapper static Array create(vx_context c, vx_enum type, vx_size capacity) { return Array(vxCreateArray(c, type, capacity)); } /// vxCreateVirtualArray() wrapper static Array createVirtual(vx_graph g, vx_enum type, vx_size capacity) { return Array(vxCreateVirtualArray(g, type, capacity)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST, VX_ARRAY_ITEMTYPE = VX_ARRAY_ATTRIBUTE_ITEMTYPE, VX_ARRAY_NUMITEMS = VX_ARRAY_ATTRIBUTE_NUMITEMS, VX_ARRAY_CAPACITY = VX_ARRAY_ATTRIBUTE_CAPACITY, VX_ARRAY_ITEMSIZE = VX_ARRAY_ATTRIBUTE_ITEMSIZE; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryArray(ref, att, &value, sizeof(value)) ); } vx_enum itemType() const { vx_enum v; query(VX_ARRAY_ITEMTYPE, v); return v; } vx_size itemSize() const { vx_size v; query(VX_ARRAY_ITEMSIZE, v); return v; } vx_size capacity() const { vx_size v; query(VX_ARRAY_CAPACITY, v); return v; } vx_size itemCount() const { vx_size v; query(VX_ARRAY_NUMITEMS, v); return v; } void addItems(vx_size count, const void* ptr, vx_size stride) { IVX_CHECK_STATUS(vxAddArrayItems(ref, count, ptr, stride)); } void truncateArray(vx_size new_count) { if(new_count <= itemCount()) IVX_CHECK_STATUS(vxTruncateArray(ref, new_count)); else throw WrapperError(std::string(__func__) + "(): array is too small"); } void copyRangeTo(size_t start, size_t end, void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): output pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyArrayRange(ref, start, end, itemSize(), data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else vx_size stride = itemSize(); IVX_CHECK_STATUS(vxAccessArrayRange(ref, start, end, &stride, &data, VX_READ_ONLY)); IVX_CHECK_STATUS(vxCommitArrayRange(ref, start, end, data)); #endif } void copyTo(void* data) { copyRangeTo(0, itemCount(), data); } void copyRangeFrom(size_t start, size_t end, const void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): input pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyArrayRange(ref, start, end, itemSize(), const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else vx_size stride = itemSize(); IVX_CHECK_STATUS(vxAccessArrayRange(ref, start, end, &stride, const_cast(&data), VX_WRITE_ONLY)); IVX_CHECK_STATUS(vxCommitArrayRange(ref, start, end, data)); #endif } void copyFrom(const void* data) { copyRangeFrom(0, itemCount(), data); } void copyRange(size_t start, size_t end, void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { if (!data) throw WrapperError(std::string(__func__) + "(): data pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyArrayRange(ref, start, end, itemSize(), data, usage, memType)); #else vx_size stride = itemSize(); IVX_CHECK_STATUS(vxAccessArrayRange(ref, start, end, &stride, &data, usage)); IVX_CHECK_STATUS(vxCommitArrayRange(ref, start, end, data)); (void)memType; #endif } void copy(void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { copyRange(0, itemCount(), data, usage, memType); } template void addItem(const T& item) { if (!areTypesCompatible(TypeToEnum::value, itemType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); addItems(1, &item, sizeof(T)); } template void addItems(const std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, itemType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); addItems(data.size(), &data[0], itemSize()); } template void copyRangeTo(size_t start, size_t end, std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, itemType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (data.empty()) data.resize((end - start)); else if (data.size() != (end - start)) { throw WrapperError(std::string(__func__) + "(): destination size is wrong"); } copyRangeTo(start, end, &data[0]); } template void copyTo(std::vector& data) { copyRangeTo(0, itemCount(), data); } template void copyRangeFrom(size_t start, size_t end, const std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, itemType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); if (data.size() != (end - start)) throw WrapperError(std::string(__func__) + "(): source size is wrong"); copyRangeFrom(start, end, &data[0]); } template void copyFrom(std::vector& data) { copyRangeFrom(0, itemCount(), data); } #ifdef IVX_USE_OPENCV void addItems(cv::InputArray ia) { cv::Mat m = ia.getMat(); if (m.type() != enumToCVType(itemType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); addItems(m.total(), m.isContinuous() ? m.ptr() : m.clone().ptr(), (vx_size)(m.elemSize())); } void copyRangeTo(size_t start, size_t end, cv::Mat& m) { if (m.type() != enumToCVType(itemType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (!( ((vx_size)(m.rows) == (end - start) && m.cols == 1) || ((vx_size)(m.cols) == (end - start) && m.rows == 1) ) && !m.empty()) throw WrapperError(std::string(__func__) + "(): destination size is wrong"); if (m.isContinuous() && (vx_size)(m.total()) == (end - start)) { copyRangeTo(start, end, m.ptr()); } else { cv::Mat tmp(1, (int)(end - start), enumToCVType(itemType())); copyRangeTo(start, end, tmp.ptr()); if (m.empty()) m = tmp; else tmp.copyTo(m); } } void copyTo(cv::Mat& m) { copyRangeTo(0, itemCount(), m); } void copyRangeFrom(size_t start, size_t end, const cv::Mat& m) { if (!( ((vx_size)(m.rows) == (end - start) && m.cols == 1) || ((vx_size)(m.cols) == (end - start) && m.rows == 1) )) throw WrapperError(std::string(__func__) + "(): source size is wrong"); if (m.type() != enumToCVType(itemType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); copyFrom(m.isContinuous() ? m.ptr() : m.clone().ptr()); } void copyFrom(const cv::Mat& m) { copyRangeFrom(0, itemCount(), m); } #endif //IVX_USE_OPENCV }; /* * Convolution */ class Convolution : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Convolution); static Convolution create(vx_context context, vx_size columns, vx_size rows) { return Convolution(vxCreateConvolution(context, columns, rows)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST, VX_CONVOLUTION_ROWS = VX_CONVOLUTION_ATTRIBUTE_ROWS, VX_CONVOLUTION_COLUMNS = VX_CONVOLUTION_ATTRIBUTE_COLUMNS, VX_CONVOLUTION_SCALE = VX_CONVOLUTION_ATTRIBUTE_SCALE, VX_CONVOLUTION_SIZE = VX_CONVOLUTION_ATTRIBUTE_SIZE; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryConvolution(ref, att, &value, sizeof(value)) ); } vx_size columns() const { vx_size v; query(VX_CONVOLUTION_COLUMNS, v); return v; } vx_size rows() const { vx_size v; query(VX_CONVOLUTION_ROWS, v); return v; } vx_uint32 scale() const { vx_uint32 v; query(VX_CONVOLUTION_SCALE, v); return v; } vx_size size() const { vx_size v; query(VX_CONVOLUTION_SIZE, v); return v; } vx_enum dataType() { return VX_TYPE_INT16; } void setScale(vx_uint32 newScale) { IVX_CHECK_STATUS( vxSetConvolutionAttribute(ref, VX_CONVOLUTION_SCALE, &newScale, sizeof(newScale)) ); } void copyTo(void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): output pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyConvolutionCoefficients(ref, data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxReadConvolutionCoefficients(ref, (vx_int16 *)data)); #endif } void copyFrom(const void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): input pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyConvolutionCoefficients(ref, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxWriteConvolutionCoefficients(ref, (const vx_int16 *)data)); #endif } void copy(void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { if (!data) throw WrapperError(std::string(__func__) + "(): data pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyConvolutionCoefficients(ref, data, usage, memType)); #else if (usage == VX_READ_ONLY) IVX_CHECK_STATUS(vxReadConvolutionCoefficients(ref, (vx_int16 *)data)); else if (usage == VX_WRITE_ONLY) IVX_CHECK_STATUS(vxWriteConvolutionCoefficients(ref, (const vx_int16 *)data)); else throw WrapperError(std::string(__func__) + "(): unknown copy direction"); (void)memType; #endif } template void copyTo(std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (data.size()*sizeof(T) != size()) { if (data.size() == 0) data.resize(size()/sizeof(T)); else throw WrapperError(std::string(__func__) + "(): destination size is wrong"); } copyTo(&data[0]); } template void copyFrom(const std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); if (data.size()*sizeof(T) != size()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); copyFrom(&data[0]); } #ifdef IVX_USE_OPENCV void copyTo(cv::Mat& m) { if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (((vx_size)(m.rows) != rows() || (vx_size)(m.cols) != columns()) && !m.empty()) throw WrapperError(std::string(__func__) + "(): destination size is wrong"); if (m.isContinuous() && (vx_size)(m.rows) == rows() && (vx_size)(m.cols) == columns()) { copyTo(m.ptr()); } else { cv::Mat tmp((int)rows(), (int)columns(), enumToCVType(dataType())); copyTo(tmp.ptr()); if (m.empty()) m = tmp; else tmp.copyTo(m); } } void copyFrom(const cv::Mat& m) { if ((vx_size)(m.rows) != rows() || (vx_size)(m.cols) != columns()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); copyFrom(m.isContinuous() ? m.ptr() : m.clone().ptr()); } #endif //IVX_USE_OPENCV }; /* * Matrix */ class Matrix : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Matrix); static Matrix create(vx_context context, vx_enum dataType, vx_size columns, vx_size rows) { return Matrix(vxCreateMatrix(context, dataType, columns, rows)); } #ifdef VX_VERSION_1_1 static Matrix createFromPattern(vx_context context, vx_enum pattern, vx_size columns, vx_size rows) { return Matrix(vxCreateMatrixFromPattern(context, pattern, columns, rows)); } #endif #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST, VX_MATRIX_TYPE = VX_MATRIX_ATTRIBUTE_TYPE, VX_MATRIX_ROWS = VX_MATRIX_ATTRIBUTE_ROWS, VX_MATRIX_COLUMNS = VX_MATRIX_ATTRIBUTE_COLUMNS, VX_MATRIX_SIZE = VX_MATRIX_ATTRIBUTE_SIZE; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryMatrix(ref, att, &value, sizeof(value)) ); } vx_enum dataType() const { vx_enum v; query(VX_MATRIX_TYPE, v); return v; } vx_size columns() const { vx_size v; query(VX_MATRIX_COLUMNS, v); return v; } vx_size rows() const { vx_size v; query(VX_MATRIX_ROWS, v); return v; } vx_size size() const { vx_size v; query(VX_MATRIX_SIZE, v); return v; } #ifdef VX_VERSION_1_1 vx_coordinates2d_t origin() const { vx_coordinates2d_t v; query(VX_MATRIX_ORIGIN, v); return v; } vx_enum pattern() const { vx_enum v; query(VX_MATRIX_PATTERN, v); return v; } #endif // VX_VERSION_1_1 void copyTo(void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): output pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyMatrix(ref, data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxReadMatrix(ref, data)); #endif } void copyFrom(const void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): input pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyMatrix(ref, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxWriteMatrix(ref, data)); #endif } void copy(void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { if (!data) throw WrapperError(std::string(__func__) + "(): data pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyMatrix(ref, data, usage, memType)); #else if (usage == VX_READ_ONLY) IVX_CHECK_STATUS(vxReadMatrix(ref, data)); else if (usage == VX_WRITE_ONLY) IVX_CHECK_STATUS(vxWriteMatrix(ref, data)); else throw WrapperError(std::string(__func__) + "(): unknown copy direction"); (void)memType; #endif } template void copyTo(std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (data.size()*sizeof(T) != size()) { if (data.size() == 0) data.resize(size()/sizeof(T)); else throw WrapperError(std::string(__func__) + "(): destination size is wrong"); } copyTo(&data[0]); } template void copyFrom(const std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); if (data.size()*sizeof(T) != size()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); copyFrom(&data[0]); } #ifdef IVX_USE_OPENCV void copyTo(cv::Mat& m) { if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (((vx_size)(m.rows) != rows() || (vx_size)(m.cols) != columns()) && !m.empty()) throw WrapperError(std::string(__func__) + "(): destination size is wrong"); if (m.isContinuous() && (vx_size)(m.rows) == rows() && (vx_size)(m.cols) == columns()) { copyTo(m.ptr()); } else { cv::Mat tmp((int)rows(), (int)columns(), enumToCVType(dataType())); copyTo(tmp.ptr()); if (m.empty()) m = tmp; else tmp.copyTo(m); } } void copyFrom(const cv::Mat& m) { if ((vx_size)(m.rows) != rows() || (vx_size)(m.cols) != columns()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); copyFrom(m.isContinuous() ? m.ptr() : m.clone().ptr()); } #endif //IVX_USE_OPENCV }; /* * LUT */ class LUT : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(LUT); #ifdef VX_VERSION_1_1 static LUT create(vx_context context, vx_enum dataType = VX_TYPE_UINT8, vx_size count = 256) { #else static LUT create(vx_context context) { vx_enum dataType = VX_TYPE_UINT8; vx_size count = 256; #endif return LUT(vxCreateLUT(context, dataType, count)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS(vxQueryLUT(ref, att, &value, sizeof(value))); } #ifndef VX_VERSION_1_1 static const vx_enum VX_LUT_TYPE = VX_LUT_ATTRIBUTE_TYPE, VX_LUT_COUNT = VX_LUT_ATTRIBUTE_COUNT, VX_LUT_SIZE = VX_LUT_ATTRIBUTE_SIZE; #endif vx_enum dataType() const { vx_enum v; query(VX_LUT_TYPE, v); return v; } vx_size count() const { vx_size v; query(VX_LUT_COUNT, v); return v; } vx_size size() const { vx_size v; query(VX_LUT_SIZE, v); return v; } #ifdef VX_VERSION_1_1 vx_uint32 offset() const { vx_enum v; query(VX_LUT_OFFSET, v); return v; } #endif // VX_VERSION_1_1 void copyTo(void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): output pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyLUT(ref, data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxAccessLUT(ref, &data, VX_READ_ONLY)); IVX_CHECK_STATUS(vxCommitLUT(ref, data)); #endif } void copyFrom(const void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): input pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyLUT(ref, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxAccessLUT(ref, const_cast(&data), VX_WRITE_ONLY)); IVX_CHECK_STATUS(vxCommitLUT(ref, data)); #endif } void copy(void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyLUT(ref, data, usage, memType)); #else IVX_CHECK_STATUS(vxAccessLUT(ref, const_cast(&data), usage)); IVX_CHECK_STATUS(vxCommitLUT(ref, data)); (void)memType; #endif } template void copyTo(std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (data.size() != count()) { if (data.size() == 0) data.resize(count()); else throw WrapperError(std::string(__func__) + "(): destination size is wrong"); } copyTo(&data[0]); } template void copyFrom(const std::vector& data) { if (!areTypesCompatible(TypeToEnum::value, dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); if (data.size() != count()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); copyFrom(&data[0]); } #ifdef IVX_USE_OPENCV void copyTo(cv::Mat& m) { if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (!( ((vx_size)(m.rows) == count() && m.cols == 1) || ((vx_size)(m.cols) == count() && m.rows == 1) ) && !m.empty()) throw WrapperError(std::string(__func__) + "(): destination size is wrong"); if (m.isContinuous() && (vx_size)(m.total()) == count()) { copyTo(m.ptr()); } else { cv::Mat tmp(1, (int)count(), enumToCVType(dataType())); copyTo(tmp.ptr()); if (m.empty()) m = tmp; else tmp.copyTo(m); } } void copyFrom(const cv::Mat& m) { if (!( ((vx_size)(m.rows) == count() && m.cols == 1) || ((vx_size)(m.cols) == count() && m.rows == 1) )) throw WrapperError(std::string(__func__) + "(): source size is wrong"); if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); copyFrom(m.isContinuous() ? m.ptr() : m.clone().ptr()); } #endif //IVX_USE_OPENCV }; /* * Pyramid */ class Pyramid : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Pyramid) static Pyramid create(vx_context context, vx_size levels, vx_float32 scale, vx_uint32 width, vx_uint32 height, vx_df_image format) {return Pyramid(vxCreatePyramid(context, levels, scale, width, height, format));} static Pyramid createVirtual(vx_graph graph, vx_size levels, vx_float32 scale, vx_uint32 width, vx_uint32 height, vx_df_image format) {return Pyramid(vxCreateVirtualPyramid(graph, levels, scale, width, height, format));} #ifndef VX_VERSION_1_1 static const vx_enum VX_PYRAMID_LEVELS = VX_PYRAMID_ATTRIBUTE_LEVELS, VX_PYRAMID_SCALE = VX_PYRAMID_ATTRIBUTE_SCALE, VX_PYRAMID_WIDTH = VX_PYRAMID_ATTRIBUTE_WIDTH, VX_PYRAMID_HEIGHT = VX_PYRAMID_ATTRIBUTE_HEIGHT, VX_PYRAMID_FORMAT = VX_PYRAMID_ATTRIBUTE_FORMAT; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS( vxQueryPyramid(ref, att, &value, sizeof(value)) ); } vx_size levels() const { vx_size l; query(VX_PYRAMID_LEVELS, l); return l; } vx_float32 scale() const { vx_float32 s; query(VX_PYRAMID_SCALE, s); return s; } vx_uint32 width() const { vx_uint32 v; query(VX_PYRAMID_WIDTH, v); return v; } vx_uint32 height() const { vx_uint32 v; query(VX_PYRAMID_HEIGHT, v); return v; } vx_df_image format() const { vx_df_image f; query(VX_PYRAMID_FORMAT, f); return f; } Image getLevel(vx_uint32 index) { return Image(vxGetPyramidLevel(ref, index)); } }; /* * Distribution */ class Distribution : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Distribution); static Distribution create(vx_context context, vx_size numBins, vx_int32 offset, vx_uint32 range) { return Distribution(vxCreateDistribution(context, numBins, offset, range)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_MEMORY_TYPE_HOST = VX_IMPORT_TYPE_HOST, VX_DISTRIBUTION_DIMENSIONS = VX_DISTRIBUTION_ATTRIBUTE_DIMENSIONS, VX_DISTRIBUTION_OFFSET = VX_DISTRIBUTION_ATTRIBUTE_OFFSET, VX_DISTRIBUTION_RANGE = VX_DISTRIBUTION_ATTRIBUTE_RANGE, VX_DISTRIBUTION_BINS = VX_DISTRIBUTION_ATTRIBUTE_BINS, VX_DISTRIBUTION_WINDOW = VX_DISTRIBUTION_ATTRIBUTE_WINDOW, VX_DISTRIBUTION_SIZE = VX_DISTRIBUTION_ATTRIBUTE_SIZE; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS(vxQueryDistribution(ref, att, &value, sizeof(value))); } vx_size dimensions() const { vx_size v; query(VX_DISTRIBUTION_DIMENSIONS, v); return v; } vx_int32 offset() const { vx_int32 v; query(VX_DISTRIBUTION_OFFSET, v); return v; } vx_uint32 range() const { vx_uint32 v; query(VX_DISTRIBUTION_RANGE, v); return v; } vx_size bins() const { vx_size v; query(VX_DISTRIBUTION_BINS, v); return v; } vx_uint32 window() const { vx_uint32 v; query(VX_DISTRIBUTION_WINDOW, v); return v; } vx_size size() const { vx_size v; query(VX_DISTRIBUTION_SIZE, v); return v; } vx_size dataType() const { return VX_TYPE_UINT32; } void copyTo(void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): output pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyDistribution(ref, data, VX_READ_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxAccessDistribution(ref, &data, VX_READ_ONLY)); IVX_CHECK_STATUS(vxCommitDistribution(ref, data)); #endif } void copyFrom(const void* data) { if (!data) throw WrapperError(std::string(__func__) + "(): input pointer is 0"); #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyDistribution(ref, const_cast(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST)); #else IVX_CHECK_STATUS(vxAccessDistribution(ref, const_cast(&data), VX_WRITE_ONLY)); IVX_CHECK_STATUS(vxCommitDistribution(ref, data)); #endif } void copy(void* data, vx_enum usage, vx_enum memType = VX_MEMORY_TYPE_HOST) { #ifdef VX_VERSION_1_1 IVX_CHECK_STATUS(vxCopyDistribution(ref, data, usage, memType)); #else IVX_CHECK_STATUS(vxAccessDistribution(ref, const_cast(&data), usage)); IVX_CHECK_STATUS(vxCommitDistribution(ref, data)); (void)memType; #endif } template void copyTo(std::vector& data) { if (TypeToEnum::value != dataType()) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (data.size() != bins()) { if (data.size() == 0) data.resize(bins()); else throw WrapperError(std::string(__func__) + "(): destination size is wrong"); } copyTo(&data[0]); } template void copyFrom(const std::vector& data) { if (TypeToEnum::value != dataType()) throw WrapperError(std::string(__func__) + "(): source type is wrong"); if (data.size() != bins()) throw WrapperError(std::string(__func__) + "(): source size is wrong"); copyFrom(&data[0]); } #ifdef IVX_USE_OPENCV void copyTo(cv::Mat& m) { if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); if (!( ((vx_size)(m.rows) == bins() && m.cols == 1) || ((vx_size)(m.cols) == bins() && m.rows == 1) ) && !m.empty()) throw WrapperError(std::string(__func__) + "(): destination size is wrong"); if (m.isContinuous() && (vx_size)(m.total()) == bins()) { copyTo(m.ptr()); } else { cv::Mat tmp(1, (int)bins(), enumToCVType(dataType())); copyTo(tmp.ptr()); if (m.empty()) m = tmp; else tmp.copyTo(m); } } void copyFrom(const cv::Mat& m) { if (!( ((vx_size)(m.rows) == bins() && m.cols == 1) || ((vx_size)(m.cols) == bins() && m.rows == 1) )) throw WrapperError(std::string(__func__) + "(): source size is wrong"); if (m.type() != enumToCVType(dataType())) throw WrapperError(std::string(__func__) + "(): source type is wrong"); copyFrom(m.isContinuous() ? m.ptr() : m.clone().ptr()); } #endif //IVX_USE_OPENCV }; /* * Remap */ class Remap : public RefWrapper { public: IVX_REF_STD_CTORS_AND_ASSIGNMENT(Remap); static Remap create(vx_context context, vx_uint32 src_width, vx_uint32 src_height, vx_uint32 dst_width, vx_uint32 dst_height) { return Remap(vxCreateRemap(context, src_width, src_height, dst_width, dst_height)); } #ifndef VX_VERSION_1_1 static const vx_enum VX_REMAP_SOURCE_WIDTH = VX_REMAP_ATTRIBUTE_SOURCE_WIDTH, VX_REMAP_SOURCE_HEIGHT = VX_REMAP_ATTRIBUTE_SOURCE_HEIGHT, VX_REMAP_DESTINATION_WIDTH = VX_REMAP_ATTRIBUTE_DESTINATION_WIDTH, VX_REMAP_DESTINATION_HEIGHT = VX_REMAP_ATTRIBUTE_DESTINATION_HEIGHT; #endif template void query(vx_enum att, T& value) const { IVX_CHECK_STATUS(vxQueryRemap(ref, att, &value, sizeof(value))); } vx_uint32 srcWidth() const { vx_uint32 v; query(VX_REMAP_SOURCE_WIDTH, v); return v; } vx_uint32 srcHeight() const { vx_uint32 v; query(VX_REMAP_SOURCE_HEIGHT, v); return v; } vx_uint32 dstWidth() const { vx_uint32 v; query(VX_REMAP_DESTINATION_WIDTH, v); return v; } vx_uint32 dstHeight() const { vx_uint32 v; query(VX_REMAP_DESTINATION_HEIGHT, v); return v; } vx_uint32 srcCoordType() const { return VX_TYPE_FLOAT32; } vx_uint32 dstCoordType() const { return VX_TYPE_UINT32; } void setMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 src_x, vx_float32 src_y) { IVX_CHECK_STATUS(vxSetRemapPoint(ref, dst_x, dst_y, src_x, src_y)); } void getMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 &src_x, vx_float32 &src_y) const { IVX_CHECK_STATUS(vxGetRemapPoint(ref, dst_x, dst_y, &src_x, &src_y)); } #ifdef IVX_USE_OPENCV void setMappings(const cv::Mat& map_x, const cv::Mat& map_y) { if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType())) throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); if ((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth()) throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); if ((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth()) throw WrapperError(std::string(__func__) + "(): y mapping size is wrong"); for (vx_uint32 y = 0; y < dstHeight(); y++) { const vx_float32* map_x_line = map_x.ptr(y); const vx_float32* map_y_line = map_y.ptr(y); for (vx_uint32 x = 0; x < dstWidth(); x++) setMapping(x, y, map_x_line[x], map_y_line[x]); } } void setMappings(const cv::Mat& map) { if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2) throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); if ((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth()) throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); for (vx_uint32 y = 0; y < dstHeight(); y++) { const vx_float32* map_line = map.ptr(y); for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2) setMapping(x, y, map_line[x], map_line[x+1]); } } void getMappings(cv::Mat& map_x, cv::Mat& map_y) const { if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType())) throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); if (((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth()) && !map_x.empty()) throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); if (((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth()) && !map_y.empty()) throw WrapperError(std::string(__func__) + "(): y mapping size is wrong"); if (map_x.empty()) map_x = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType())); if (map_y.empty()) map_y = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType())); for (vx_uint32 y = 0; y < dstHeight(); y++) { vx_float32* map_x_line = map_x.ptr(y); vx_float32* map_y_line = map_y.ptr(y); for (vx_uint32 x = 0; x < dstWidth(); x++) getMapping(x, y, map_x_line[x], map_y_line[x]); } } void getMappings(cv::Mat& map) const { if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2) throw WrapperError(std::string(__func__) + "(): mapping type is wrong"); if (((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth()) && !map.empty()) throw WrapperError(std::string(__func__) + "(): x mapping size is wrong"); if (map.empty()) map = cv::Mat((int)dstHeight(), (int)dstWidth(), CV_MAKETYPE(CV_MAT_DEPTH(enumToCVType(srcCoordType())),2)); for (vx_uint32 y = 0; y < dstHeight(); y++) { vx_float32* map_line = map.ptr(y); for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2) getMapping(x, y, map_line[x], map_line[x+1]); } } #endif //IVX_USE_OPENCV }; /// Standard nodes namespace nodes { /// Creates a Gaussian Filter 3x3 Node (vxGaussian3x3Node) inline Node gaussian3x3(vx_graph graph, vx_image inImg, vx_image outImg) { return Node(vxGaussian3x3Node(graph, inImg, outImg)); } } // namespace nodes } // namespace ivx // restore warnings #if defined(_MSC_VER) #pragma warning(pop) #elif defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif // compiler macro #endif //IVX_HPP