diff --git a/3rdparty/openvx/include/ivx.hpp b/3rdparty/openvx/include/ivx.hpp index 3d5102f5cf..04304be390 100644 --- a/3rdparty/openvx/include/ivx.hpp +++ b/3rdparty/openvx/include/ivx.hpp @@ -343,6 +343,15 @@ template <> struct RefTypeTraits static vx_status release(vxType& ref) { return vxReleaseLUT(&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); } +}; + #ifdef IVX_USE_CXX98 /// Casting to vx_reference with compile-time check @@ -2738,6 +2747,173 @@ public: #endif //IVX_USE_OPENCV }; +/* +* 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 +}; + /// Standard nodes namespace nodes { diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 7f46bc2d03..23ec520444 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -42,11 +42,7 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#ifdef HAVE_OPENVX -#define IVX_USE_OPENCV -#define IVX_HIDE_INFO_WARNINGS -#include "ivx.hpp" -#endif +#include "opencv2/core/openvx/ovx_defs.hpp" namespace cv { @@ -1268,6 +1264,63 @@ private: } +#ifdef HAVE_OPENVX +namespace cv +{ + static bool openvx_calchist(const Mat& image, OutputArray _hist, const int histSize, + const float* _range) + { + vx_int32 offset = (vx_int32)(_range[0]); + vx_uint32 range = (vx_uint32)(_range[1] - _range[0]); + if (float(offset) != _range[0] || float(range) != (_range[1] - _range[0])) + return false; + + size_t total_size = image.total(); + int rows = image.dims > 1 ? image.size[0] : 1, cols = rows ? (int)(total_size / rows) : 0; + if (image.dims > 2 && !(image.isContinuous() && cols > 0 && (size_t)rows*cols == total_size)) + return false; + + try + { + ivx::Context ctx = ivx::Context::create(); +#if VX_VERSION <= VX_VERSION_1_0 + if (ctx.vendorID() == VX_ID_KHRONOS && (range % histSize)) + return false; +#endif + + ivx::Image + img = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8, + ivx::Image::createAddressing(cols, rows, 1, (vx_int32)(image.step[0])), image.data); + + ivx::Distribution vxHist = ivx::Distribution::create(ctx, histSize, offset, range); + ivx::IVX_CHECK_STATUS(vxuHistogram(ctx, img, vxHist)); + + _hist.create(1, &histSize, CV_32F); + Mat hist = _hist.getMat(), ihist = hist; + ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK) | CV_32S; + vxHist.copyTo(ihist); + ihist.convertTo(hist, CV_32F); + +#ifdef VX_VERSION_1_1 + img.swapHandle(); +#endif + } + catch (ivx::RuntimeError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + catch (ivx::WrapperError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + + return true; + } +} +#endif + #if defined(HAVE_IPP) namespace cv { @@ -1321,6 +1374,13 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels, { CV_INSTRUMENT_REGION() + CV_OVX_RUN( + images && histSize && + nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && _mask.getMat().empty() && + (!channels || channels[0] == 0) && !accumulate && uniform && + ranges && ranges[0], + openvx_calchist(images[0], _hist, histSize[0], ranges[0])); + CV_IPP_RUN(nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels && channels[0] == 0 && _mask.getMat().empty() && images[0].dims <= 2 && !accumulate && uniform,