From 636ab095b0dda4f63da71e681e47d5e69e6be6b7 Mon Sep 17 00:00:00 2001 From: Arnaud Brejeon Date: Wed, 19 Apr 2017 03:13:39 -0700 Subject: [PATCH] Merge pull request #8535 from arnaudbrejeon:std_array Add support for std::array (#8535) * Add support for std::array * Add std::array support * Remove UMat constructor with std::array parameter --- modules/core/include/opencv2/core/cvdef.h | 15 ++ modules/core/include/opencv2/core/mat.hpp | 45 +++- modules/core/include/opencv2/core/mat.inl.hpp | 101 +++++++- modules/core/src/convert.cpp | 4 + modules/core/src/lda.cpp | 4 +- modules/core/src/matmul.cpp | 2 +- modules/core/src/matrix.cpp | 223 ++++++++++++++++-- modules/core/test/test_mat.cpp | 92 ++++++++ 8 files changed, 466 insertions(+), 20 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 43f8a02a72..a0c3438116 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -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 +# endif +#else +# if CV_CXX_STD_ARRAY == 0 +# undef CV_CXX_STD_ARRAY +# endif +#endif + //! @} #endif // OPENCV_CORE_CVDEF_H diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index e3a24032d0..0a74e72817 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -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& umv); +#ifdef CV_CXX_STD_ARRAY + template _InputArray(const std::array<_Tp, _N>& arr); + template _InputArray(const std::array& 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& vec); +#ifdef CV_CXX_STD_ARRAY + template _OutputArray(std::array<_Tp, _N>& arr); + template _OutputArray(const std::array<_Tp, _N>& arr); + template _OutputArray(std::array& arr); + template _OutputArray(const std::array& arr); +#endif + bool fixedSize() const; bool fixedType() const; bool needed() const; @@ -374,6 +388,14 @@ public: template _InputOutputArray(const Matx<_Tp, m, n>& matx); _InputOutputArray(const UMat& m); _InputOutputArray(const std::vector& vec); + +#ifdef CV_CXX_STD_ARRAY + template _InputOutputArray(std::array<_Tp, _N>& arr); + template _InputOutputArray(const std::array<_Tp, _N>& arr); + template _InputOutputArray(std::array& arr); + template _InputOutputArray(const std::array& arr); +#endif + }; typedef const _InputArray& InputArray; @@ -955,6 +977,12 @@ public: */ template explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); +#ifdef CV_CXX_STD_ARRAY + /** @overload + */ + template explicit Mat(const std::array<_Tp, _N>& arr, bool copyData=false); +#endif + /** @overload */ template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); @@ -1575,6 +1603,10 @@ public: template operator Vec<_Tp, n>() const; template operator Matx<_Tp, m, n>() const; +#ifdef CV_CXX_STD_ARRAY + template 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_::channel_type>& pt, bool copyData=true); explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); +#ifdef CV_CXX_STD_ARRAY + template 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 operator std::array<_Tp, _N>() const; +#endif + //! conversion to Vec template operator Vec::channel_type, n>() const; //! conversion to Matx @@ -2281,6 +2323,7 @@ public: UMat(const UMat& m, const std::vector& ranges); //! builds matrix from std::vector with or without copying the data template explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default template explicit UMat(const Vec<_Tp, n>& vec, bool copyData=true); //! builds matrix from cv::Matx; the data is copied by default diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index aa746e8807..399c92220d 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -77,6 +77,16 @@ template 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 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 inline +_InputArray::_InputArray(const std::array& arr) +{ init(STD_ARRAY_MAT + ACCESS_READ, arr.data(), Size(1, _N)); } +#endif + inline _InputArray::_InputArray(const std::vector& vec) { init(FIXED_TYPE + STD_BOOL_VECTOR + DataType::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 inline _OutputArray::_OutputArray(std::vector<_Tp>& vec) { init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } +#ifdef CV_CXX_STD_ARRAY +template 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 inline +_OutputArray::_OutputArray(std::array& arr) +{ init(STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _N)); } +#endif + inline _OutputArray::_OutputArray(std::vector&) { CV_Error(Error::StsUnsupportedFormat, "std::vector cannot be an output array\n"); } @@ -177,6 +199,16 @@ template 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 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 inline +_OutputArray::_OutputArray(const std::array& arr) +{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _N)); } +#endif + template inline _OutputArray::_OutputArray(const std::vector >& vec) { init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } @@ -244,6 +276,16 @@ template inline _InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec) { init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); } +#ifdef CV_CXX_STD_ARRAY +template 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 inline +_InputOutputArray::_InputOutputArray(std::array& arr) +{ init(STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _N)); } +#endif + inline _InputOutputArray::_InputOutputArray(std::vector&) { CV_Error(Error::StsUnsupportedFormat, "std::vector cannot be an input/output array\n"); } @@ -271,6 +313,16 @@ template 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 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 inline +_InputOutputArray::_InputOutputArray(const std::array& arr) +{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _N)); } +#endif + template inline _InputOutputArray::_InputOutputArray(const std::vector >& 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 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 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 inline +Mat::operator std::array<_Tp, _N>() const +{ + std::array<_Tp, _N> v; + copyTo(v); + return v; +} +#endif + template 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 template inline +Mat_<_Tp>::Mat_(const std::array<_Tp, _N>& arr, bool copyData) + : Mat(arr, copyData) +{} +#endif + template 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 template inline +Mat_<_Tp>::operator std::array<_Tp, _N>() const +{ + std::array<_Tp, _N> a; + copyTo(a); + return a; +} +#endif + template template inline Mat_<_Tp>::operator Vec::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) { diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 6c060f9c9c..8d3c242659 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -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; diff --git a/modules/core/src/lda.cpp b/modules/core/src/lda.cpp index 4ccbf8a834..a706eeb3fe 100644 --- a/modules/core/src/lda.cpp +++ b/modules/core/src/lda.cpp @@ -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) 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: diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 3b4b8bd1ad..8b06193cf6 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -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 src; _src.getMatVector(src); diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2e479f7c56..edc4462d20 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -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& v = *(const std::vector*)obj; @@ -1381,7 +1389,7 @@ void _InputArray::getMatVector(std::vector& 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& 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& v = *(const std::vector*)obj; @@ -1472,6 +1491,17 @@ void _InputArray::getUMatVector(std::vector& 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& v = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& vv = *(const std::vector*)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& v = *(std::vector*)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& v = *(std::vector*)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); diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 98ce812ee9..7f2451e842 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -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_ src_base(5, 1); + std::array 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_ 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 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_ src_base(2, 5); + std::array 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 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 src; + for(size_t i=0; i dst; + split(merged, dst); + + Mat diff; + for(size_t i=0; i