Merge pull request #8535 from arnaudbrejeon:std_array
authorArnaud Brejeon <arnaud.brejeon+github@gmail.com>
Wed, 19 Apr 2017 10:13:39 +0000 (03:13 -0700)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Wed, 19 Apr 2017 10:13:39 +0000 (13:13 +0300)
Add support for std::array<T, N> (#8535)

* Add support for std::array<T, N>

* Add std::array<Mat, N> support

* Remove UMat constructor with std::array parameter

modules/core/include/opencv2/core/cvdef.h
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/mat.inl.hpp
modules/core/src/convert.cpp
modules/core/src/lda.cpp
modules/core/src/matmul.cpp
modules/core/src/matrix.cpp
modules/core/test/test_mat.cpp

index 43f8a02..a0c3438 100644 (file)
@@ -364,6 +364,21 @@ Cv64suf;
 #  endif
 #endif
 
+/****************************************************************************************\
+*                                    C++11 std::array                                    *
+\****************************************************************************************/
+
+#ifndef CV_CXX_STD_ARRAY
+#  if __cplusplus >= 201103L
+#    define CV_CXX_STD_ARRAY 1
+#    include <array>
+#  endif
+#else
+#  if CV_CXX_STD_ARRAY == 0
+#    undef CV_CXX_STD_ARRAY
+#  endif
+#endif
+
 //! @}
 
 #endif // OPENCV_CORE_CVDEF_H
index e3a2403..0a74e72 100644 (file)
@@ -165,7 +165,9 @@ public:
         UMAT              =10 << KIND_SHIFT,
         STD_VECTOR_UMAT   =11 << KIND_SHIFT,
         STD_BOOL_VECTOR   =12 << KIND_SHIFT,
-        STD_VECTOR_CUDA_GPU_MAT = 13 << KIND_SHIFT
+        STD_VECTOR_CUDA_GPU_MAT = 13 << KIND_SHIFT,
+        STD_ARRAY         =14 << KIND_SHIFT,
+        STD_ARRAY_MAT     =15 << KIND_SHIFT
     };
 
     _InputArray();
@@ -189,6 +191,11 @@ public:
     _InputArray(const UMat& um);
     _InputArray(const std::vector<UMat>& umv);
 
+#ifdef CV_CXX_STD_ARRAY
+    template<typename _Tp, std::size_t _N> _InputArray(const std::array<_Tp, _N>& arr);
+    template<std::size_t _N> _InputArray(const std::array<Mat, _N>& arr);
+#endif
+
     Mat getMat(int idx=-1) const;
     Mat getMat_(int idx=-1) const;
     UMat getUMat(int idx=-1) const;
@@ -316,6 +323,13 @@ public:
     _OutputArray(const UMat& m);
     _OutputArray(const std::vector<UMat>& vec);
 
+#ifdef CV_CXX_STD_ARRAY
+    template<typename _Tp, std::size_t _N> _OutputArray(std::array<_Tp, _N>& arr);
+    template<typename _Tp, std::size_t _N> _OutputArray(const std::array<_Tp, _N>& arr);
+    template<std::size_t _N> _OutputArray(std::array<Mat, _N>& arr);
+    template<std::size_t _N> _OutputArray(const std::array<Mat, _N>& arr);
+#endif
+
     bool fixedSize() const;
     bool fixedType() const;
     bool needed() const;
@@ -374,6 +388,14 @@ public:
     template<typename _Tp, int m, int n> _InputOutputArray(const Matx<_Tp, m, n>& matx);
     _InputOutputArray(const UMat& m);
     _InputOutputArray(const std::vector<UMat>& vec);
+
+#ifdef CV_CXX_STD_ARRAY
+    template<typename _Tp, std::size_t _N> _InputOutputArray(std::array<_Tp, _N>& arr);
+    template<typename _Tp, std::size_t _N> _InputOutputArray(const std::array<_Tp, _N>& arr);
+    template<std::size_t _N> _InputOutputArray(std::array<Mat, _N>& arr);
+    template<std::size_t _N> _InputOutputArray(const std::array<Mat, _N>& arr);
+#endif
+
 };
 
 typedef const _InputArray& InputArray;
@@ -955,6 +977,12 @@ public:
     */
     template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false);
 
+#ifdef CV_CXX_STD_ARRAY
+    /** @overload
+    */
+    template<typename _Tp, size_t _N> explicit Mat(const std::array<_Tp, _N>& arr, bool copyData=false);
+#endif
+
     /** @overload
     */
     template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true);
