Commit 636ab095 authored by Arnaud Brejeon's avatar Arnaud Brejeon Committed by Alexander Alekhin

Merge pull request #8535 from arnaudbrejeon:std_array

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
parent 2922738b
......@@ -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
......@@ -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
......
......@@ -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)
{
......
......@@ -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;
......
......@@ -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:
......
......@@ -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);
......
This diff is collapsed.
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment