Added OpenVX based processing to calcHist
authorVitaly Tuzov <terfendail@mediana.jetos.com>
Fri, 25 Nov 2016 18:49:26 +0000 (21:49 +0300)
committerVitaly Tuzov <terfendail@mediana.jetos.com>
Tue, 13 Dec 2016 15:33:02 +0000 (18:33 +0300)
3rdparty/openvx/include/ivx.hpp
modules/imgproc/src/histogram.cpp

index 3d5102f..04304be 100644 (file)
@@ -343,6 +343,15 @@ template <> struct RefTypeTraits <vx_lut>
     static vx_status release(vxType& ref) { return vxReleaseLUT(&ref); }
 };
 
+class Distribution;
+template <> struct RefTypeTraits <vx_distribution>
+{
+    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<vx_distribution>
+{
+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<typename T>
+    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<void*>(data), VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST));
+#else
+        IVX_CHECK_STATUS(vxAccessDistribution(ref, const_cast<void**>(&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<void**>(&data), usage));
+        IVX_CHECK_STATUS(vxCommitDistribution(ref, data));
+        (void)memType;
+#endif
+    }
+
+    template<typename T> void copyTo(std::vector<T>& data)
+    {
+        if (TypeToEnum<T>::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<typename T> void copyFrom(const std::vector<T>& data)
+    {
+        if (TypeToEnum<T>::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 {
 
index 7f46bc2..23ec520 100644 (file)
 #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,