diff --git a/3rdparty/openvx/include/ivx.hpp b/3rdparty/openvx/include/ivx.hpp index b01731c0e1..0b2397707b 100644 --- a/3rdparty/openvx/include/ivx.hpp +++ b/3rdparty/openvx/include/ivx.hpp @@ -1838,6 +1838,160 @@ public: /// 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 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 copyRangeTo(size_t start, size_t end, std::vector& data) + { + if (TypeToEnum::value != itemType()) throw WrapperError(std::string(__func__) + "(): destination type is wrong"); + if (data.size() != (end - start)) + { + if (data.size() == 0) + data.resize((end - start)); + else + 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 (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 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 }; /* diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 9def2e171d..d829c69a9d 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -47,6 +47,12 @@ #include "opencl_kernels_core.hpp" +#ifdef HAVE_OPENVX +#define IVX_HIDE_INFO_WARNINGS +#define IVX_USE_OPENCV +#include "ivx.hpp" +#endif + namespace cv { @@ -2226,6 +2232,81 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* #endif +#ifdef HAVE_OPENVX +static bool openvx_minMaxIdx(Mat &src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, Mat &mask) +{ + int stype = src.type(); + size_t total_size = src.total(); + int rows = src.size[0], cols = rows ? (int)(total_size / rows) : 0; + if ((stype != CV_8UC1 && stype != CV_16SC1) || !mask.empty() || + (src.dims != 2 && !(src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size)) + ) + return false; + + try + { + ivx::Context ctx = ivx::Context::create(); + ivx::Image + ia = ivx::Image::createFromHandle(ctx, stype == CV_8UC1 ? VX_DF_IMAGE_U8 : VX_DF_IMAGE_S16, + ivx::Image::createAddressing(cols, rows, stype == CV_8UC1 ? 1 : 2, (vx_int32)(src.step[0])), src.ptr()); + + ivx::Scalar vxMinVal = ivx::Scalar::create(ctx, stype == CV_8UC1 ? VX_TYPE_UINT8 : VX_TYPE_INT16, 0); + ivx::Scalar vxMaxVal = ivx::Scalar::create(ctx, stype == CV_8UC1 ? VX_TYPE_UINT8 : VX_TYPE_INT16, 0); + ivx::Array vxMinInd, vxMaxInd; + ivx::Scalar vxMinCount, vxMaxCount; + if (minIdx) + { + vxMinInd = ivx::Array::create(ctx, VX_TYPE_COORDINATES2D, 1); + vxMinCount = ivx::Scalar::create(ctx, VX_TYPE_UINT32, 0); + } + if (maxIdx) + { + vxMaxInd = ivx::Array::create(ctx, VX_TYPE_COORDINATES2D, 1); + vxMaxCount = ivx::Scalar::create(ctx, VX_TYPE_UINT32, 0); + } + + ivx::IVX_CHECK_STATUS(vxuMinMaxLoc(ctx, ia, vxMinVal, vxMaxVal, vxMinInd, vxMaxInd, vxMinCount, vxMaxCount)); + + if (minVal) + { + *minVal = stype == CV_8UC1 ? vxMinVal.getValue() : vxMinVal.getValue(); + } + if (maxVal) + { + *maxVal = stype == CV_8UC1 ? vxMaxVal.getValue() : vxMaxVal.getValue(); + } + if (minIdx) + { + if(vxMinCount.getValue()<1) throw ivx::RuntimeError(VX_ERROR_INVALID_VALUE, std::string(__func__) + "(): minimum value location not found"); + vx_coordinates2d_t loc; + vxMinInd.copyRangeTo(0, 1, &loc); + size_t minidx = loc.y * cols + loc.x + 1; + ofs2idx(src, minidx, minIdx); + } + if (maxIdx) + { + if (vxMaxCount.getValue()<1) throw ivx::RuntimeError(VX_ERROR_INVALID_VALUE, std::string(__func__) + "(): maximum value location not found"); + vx_coordinates2d_t loc; + vxMaxInd.copyRangeTo(0, 1, &loc); + size_t maxidx = loc.y * cols + loc.x + 1; + ofs2idx(src, maxidx, maxIdx); + } + + return true; + } + catch (ivx::RuntimeError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } + catch (ivx::WrapperError & e) + { + CV_Error(CV_StsInternal, e.what()); + return false; + } +} +#endif + #ifdef HAVE_IPP static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, Mat &mask) { @@ -2349,6 +2430,12 @@ void cv::minMaxIdx(InputArray _src, double* minVal, ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask)) Mat src = _src.getMat(), mask = _mask.getMat(); + +#ifdef HAVE_OPENVX + if (openvx_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) + return; +#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) MinMaxIdxFunc func = getMinmaxTab(depth);