You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			355 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			355 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
// 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) 2018 Intel Corporation
 | 
						|
 | 
						|
 | 
						|
#ifndef OPENCV_GAPI_OWN_MAT_HPP
 | 
						|
#define OPENCV_GAPI_OWN_MAT_HPP
 | 
						|
 | 
						|
#include <opencv2/gapi/opencv_includes.hpp>
 | 
						|
#include <opencv2/gapi/own/types.hpp>
 | 
						|
#include <opencv2/gapi/own/scalar.hpp>
 | 
						|
#include <opencv2/gapi/own/saturate.hpp>
 | 
						|
#include <opencv2/gapi/own/assert.hpp>
 | 
						|
 | 
						|
#include <memory>                   //std::shared_ptr
 | 
						|
#include <cstring>                  //std::memcpy
 | 
						|
#include <numeric>                  //std::accumulate
 | 
						|
#include <vector>
 | 
						|
#include <opencv2/gapi/util/throw.hpp>
 | 
						|
 | 
						|
namespace cv { namespace gapi { namespace own {
 | 
						|
    namespace detail {
 | 
						|
        template <typename T, unsigned char channels>
 | 
						|
        void assign_row(void* ptr, int cols, Scalar const& s)
 | 
						|
        {
 | 
						|
            auto p = static_cast<T*>(ptr);
 | 
						|
            for (int c = 0; c < cols; c++)
 | 
						|
            {
 | 
						|
                for (int ch = 0; ch < channels; ch++)
 | 
						|
                {
 | 
						|
                    p[c * channels + ch] = saturate<T>(s[ch], roundd);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        inline size_t default_step(int type, int cols)
 | 
						|
        {
 | 
						|
            return CV_ELEM_SIZE(type) * cols;
 | 
						|
        }
 | 
						|
        //Matrix header, i.e. fields that are unique to each Mat object.
 | 
						|
        //Devoted class is needed to implement custom behavior on move (erasing state of moved from object)
 | 
						|
        struct MatHeader{
 | 
						|
            enum { AUTO_STEP = 0};
 | 
						|
            enum { TYPE_MASK = 0x00000FFF  };
 | 
						|
 | 
						|
            MatHeader() = default;
 | 
						|
 | 
						|
            MatHeader(int _rows, int _cols, int type, void* _data, size_t _step)
 | 
						|
            : flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step)
 | 
						|
            {}
 | 
						|
 | 
						|
            MatHeader(const std::vector<int> &_dims, int type, void* _data)
 | 
						|
            : flags((type & TYPE_MASK)), data((uchar*)_data), step(0), dims(_dims)
 | 
						|
            {}
 | 
						|
 | 
						|
            MatHeader(const MatHeader& ) = default;
 | 
						|
            MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here
 | 
						|
            {
 | 
						|
                MatHeader empty; //give it a name to call copy(not move) assignment below
 | 
						|
                src = empty;
 | 
						|
            }
 | 
						|
            MatHeader& operator=(const MatHeader& ) = default;
 | 
						|
            MatHeader& operator=(MatHeader&& src)
 | 
						|
            {
 | 
						|
                *this = src; //calling a copy assignment here, not move one
 | 
						|
                MatHeader empty; //give it a name to call copy(not move) assignment below
 | 
						|
                src = empty;
 | 
						|
                return *this;
 | 
						|
            }
 | 
						|
            /*! includes several bit-fields:
 | 
						|
                 - depth
 | 
						|
                 - number of channels
 | 
						|
             */
 | 
						|
            int flags = 0;
 | 
						|
 | 
						|
            //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
 | 
						|
            int rows = 0, cols = 0;
 | 
						|
            //! pointer to the data
 | 
						|
            uchar* data = nullptr;
 | 
						|
            size_t step = 0;
 | 
						|
            //! dimensions (ND-case)
 | 
						|
            std::vector<int> dims;
 | 
						|
        };
 | 
						|
    } // namespace detail
 | 
						|
    //concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required)
 | 
						|
    class Mat : public detail::MatHeader{
 | 
						|
    public:
 | 
						|
 | 
						|
        Mat() = default;
 | 
						|
 | 
						|
        /** @overload
 | 
						|
        @param _rows Number of rows in a 2D array.
 | 
						|
        @param _cols Number of columns in a 2D array.
 | 
						|
        @param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
 | 
						|
        CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
 | 
						|
        @param _data Pointer to the user data. Matrix constructors that take data and step parameters do not
 | 
						|
        allocate matrix data. Instead, they just initialize the matrix header that points to the specified
 | 
						|
        data, which means that no data is copied. This operation is very efficient and can be used to
 | 
						|
        process external data using OpenCV functions. The external data is not automatically deallocated, so
 | 
						|
        you should take care of it.
 | 
						|
        @param _step Number of bytes each matrix row occupies. The value should include the padding bytes at
 | 
						|
        the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed
 | 
						|
        and the actual step is calculated as cols*elemSize(). See Mat::elemSize.
 | 
						|
        */
 | 
						|
        Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP)
 | 
						|
        : MatHeader (_rows, _cols, _type, _data, _step)
 | 
						|
        {}
 | 
						|
 | 
						|
        Mat(const std::vector<int> &_dims, int _type, void* _data)
 | 
						|
        : MatHeader (_dims, _type, _data)
 | 
						|
        {}
 | 
						|
 | 
						|
        Mat(std::vector<int> &&_dims, int _type, void* _data)
 | 
						|
        : MatHeader (std::move(_dims), _type, _data)
 | 
						|
        {}
 | 
						|
 | 
						|
        Mat(Mat const& src, const Rect& roi )
 | 
						|
        : Mat(src)
 | 
						|
        {
 | 
						|
           rows = roi.height;
 | 
						|
           cols = roi.width;
 | 
						|
           data = ptr(roi.y, roi.x);
 | 
						|
        }
 | 
						|
 | 
						|
        Mat(Mat const& ) = default;
 | 
						|
        Mat(Mat&& ) = default;
 | 
						|
 | 
						|
        Mat& operator=(Mat const& ) = default;
 | 
						|
        Mat& operator=(Mat&& ) = default;
 | 
						|
 | 
						|
        /** @brief Sets all or some of the array elements to the specified value.
 | 
						|
        @param s Assigned scalar converted to the actual array type.
 | 
						|
        */
 | 
						|
        Mat& operator = (const Scalar& s)
 | 
						|
        {
 | 
						|
            constexpr unsigned max_channels = 4; //Scalar can't fit more than 4
 | 
						|
            using func_p_t = void (*)(void*, int, Scalar const&);
 | 
						|
            using detail::assign_row;
 | 
						|
            #define TABLE_ENTRY(type)  {assign_row<type, 1>, assign_row<type, 2>, assign_row<type, 3>, assign_row<type, 4>}
 | 
						|
            static constexpr func_p_t func_tbl[][max_channels] = {
 | 
						|
                    TABLE_ENTRY(uchar),
 | 
						|
                    TABLE_ENTRY(schar),
 | 
						|
                    TABLE_ENTRY(ushort),
 | 
						|
                    TABLE_ENTRY(short),
 | 
						|
                    TABLE_ENTRY(int),
 | 
						|
                    TABLE_ENTRY(float),
 | 
						|
                    TABLE_ENTRY(double)
 | 
						|
            };
 | 
						|
            #undef TABLE_ENTRY
 | 
						|
 | 
						|
            static_assert(CV_8U == 0 && CV_8S == 1  && CV_16U == 2 && CV_16S == 3
 | 
						|
                       && CV_32S == 4 && CV_32F == 5 && CV_64F == 6,
 | 
						|
                       "OCV type ids used as indexes to array, thus exact numbers are important!"
 | 
						|
            );
 | 
						|
 | 
						|
            const auto depth = static_cast<unsigned int>(this->depth());
 | 
						|
            GAPI_Assert(depth < sizeof(func_tbl)/sizeof(func_tbl[0]));
 | 
						|
 | 
						|
            if (dims.empty())
 | 
						|
            {
 | 
						|
                const auto channels = static_cast<unsigned int>(this->channels());
 | 
						|
                GAPI_Assert(channels <= max_channels);
 | 
						|
 | 
						|
                auto* f = func_tbl[depth][channels - 1];
 | 
						|
                for (int r = 0; r < rows; ++r)
 | 
						|
                {
 | 
						|
                    (*f)(static_cast<void *>(ptr(r)), cols, s );
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                auto* f = func_tbl[depth][0];
 | 
						|
                // FIXME: better to refactor assign_row to use std::size_t by default
 | 
						|
                (*f)(static_cast<void *>(data), static_cast<int>(total()), s);
 | 
						|
            }
 | 
						|
            return *this;
 | 
						|
        }
 | 
						|
 | 
						|
        /** @brief Returns the matrix element size in bytes.
 | 
						|
 | 
						|
        The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 ,
 | 
						|
        the method returns 3\*sizeof(short) or 6.
 | 
						|
         */
 | 
						|
        size_t elemSize() const
 | 
						|
        {
 | 
						|
            return CV_ELEM_SIZE(type());
 | 
						|
        }
 | 
						|
        /** @brief Returns the type of a matrix element.
 | 
						|
 | 
						|
        The method returns a matrix element type. This is an identifier compatible with the CvMat type
 | 
						|
        system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
 | 
						|
         */
 | 
						|
        int type() const            {return CV_MAT_TYPE(flags);}
 | 
						|
 | 
						|
        /** @brief Returns the depth of a matrix element.
 | 
						|
 | 
						|
        The method returns the identifier of the matrix element depth (the type of each individual channel).
 | 
						|
        For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
 | 
						|
        matrix types contains the following values:
 | 
						|
        -   CV_8U - 8-bit unsigned integers ( 0..255 )
 | 
						|
        -   CV_8S - 8-bit signed integers ( -128..127 )
 | 
						|
        -   CV_16U - 16-bit unsigned integers ( 0..65535 )
 | 
						|
        -   CV_16S - 16-bit signed integers ( -32768..32767 )
 | 
						|
        -   CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
 | 
						|
        -   CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
 | 
						|
        -   CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
 | 
						|
         */
 | 
						|
        int depth() const           {return CV_MAT_DEPTH(flags);}
 | 
						|
 | 
						|
        /** @brief Returns the number of matrix channels.
 | 
						|
 | 
						|
        The method returns the number of matrix channels.
 | 
						|
        If matrix is N-dimensional, -1 is returned.
 | 
						|
         */
 | 
						|
        int channels() const        {return dims.empty() ? CV_MAT_CN(flags) : -1;}
 | 
						|
 | 
						|
        /**
 | 
						|
        @param _rows New number of rows.
 | 
						|
        @param _cols New number of columns.
 | 
						|
        @param _type New matrix type.
 | 
						|
         */
 | 
						|
        void create(int _rows, int _cols, int _type)
 | 
						|
        {
 | 
						|
            create(Size{_cols, _rows}, _type);
 | 
						|
        }
 | 
						|
        /** @overload
 | 
						|
        @param _size Alternative new matrix size specification: Size(cols, rows)
 | 
						|
        @param _type New matrix type.
 | 
						|
        */
 | 
						|
        void create(Size _size, int _type)
 | 
						|
        {
 | 
						|
            GAPI_Assert(_size.height >= 0 && _size.width >= 0);
 | 
						|
            if (_size != Size{cols, rows} )
 | 
						|
            {
 | 
						|
                Mat tmp{_size.height, _size.width, _type, nullptr};
 | 
						|
                tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;});
 | 
						|
                tmp.data = tmp.memory.get();
 | 
						|
 | 
						|
                *this = std::move(tmp);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void create(const std::vector<int> &_dims, int _type)
 | 
						|
        {
 | 
						|
            // FIXME: make a proper reallocation-on-demands
 | 
						|
            // WARNING: no tensor views, so no strides
 | 
						|
            Mat tmp{_dims, _type, nullptr};
 | 
						|
            // FIXME: this accumulate duplicates a lot
 | 
						|
            const auto sz = std::accumulate(_dims.begin(), _dims.end(), 1, std::multiplies<int>());
 | 
						|
            tmp.memory.reset(new uchar[CV_ELEM_SIZE(_type)*sz], [](uchar * p){delete[] p;});
 | 
						|
            tmp.data = tmp.memory.get();
 | 
						|
            *this = std::move(tmp);
 | 
						|
        }
 | 
						|
 | 
						|
        /** @brief Creates a full copy of the matrix and the underlying data.
 | 
						|
 | 
						|
        The method creates a full copy of the matrix. The original step[] is not taken into account.
 | 
						|
        So, the copy has a continuous buffer occupying total() * elemSize() bytes.
 | 
						|
         */
 | 
						|
        Mat clone() const
 | 
						|
        {
 | 
						|
            Mat m;
 | 
						|
            copyTo(m);
 | 
						|
            return m;
 | 
						|
        }
 | 
						|
 | 
						|
        /** @brief Copies the matrix to another one.
 | 
						|
 | 
						|
        The method copies the matrix data to another matrix. Before copying the data, the method invokes :
 | 
						|
        @code
 | 
						|
            m.create(this->size(), this->type());
 | 
						|
        @endcode
 | 
						|
        so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the
 | 
						|
        function does not handle the case of a partial overlap between the source and the destination
 | 
						|
        matrices.
 | 
						|
         */
 | 
						|
        void copyTo(Mat& dst) const
 | 
						|
        {
 | 
						|
            if (dims.empty())
 | 
						|
            {
 | 
						|
                dst.create(rows, cols, type());
 | 
						|
                for (int r = 0; r < rows; ++r)
 | 
						|
                {
 | 
						|
                    std::copy_n(ptr(r), detail::default_step(type(),cols), dst.ptr(r));
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                dst.create(dims, depth());
 | 
						|
                std::copy_n(data, total()*elemSize(), data);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /** @brief Returns true if the array has no elements.
 | 
						|
 | 
						|
        The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and
 | 
						|
        resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
 | 
						|
         */
 | 
						|
        bool empty() const
 | 
						|
        {
 | 
						|
            return data == 0 || total() == 0;
 | 
						|
        }
 | 
						|
 | 
						|
        /** @brief Returns the total number of array elements.
 | 
						|
 | 
						|
        The method returns the number of array elements (a number of pixels if the array represents an
 | 
						|
        image).
 | 
						|
         */
 | 
						|
        size_t total() const
 | 
						|
        {
 | 
						|
            return dims.empty()
 | 
						|
                 ? (static_cast<std::size_t>(rows) * cols)
 | 
						|
                 : std::accumulate(dims.begin(), dims.end(), static_cast<std::size_t>(1), std::multiplies<size_t>());
 | 
						|
        }
 | 
						|
 | 
						|
        /** @overload
 | 
						|
        @param roi Extracted submatrix specified as a rectangle.
 | 
						|
        */
 | 
						|
        Mat operator()( const Rect& roi ) const
 | 
						|
        {
 | 
						|
            return Mat{*this, roi};
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /** @brief Returns a pointer to the specified matrix row.
 | 
						|
 | 
						|
        The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in
 | 
						|
        Mat::isContinuous to know how to use these methods.
 | 
						|
        @param row Index along the dimension 0
 | 
						|
        @param col Index along the dimension 1
 | 
						|
        */
 | 
						|
        uchar* ptr(int row, int col = 0)
 | 
						|
        {
 | 
						|
            return const_cast<uchar*>(const_cast<const Mat*>(this)->ptr(row,col));
 | 
						|
        }
 | 
						|
        /** @overload */
 | 
						|
        const uchar* ptr(int row, int col = 0) const
 | 
						|
        {
 | 
						|
            return data + step * row + CV_ELEM_SIZE(type()) * col;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
    private:
 | 
						|
        //actual memory allocated for storage, or nullptr if object is non owning view to over memory
 | 
						|
        std::shared_ptr<uchar> memory;
 | 
						|
    };
 | 
						|
 | 
						|
} //namespace own
 | 
						|
} //namespace gapi
 | 
						|
} //namespace cv
 | 
						|
 | 
						|
#endif /* OPENCV_GAPI_OWN_MAT_HPP */
 |