@@ -1575,6 +1603,10 @@ public:
     template<typename _Tp, int n> operator Vec<_Tp, n>() const;
     template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;
 
+#ifdef CV_CXX_STD_ARRAY
+    template<typename _Tp, std::size_t _N> operator std::array<_Tp, _N>() const;
+#endif
+
     /** @brief Reports whether the matrix is continuous or not.
 
     The method returns true if the matrix elements are stored continuously without gaps at the end of
@@ -2114,6 +2146,10 @@ public:
     explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
     explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
 
+#ifdef CV_CXX_STD_ARRAY
+    template <std::size_t _N> explicit Mat_(const std::array<_Tp, _N>& arr, bool copyData=false);
+#endif
+
     Mat_& operator = (const Mat& m);
     Mat_& operator = (const Mat_& m);
     //! set all the elements to s.
@@ -2207,6 +2243,12 @@ public:
 
     //! conversion to vector.
     operator std::vector<_Tp>() const;
+
+#ifdef CV_CXX_STD_ARRAY
+    //! conversion to array.
+    template<std::size_t _N> operator std::array<_Tp, _N>() const;
+#endif
+
     //! conversion to Vec
     template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const;
     //! conversion to Matx
@@ -2281,6 +2323,7 @@ public:
     UMat(const UMat& m, const std::vector<Range>& ranges);
     //! builds matrix from std::vector with or without copying the data
     template<typename _Tp> explicit UMat(const std::vector<_Tp>& vec, bool copyData=false);
+
     //! builds matrix from cv::Vec; the data is copied by default
     template<typename _Tp, int n> explicit UMat(const Vec<_Tp, n>& vec, bool copyData=true);
     //! builds matrix from cv::Matx; the data is copied by default
index aa746e8..399c922 100644 (file)
@@ -77,6 +77,16 @@ template<typename _Tp> inline
 _InputArray::_InputArray(const std::vector<_Tp>& vec)
 { init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_READ, &vec); }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+_InputArray::_InputArray(const std::array<_Tp, _N>& arr)
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_READ, arr.data(), Size(1, _N)); }
+
+template<std::size_t _N> inline
+_InputArray::_InputArray(const std::array<Mat, _N>& arr)
+{ init(STD_ARRAY_MAT + ACCESS_READ, arr.data(), Size(1, _N)); }
+#endif
+
 inline
 _InputArray::_InputArray(const std::vector<bool>& vec)
 { init(FIXED_TYPE + STD_BOOL_VECTOR + DataType<bool>::type + ACCESS_READ, &vec); }
@@ -133,7 +143,9 @@ inline bool _InputArray::isUMat() const  { return kind() == _InputArray::UMAT; }
 inline bool _InputArray::isMatVector() const { return kind() == _InputArray::STD_VECTOR_MAT; }
 inline bool _InputArray::isUMatVector() const  { return kind() == _InputArray::STD_VECTOR_UMAT; }
 inline bool _InputArray::isMatx() const { return kind() == _InputArray::MATX; }
-inline bool _InputArray::isVector() const { return kind() == _InputArray::STD_VECTOR || kind() == _InputArray::STD_BOOL_VECTOR; }
+inline bool _InputArray::isVector() const { return kind() == _InputArray::STD_VECTOR ||
+                                                   kind() == _InputArray::STD_BOOL_VECTOR ||
+                                                   kind() == _InputArray::STD_ARRAY; }
 inline bool _InputArray::isGpuMatVector() const { return kind() == _InputArray::STD_VECTOR_CUDA_GPU_MAT; }
 
 ////////////////////////////////////////////////////////////////////////////////////////
@@ -149,6 +161,16 @@ template<typename _Tp> inline
 _OutputArray::_OutputArray(std::vector<_Tp>& vec)
 { init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+_OutputArray::_OutputArray(std::array<_Tp, _N>& arr)
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_WRITE, arr.data(), Size(1, _N)); }
+
+template<std::size_t _N> inline
+_OutputArray::_OutputArray(std::array<Mat, _N>& arr)
+{ init(STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _N)); }
+#endif
+
 inline
 _OutputArray::_OutputArray(std::vector<bool>&)
 { CV_Error(Error::StsUnsupportedFormat, "std::vector<bool> cannot be an output array\n"); }
@@ -177,6 +199,16 @@ template<typename _Tp> inline
 _OutputArray::_OutputArray(const std::vector<_Tp>& vec)
 { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+_OutputArray::_OutputArray(const std::array<_Tp, _N>& arr)
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_WRITE, arr.data(), Size(1, _N)); }
+
+template<std::size_t _N> inline
+_OutputArray::_OutputArray(const std::array<Mat, _N>& arr)
+{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _N)); }
+#endif
+
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const std::vector<std::vector<_Tp> >& vec)
 { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
@@ -244,6 +276,16 @@ template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec)
 { init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+_InputOutputArray::_InputOutputArray(std::array<_Tp, _N>& arr)
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_RW, arr.data(), Size(1, _N)); }
+
+template<std::size_t _N> inline
+_InputOutputArray::_InputOutputArray(std::array<Mat, _N>& arr)
+{ init(STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _N)); }
+#endif
+
 inline _InputOutputArray::_InputOutputArray(std::vector<bool>&)
 { CV_Error(Error::StsUnsupportedFormat, "std::vector<bool> cannot be an input/output array\n"); }
 
@@ -271,6 +313,16 @@ template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const std::vector<_Tp>& vec)
 { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+_InputOutputArray::_InputOutputArray(const std::array<_Tp, _N>& arr)
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_RW, arr.data(), Size(1, _N)); }
+
+template<std::size_t _N> inline
+_InputOutputArray::_InputOutputArray(const std::array<Mat, _N>& arr)
+{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _N)); }
+#endif
+
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const std::vector<std::vector<_Tp> >& vec)
 { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
@@ -505,6 +557,25 @@ Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
         Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
 }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+Mat::Mat(const std::array<_Tp, _N>& arr, bool copyData)
+    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)arr.size()),
+      cols(1), data(0), datastart(0), dataend(0), allocator(0), u(0), size(&rows)
+{
+    if(arr.empty())
+        return;
+    if( !copyData )
+    {
+        step[0] = step[1] = sizeof(_Tp);
+        datastart = data = (uchar*)arr.data();
+        datalimit = dataend = datastart + rows * step[0];
+    }
+    else
+        Mat((int)arr.size(), 1, DataType<_Tp>::type, (uchar*)arr.data()).copyTo(*this);
+}
+#endif
+
 template<typename _Tp, int n> inline
 Mat::Mat(const Vec<_Tp, n>& vec, bool copyData)
     : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0),
@@ -1114,6 +1185,16 @@ Mat::operator std::vector<_Tp>() const
     return v;
 }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp, std::size_t _N> inline
+Mat::operator std::array<_Tp, _N>() const
+{
+    std::array<_Tp, _N> v;
+    copyTo(v);
+    return v;
+}
+#endif
+
 template<typename _Tp, int n> inline
 Mat::operator Vec<_Tp, n>() const
 {
@@ -1468,6 +1549,13 @@ Mat_<_Tp>::Mat_(const std::vector<_Tp>& vec, bool copyData)
     : Mat(vec, copyData)
 {}
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp> template<std::size_t _N> inline
+Mat_<_Tp>::Mat_(const std::array<_Tp, _N>& arr, bool copyData)
+    : Mat(arr, copyData)
+{}
+#endif
+
 template<typename _Tp> inline
 Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
 {
@@ -1745,6 +1833,16 @@ Mat_<_Tp>::operator std::vector<_Tp>() const
     return v;
 }
 
+#ifdef CV_CXX_STD_ARRAY
+template<typename _Tp> template<std::size_t _N> inline
+Mat_<_Tp>::operator std::array<_Tp, _N>() const
+{
+    std::array<_Tp, _N> a;
+    copyTo(a);
+    return a;
+}
+#endif
+
 template<typename _Tp> template<int n> inline
 Mat_<_Tp>::operator Vec<typename DataType<_Tp>::channel_type, n>() const
 {
@@ -3426,7 +3524,6 @@ cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
         Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
 }
 
-
 inline
 UMat& UMat::operator = (const UMat& m)
 {
index 6c060f9..8d3c242 100644 (file)
@@ -637,9 +637,11 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst,
                ocl_mixChannels(src, dst, fromTo, npairs))
 
     bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT &&
+            src.kind() != _InputArray::STD_ARRAY_MAT &&
             src.kind() != _InputArray::STD_VECTOR_VECTOR &&
             src.kind() != _InputArray::STD_VECTOR_UMAT;
     bool dst_is_mat = dst.kind() != _InputArray::STD_VECTOR_MAT &&
+            dst.kind() != _InputArray::STD_ARRAY_MAT &&
             dst.kind() != _InputArray::STD_VECTOR_VECTOR &&
             dst.kind() != _InputArray::STD_VECTOR_UMAT;
     int i;
@@ -668,9 +670,11 @@ void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst,
                ocl_mixChannels(src, dst, &fromTo[0], fromTo.size()>>1))
 
     bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT &&
+            src.kind() != _InputArray::STD_ARRAY_MAT &&
             src.kind() != _InputArray::STD_VECTOR_VECTOR &&
             src.kind() != _InputArray::STD_VECTOR_UMAT;
     bool dst_is_mat = dst.kind() != _InputArray::STD_VECTOR_MAT &&
+            dst.kind() != _InputArray::STD_ARRAY_MAT &&
             dst.kind() != _InputArray::STD_VECTOR_VECTOR &&
             dst.kind() != _InputArray::STD_VECTOR_UMAT;
     int i;
index 4ccbf8a..a706eeb 100644 (file)
@@ -53,7 +53,8 @@ static Mat argsort(InputArray _src, bool ascending=true)
 
 static Mat asRowMatrix(InputArrayOfArrays src, int rtype, double alpha=1, double beta=0) {
     // make sure the input data is a vector of matrices or vector of vector
-    if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) {
+    if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_ARRAY_MAT &&
+        src.kind() != _InputArray::STD_VECTOR_VECTOR) {
         String error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector<Mat>) or _InputArray::STD_VECTOR_VECTOR (a std::vector< std::vector<...> >).";
         CV_Error(Error::StsBadArg, error_message);
     }
@@ -1096,6 +1097,7 @@ void LDA::lda(InputArrayOfArrays _src, InputArray _lbls) {
 void LDA::compute(InputArrayOfArrays _src, InputArray _lbls) {
     switch(_src.kind()) {
     case _InputArray::STD_VECTOR_MAT:
+    case _InputArray::STD_ARRAY_MAT:
         lda(asRowMatrix(_src, CV_64FC1), _lbls);
         break;
     case _InputArray::MAT:
index 3b4b8bd..8b06193 100644 (file)
@@ -2579,7 +2579,7 @@ void cv::calcCovarMatrix( InputArray _src, OutputArray _covar, InputOutputArray
 {
     CV_INSTRUMENT_REGION()
 
-    if(_src.kind() == _InputArray::STD_VECTOR_MAT)
+    if(_src.kind() == _InputArray::STD_VECTOR_MAT || _src.kind() == _InputArray::STD_ARRAY_MAT)
     {
         std::vector<cv::Mat> src;
         _src.getMatVector(src);
index 2e479f7..edc4462 100644 (file)
@@ -1235,7 +1235,7 @@ Mat _InputArray::getMat_(int i) const
         return (Mat)*((const MatExpr*)obj);
     }
 
-    if( k == MATX )
+    if( k == MATX || k == STD_ARRAY )
     {
         CV_Assert( i < 0 );
         return Mat(sz, flags, obj);
@@ -1286,6 +1286,14 @@ Mat _InputArray::getMat_(int i) const
         return v[i];
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* v = (const Mat*)obj;
+        CV_Assert( 0 <= i && i < sz.height );
+
+        return v[i];
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
@@ -1381,7 +1389,7 @@ void _InputArray::getMatVector(std::vector<Mat>& mv) const
         return;
     }
 
-    if( k == MATX )
+    if( k == MATX || k == STD_ARRAY )
     {
         size_t n = sz.height, esz = CV_ELEM_SIZE(flags);
         mv.resize(n);
@@ -1436,6 +1444,17 @@ void _InputArray::getMatVector(std::vector<Mat>& mv) const
         return;
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* v = (const Mat*)obj;
+        size_t n = sz.height;
+        mv.resize(n);
+
+        for( size_t i = 0; i < n; i++ )
+            mv[i] = v[i];
+        return;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
@@ -1472,6 +1491,17 @@ void _InputArray::getUMatVector(std::vector<UMat>& umv) const
         return;
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* v = (const Mat*)obj;
+        size_t n = sz.height;
+        umv.resize(n);
+
+        for( size_t i = 0; i < n; i++ )
+            umv[i] = v[i].getUMat(accessFlags);
+        return;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& v = *(const std::vector<UMat>*)obj;
@@ -1584,7 +1614,7 @@ Size _InputArray::size(int i) const
         return ((const UMat*)obj)->size();
     }
 
-    if( k == MATX )
+    if( k == MATX || k == STD_ARRAY )
     {
         CV_Assert( i < 0 );
         return sz;
@@ -1631,6 +1661,16 @@ Size _InputArray::size(int i) const
         return vv[i].size();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( i < 0 )
+            return sz.height==0 ? Size() : Size(sz.height, 1);
+        CV_Assert( i < sz.height );
+
+        return vv[i].size();
+    }
+
     if (k == STD_VECTOR_CUDA_GPU_MAT)
     {
         const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
@@ -1709,6 +1749,16 @@ int _InputArray::sizend(int* arrsz, int i) const
             for(j = 0; j < d; j++)
                 arrsz[j] = m.size.p[j];
     }
+    else if( k == STD_ARRAY_MAT && i >= 0 )
+    {
+        const Mat* vv = (const Mat*)obj;
+        CV_Assert( i < sz.height );
+        const Mat& m = vv[i];
+        d = m.dims;
+        if(arrsz)
+            for(j = 0; j < d; j++)
+                arrsz[j] = m.size.p[j];
+    }
     else if( k == STD_VECTOR_UMAT && i >= 0 )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -1789,7 +1839,7 @@ int _InputArray::dims(int i) const
         return ((const UMat*)obj)->dims;
     }
 
-    if( k == MATX )
+    if( k == MATX || k == STD_ARRAY )
     {
         CV_Assert( i < 0 );
         return 2;
@@ -1823,6 +1873,16 @@ int _InputArray::dims(int i) const
         return vv[i].dims;
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( i < 0 )
+            return 1;
+        CV_Assert( i < sz.height );
+
+        return vv[i].dims;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -1881,6 +1941,15 @@ size_t _InputArray::total(int i) const
         return vv[i].total();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( i < 0 )
+            return sz.height;
+
+        CV_Assert( i < sz.height );
+        return vv[i].total();
+    }
 
     if( k == STD_VECTOR_UMAT )
     {
@@ -1908,7 +1977,7 @@ int _InputArray::type(int i) const
     if( k == EXPR )
         return ((const MatExpr*)obj)->type();
 
-    if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
+    if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
         return CV_MAT_TYPE(flags);
 
     if( k == NONE )
@@ -1938,6 +2007,18 @@ int _InputArray::type(int i) const
         return vv[i >= 0 ? i : 0].type();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( sz.height == 0 )
+        {
+            CV_Assert((flags & FIXED_TYPE) != 0);
+            return CV_MAT_TYPE(flags);
+        }
+        CV_Assert( i < sz.height );
+        return vv[i >= 0 ? i : 0].type();
+    }
+
     if (k == STD_VECTOR_CUDA_GPU_MAT)
     {
         const std::vector<cuda::GpuMat>& vv = *(const std::vector<cuda::GpuMat>*)obj;
@@ -1986,7 +2067,7 @@ bool _InputArray::empty() const
     if( k == EXPR )
         return false;
 
-    if( k == MATX )
+    if( k == MATX || k == STD_ARRAY )
         return false;
 
     if( k == STD_VECTOR )
@@ -2016,6 +2097,11 @@ bool _InputArray::empty() const
         return vv.empty();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        return sz.height == 0;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -2051,7 +2137,7 @@ bool _InputArray::isContinuous(int i) const
     if( k == UMAT )
         return i < 0 ? ((const UMat*)obj)->isContinuous() : true;
 
-    if( k == EXPR || k == MATX || k == STD_VECTOR ||
+    if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
         k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
         return true;
 
@@ -2062,6 +2148,13 @@ bool _InputArray::isContinuous(int i) const
         return vv[i].isContinuous();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        CV_Assert(i < sz.height);
+        return vv[i].isContinuous();
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -2086,7 +2179,7 @@ bool _InputArray::isSubmatrix(int i) const
     if( k == UMAT )
         return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false;
 
-    if( k == EXPR || k == MATX || k == STD_VECTOR ||
+    if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
         k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
         return false;
 
@@ -2097,6 +2190,13 @@ bool _InputArray::isSubmatrix(int i) const
         return vv[i].isSubmatrix();
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        CV_Assert(i < sz.height);
+        return vv[i].isSubmatrix();
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -2125,7 +2225,7 @@ size_t _InputArray::offset(int i) const
         return ((const UMat*)obj)->offset;
     }
 
-    if( k == EXPR || k == MATX || k == STD_VECTOR ||
+    if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
         k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
         return 0;
 
@@ -2139,6 +2239,15 @@ size_t _InputArray::offset(int i) const
         return (size_t)(vv[i].ptr() - vv[i].datastart);
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( i < 0 )
+            return 1;
+        CV_Assert( i < sz.height );
+        return (size_t)(vv[i].ptr() - vv[i].datastart);
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -2180,7 +2289,7 @@ size_t _InputArray::step(int i) const
         return ((const UMat*)obj)->step;
     }
 
-    if( k == EXPR || k == MATX || k == STD_VECTOR ||
+    if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY ||
         k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR )
         return 0;
 
@@ -2193,6 +2302,15 @@ size_t _InputArray::step(int i) const
         return vv[i].step;
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        const Mat* vv = (const Mat*)obj;
+        if( i < 0 )
+            return 1;
+        CV_Assert( i < sz.height );
+        return vv[i].step;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
@@ -2222,7 +2340,7 @@ void _InputArray::copyTo(const _OutputArray& arr) const
 
     if( k == NONE )
         arr.release();
-    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
+    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_BOOL_VECTOR )
     {
         Mat m = getMat();
         m.copyTo(arr);
@@ -2247,7 +2365,7 @@ void _InputArray::copyTo(const _OutputArray& arr, const _InputArray & mask) cons
 
     if( k == NONE )
         arr.release();
-    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_BOOL_VECTOR )
+    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_BOOL_VECTOR )
     {
         Mat m = getMat();
         m.copyTo(arr, mask);
@@ -2436,6 +2554,14 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
         return;
     }
 
+    if( k == STD_ARRAY )
+    {
+        int type0 = CV_MAT_TYPE(flags);
+        CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
+        CV_Assert( d == 2 && sz.area() == sizes[0]*sizes[1]);
+        return;
+    }
+
     if( k == STD_VECTOR || k == STD_VECTOR_VECTOR )
     {
         CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
@@ -2583,6 +2709,65 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i,
         return;
     }
 
+    if( k == STD_ARRAY_MAT )
+    {
+        Mat* v = (Mat*)obj;
+
+        if( i < 0 )
+        {
+            CV_Assert( d == 2 && (sizes[0] == 1 || sizes[1] == 1 || sizes[0]*sizes[1] == 0) );
+            size_t len = sizes[0]*sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0, len0 = sz.height;
+
+            CV_Assert(len == len0);
+            if( fixedType() )
+            {
+                int _type = CV_MAT_TYPE(flags);
+                for( size_t j = len0; j < len; j++ )
+                {
+                    if( v[j].type() == _type )
+                        continue;
+                    CV_Assert( v[j].empty() );
+                    v[j].flags = (v[j].flags & ~CV_MAT_TYPE_MASK) | _type;
+                }
+            }
+            return;
+        }
+
+        CV_Assert( i < sz.height );
+        Mat& m = v[i];
+
+        if( allowTransposed )
+        {
+            if( !m.isContinuous() )
+            {
+                CV_Assert(!fixedType() && !fixedSize());
+                m.release();
+            }
+
+            if( d == 2 && m.dims == 2 && m.data &&
+                m.type() == mtype && m.rows == sizes[1] && m.cols == sizes[0] )
+                return;
+        }
+
+        if(fixedType())
+        {
+            if(CV_MAT_CN(mtype) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
+                mtype = m.type();
+            else
+                CV_Assert(CV_MAT_TYPE(mtype) == m.type());
+        }
+
+        if(fixedSize())
+        {
+            CV_Assert(m.dims == d);
+            for(int j = 0; j < d; ++j)
+                CV_Assert(m.size[j] == sizes[j]);
+        }
+
+        m.create(d, sizes, mtype);
+        return;
+    }
+
     if( k == STD_VECTOR_UMAT )
     {
         std::vector<UMat>& v = *(std::vector<UMat>*)obj;
@@ -2748,13 +2933,21 @@ Mat& _OutputArray::getMatRef(int i) const
         CV_Assert( k == MAT );
         return *(Mat*)obj;
     }
-    else
+
+    CV_Assert( k == STD_VECTOR_MAT || k == STD_ARRAY_MAT );
+
+    if( k == STD_VECTOR_MAT )
     {
-        CV_Assert( k == STD_VECTOR_MAT );
         std::vector<Mat>& v = *(std::vector<Mat>*)obj;
         CV_Assert( i < (int)v.size() );
         return v[i];
     }
+    else
+    {
+        Mat* v = (Mat*)obj;
+        CV_Assert( 0 <= i && i < sz.height );
+        return v[i];
+    }
 }
 
 UMat& _OutputArray::getUMatRef(int i) const
@@ -2807,7 +3000,7 @@ void _OutputArray::setTo(const _InputArray& arr, const _InputArray & mask) const
 
     if( k == NONE )
         ;
-    else if( k == MAT || k == MATX || k == STD_VECTOR )
+    else if( k == MAT || k == MATX || k == STD_VECTOR || k == STD_ARRAY )
     {
         Mat m = getMat();
         m.setTo(arr, mask);
index 98ce812..7f2451e 100644 (file)
@@ -1634,3 +1634,95 @@ TEST(Mat, regression_7873_mat_vector_initialize)
     ASSERT_EQ(3, sub_mat.size[1]);
     ASSERT_EQ(2, sub_mat.size[2]);
 }
+
+#ifdef CV_CXX_STD_ARRAY
+TEST(Core_Mat_array, outputArray_create_getMat)
+{
+    cv::Mat_<uchar> src_base(5, 1);
+    std::array<uchar, 5> dst8;
+
+    src_base << 1, 2, 3, 4, 5;
+
+    Mat src(src_base);
+    OutputArray _dst(dst8);
+
+    {
+        _dst.create(src.rows, src.cols, src.type());
+        Mat dst = _dst.getMat();
+        EXPECT_EQ(src.dims, dst.dims);
+        EXPECT_EQ(src.cols, dst.cols);
+        EXPECT_EQ(src.rows, dst.rows);
+    }
+}
+
+TEST(Core_Mat_array, copyTo_roi_column)
+{
+    cv::Mat_<uchar> src_base(5, 2);
+
+    src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
+
+    Mat src_full(src_base);
+    Mat src(src_full.col(0));
+
+    std::array<uchar, 5> dst1;
+    src.copyTo(dst1);
+    std::cout << "src = " << src << std::endl;
+    std::cout << "dst = " << Mat(dst1) << std::endl;
+    EXPECT_EQ((size_t)5, dst1.size());
+    EXPECT_EQ(1, (int)dst1[0]);
+    EXPECT_EQ(3, (int)dst1[1]);
+    EXPECT_EQ(5, (int)dst1[2]);
+    EXPECT_EQ(7, (int)dst1[3]);
+    EXPECT_EQ(9, (int)dst1[4]);
+}
+
+TEST(Core_Mat_array, copyTo_roi_row)
+{
+    cv::Mat_<uchar> src_base(2, 5);
+    std::array<uchar, 5> dst1;
+
+    src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
+
+    Mat src_full(src_base);
+    Mat src(src_full.row(0));
+    OutputArray _dst(dst1);
+    {
+        _dst.create(5, 1, src.type());
+        Mat dst = _dst.getMat();
+        EXPECT_EQ(src.dims, dst.dims);
+        EXPECT_EQ(1, dst.cols);
+        EXPECT_EQ(5, dst.rows);
+    }
+
+    std::array<uchar, 5> dst2;
+    src.copyTo(dst2);
+    std::cout << "src = " << src << std::endl;
+    std::cout << "dst = " << Mat(dst2) << std::endl;
+    EXPECT_EQ(1, (int)dst2[0]);
+    EXPECT_EQ(2, (int)dst2[1]);
+    EXPECT_EQ(3, (int)dst2[2]);
+    EXPECT_EQ(4, (int)dst2[3]);
+    EXPECT_EQ(5, (int)dst2[4]);
+}
+
+TEST(Core_Mat_array, SplitMerge)
+{
+    std::array<cv::Mat, 3> src;
+    for(size_t i=0; i<src.size(); ++i) {
+        src[i].create(10, 10, CV_8U);
+        src[i] = 127 * i;
+    }
+
+    Mat merged;
+    merge(src, merged);
+
+    std::array<cv::Mat, 3> dst;
+    split(merged, dst);
+
+    Mat diff;
+    for(size_t i=0; i<dst.size(); ++i) {
+        absdiff(src[i], dst[i], diff);
+        EXPECT_EQ(0, countNonZero(diff));
+    }
+}
+#endif
\ No newline at end of file