Commit bfaae7dd authored by Andrey Kamaev's avatar Andrey Kamaev

Input/Output arrays are updated to support fixed-type and fixed-size semantic…

Input/Output arrays are updated to support fixed-type and fixed-size semantic for all compatible types
parent e778007d
...@@ -1283,6 +1283,10 @@ class CV_EXPORTS _InputArray ...@@ -1283,6 +1283,10 @@ class CV_EXPORTS _InputArray
public: public:
enum { enum {
KIND_SHIFT = 16, KIND_SHIFT = 16,
FIXED_TYPE = 0x8000 << KIND_SHIFT,
FIXED_SIZE = 0x4000 << KIND_SHIFT,
KIND_MASK = ~(FIXED_TYPE|FIXED_SIZE) - (1 << KIND_SHIFT) + 1,
NONE = 0 << KIND_SHIFT, NONE = 0 << KIND_SHIFT,
MAT = 1 << KIND_SHIFT, MAT = 1 << KIND_SHIFT,
MATX = 2 << KIND_SHIFT, MATX = 2 << KIND_SHIFT,
...@@ -1301,6 +1305,7 @@ public: ...@@ -1301,6 +1305,7 @@ public:
template<typename _Tp> _InputArray(const vector<_Tp>& vec); template<typename _Tp> _InputArray(const vector<_Tp>& vec);
template<typename _Tp> _InputArray(const vector<vector<_Tp> >& vec); template<typename _Tp> _InputArray(const vector<vector<_Tp> >& vec);
_InputArray(const vector<Mat>& vec); _InputArray(const vector<Mat>& vec);
template<typename _Tp> _InputArray(const Mat_<_Tp>& m);
template<typename _Tp, int m, int n> _InputArray(const Matx<_Tp, m, n>& matx); template<typename _Tp, int m, int n> _InputArray(const Matx<_Tp, m, n>& matx);
_InputArray(const Scalar& s); _InputArray(const Scalar& s);
_InputArray(const double& val); _InputArray(const double& val);
...@@ -1350,17 +1355,28 @@ class CV_EXPORTS _OutputArray : public _InputArray ...@@ -1350,17 +1355,28 @@ class CV_EXPORTS _OutputArray : public _InputArray
{ {
public: public:
_OutputArray(); _OutputArray();
_OutputArray(Mat& m); _OutputArray(Mat& m);
template<typename _Tp> _OutputArray(vector<_Tp>& vec); template<typename _Tp> _OutputArray(vector<_Tp>& vec);
template<typename _Tp> _OutputArray(vector<vector<_Tp> >& vec); template<typename _Tp> _OutputArray(vector<vector<_Tp> >& vec);
_OutputArray(vector<Mat>& vec); _OutputArray(vector<Mat>& vec);
template<typename _Tp> _OutputArray(Mat_<_Tp>& m);
template<typename _Tp, int m, int n> _OutputArray(Matx<_Tp, m, n>& matx); template<typename _Tp, int m, int n> _OutputArray(Matx<_Tp, m, n>& matx);
template<typename _Tp> _OutputArray(_Tp* vec, int n); template<typename _Tp> _OutputArray(_Tp* vec, int n);
_OutputArray(const Mat& m);
template<typename _Tp> _OutputArray(const vector<_Tp>& vec);
template<typename _Tp> _OutputArray(const vector<vector<_Tp> >& vec);
_OutputArray(const vector<Mat>& vec);
template<typename _Tp> _OutputArray(const Mat_<_Tp>& m);
template<typename _Tp, int m, int n> _OutputArray(const Matx<_Tp, m, n>& matx);
template<typename _Tp> _OutputArray(const _Tp* vec, int n);
virtual bool fixedSize() const; virtual bool fixedSize() const;
virtual bool fixedType() const; virtual bool fixedType() const;
virtual bool needed() const; virtual bool needed() const;
virtual Mat& getMatRef(int i=-1) const; virtual Mat& getMatRef(int i=-1) const;
virtual void create(Size sz, int type, int i=-1, bool allocateVector=false, int fixedDepthMask=0) const; virtual void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; virtual void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; virtual void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const;
virtual void release() const; virtual void release() const;
......
...@@ -1124,25 +1124,36 @@ process( const Mat_<T1>& m1, const Mat_<T2>& m2, Mat_<T3>& m3, Op op ) ...@@ -1124,25 +1124,36 @@ process( const Mat_<T1>& m1, const Mat_<T2>& m2, Mat_<T3>& m3, Op op )
/////////////////////////////// Input/Output Arrays ///////////////////////////////// /////////////////////////////// Input/Output Arrays /////////////////////////////////
template<typename _Tp> inline _InputArray::_InputArray(const vector<_Tp>& vec) template<typename _Tp> inline _InputArray::_InputArray(const vector<_Tp>& vec)
: flags(STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} : flags(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
template<typename _Tp> inline _InputArray::_InputArray(const vector<vector<_Tp> >& vec) template<typename _Tp> inline _InputArray::_InputArray(const vector<vector<_Tp> >& vec)
: flags(STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
template<typename _Tp, int m, int n> inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) template<typename _Tp, int m, int n> inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx)
: flags(MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {} : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {}
template<typename _Tp> inline _InputArray::_InputArray(const _Tp* vec, int n) template<typename _Tp> inline _InputArray::_InputArray(const _Tp* vec, int n)
: flags(MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {} : flags(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {}
inline _InputArray::_InputArray(const Scalar& s) inline _InputArray::_InputArray(const Scalar& s)
: flags(MATX + CV_64F), obj((void*)&s), sz(1, 4) {} : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&s), sz(1, 4) {}
template<typename _Tp> inline _InputArray::_InputArray(const Mat_<_Tp>& m)
: flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) {}
template<typename _Tp> inline _OutputArray::_OutputArray(vector<_Tp>& vec) : _InputArray(vec) {} template<typename _Tp> inline _OutputArray::_OutputArray(vector<_Tp>& vec) : _InputArray(vec) {}
template<typename _Tp> inline _OutputArray::_OutputArray(vector<vector<_Tp> >& vec) : _InputArray(vec) {} template<typename _Tp> inline _OutputArray::_OutputArray(vector<vector<_Tp> >& vec) : _InputArray(vec) {}
template<typename _Tp> inline _OutputArray::_OutputArray(Mat_<_Tp>& m) : _InputArray(m) {}
template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {} template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {}
template<typename _Tp> inline _OutputArray::_OutputArray(_Tp* vec, int n) : _InputArray(vec, n) {} template<typename _Tp> inline _OutputArray::_OutputArray(_Tp* vec, int n) : _InputArray(vec, n) {}
template<typename _Tp> inline _OutputArray::_OutputArray(const vector<_Tp>& vec) : _InputArray(vec) {flags |= FIXED_SIZE;}
template<typename _Tp> inline _OutputArray::_OutputArray(const vector<vector<_Tp> >& vec) : _InputArray(vec) {flags |= FIXED_SIZE;}
template<typename _Tp> inline _OutputArray::_OutputArray(const Mat_<_Tp>& m) : _InputArray(m) {flags |= FIXED_SIZE;}
template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {}
template<typename _Tp> inline _OutputArray::_OutputArray(const _Tp* vec, int n) : _InputArray(vec, n) {}
//////////////////////////////////// Matrix Expressions ///////////////////////////////////////// //////////////////////////////////// Matrix Expressions /////////////////////////////////////////
class CV_EXPORTS MatOp class CV_EXPORTS MatOp
......
...@@ -888,10 +888,10 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) ...@@ -888,10 +888,10 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
_InputArray::_InputArray() : flags(0), obj(0) {} _InputArray::_InputArray() : flags(0), obj(0) {}
_InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {} _InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {}
_InputArray::_InputArray(const vector<Mat>& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {} _InputArray::_InputArray(const vector<Mat>& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {}
_InputArray::_InputArray(const double& val) : flags(MATX+CV_64F), obj((void*)&val), sz(Size(1,1)) {} _InputArray::_InputArray(const double& val) : flags(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F), obj((void*)&val), sz(Size(1,1)) {}
_InputArray::_InputArray(const MatExpr& expr) : flags(EXPR), obj((void*)&expr) {} _InputArray::_InputArray(const MatExpr& expr) : flags(FIXED_TYPE + FIXED_SIZE + EXPR), obj((void*)&expr) {}
_InputArray::_InputArray(const GlBuffer& buf) : flags(OPENGL_BUFFER), obj((void*)&buf) {} _InputArray::_InputArray(const GlBuffer& buf) : flags(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER), obj((void*)&buf) {}
_InputArray::_InputArray(const GlTexture& tex) : flags(OPENGL_TEXTURE), obj((void*)&tex) {} _InputArray::_InputArray(const GlTexture& tex) : flags(FIXED_TYPE + FIXED_SIZE + OPENGL_TEXTURE), obj((void*)&tex) {}
_InputArray::_InputArray(const gpu::GpuMat& d_mat) : flags(GPU_MAT), obj((void*)&d_mat) {} _InputArray::_InputArray(const gpu::GpuMat& d_mat) : flags(GPU_MAT), obj((void*)&d_mat) {}
Mat _InputArray::getMat(int i) const Mat _InputArray::getMat(int i) const
...@@ -1070,7 +1070,7 @@ gpu::GpuMat _InputArray::getGpuMat() const ...@@ -1070,7 +1070,7 @@ gpu::GpuMat _InputArray::getGpuMat() const
int _InputArray::kind() const int _InputArray::kind() const
{ {
return flags & -(1 << KIND_SHIFT); return flags & KIND_MASK;
} }
Size _InputArray::size(int i) const Size _InputArray::size(int i) const
...@@ -1252,16 +1252,18 @@ _OutputArray::_OutputArray() {} ...@@ -1252,16 +1252,18 @@ _OutputArray::_OutputArray() {}
_OutputArray::_OutputArray(Mat& m) : _InputArray(m) {} _OutputArray::_OutputArray(Mat& m) : _InputArray(m) {}
_OutputArray::_OutputArray(vector<Mat>& vec) : _InputArray(vec) {} _OutputArray::_OutputArray(vector<Mat>& vec) : _InputArray(vec) {}
_OutputArray::_OutputArray(const Mat& m) : _InputArray(m) {flags |= FIXED_SIZE|FIXED_TYPE;}
_OutputArray::_OutputArray(const vector<Mat>& vec) : _InputArray(vec) {flags |= FIXED_SIZE;}
bool _OutputArray::fixedSize() const bool _OutputArray::fixedSize() const
{ {
int k = kind(); return (flags & FIXED_SIZE) == FIXED_SIZE;
return k == MATX;
} }
bool _OutputArray::fixedType() const bool _OutputArray::fixedType() const
{ {
int k = kind(); return (flags & FIXED_TYPE) == FIXED_TYPE;
return k != MAT && k != STD_VECTOR_MAT;
} }
void _OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int fixedDepthMask) const void _OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int fixedDepthMask) const
...@@ -1269,6 +1271,8 @@ void _OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int f ...@@ -1269,6 +1271,8 @@ void _OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int f
int k = kind(); int k = kind();
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{ {
CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == _sz);
CV_Assert(!fixedType() || ((Mat*)obj)->type() == type);
((Mat*)obj)->create(_sz, type); ((Mat*)obj)->create(_sz, type);
return; return;
} }
...@@ -1281,6 +1285,8 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo ...@@ -1281,6 +1285,8 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo
int k = kind(); int k = kind();
if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 )
{ {
CV_Assert(!fixedSize() || ((Mat*)obj)->size.operator()() == Size(cols, rows));
CV_Assert(!fixedType() || ((Mat*)obj)->type() == type);
((Mat*)obj)->create(rows, cols, type); ((Mat*)obj)->create(rows, cols, type);
return; return;
} }
...@@ -1288,7 +1294,7 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo ...@@ -1288,7 +1294,7 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo
create(2, sz, type, i, allowTransposed, fixedDepthMask); create(2, sz, type, i, allowTransposed, fixedDepthMask);
} }
void _OutputArray::create(int dims, const int* size, int type, int i, bool allocateVector, int fixedDepthMask) const void _OutputArray::create(int dims, const int* size, int type, int i, bool allowTransposed, int fixedDepthMask) const
{ {
int k = kind(); int k = kind();
type = CV_MAT_TYPE(type); type = CV_MAT_TYPE(type);
...@@ -1297,15 +1303,32 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1297,15 +1303,32 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
{ {
CV_Assert( i < 0 ); CV_Assert( i < 0 );
Mat& m = *(Mat*)obj; Mat& m = *(Mat*)obj;
if( allocateVector ) if( allowTransposed )
{ {
if( !m.isContinuous() ) if( !m.isContinuous() )
{
CV_Assert(!fixedType() && !fixedSize());
m.release(); m.release();
}
if( dims == 2 && m.dims == 2 && m.data && if( dims == 2 && m.dims == 2 && m.data &&
m.type() == type && m.rows == size[1] && m.cols == size[0] ) m.type() == type && m.rows == size[1] && m.cols == size[0] )
return; return;
} }
if(fixedType())
{
if(CV_MAT_CN(type) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
type = m.type();
else
CV_Assert(!fixedType() || (CV_MAT_CN(type) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0));
}
if(fixedSize())
{
CV_Assert(m.dims == dims);
for(int j = 0; j < dims; ++j)
CV_Assert(m.size[j] == size[j]);
}
m.create(dims, size, type); m.create(dims, size, type);
return; return;
} }
...@@ -1316,7 +1339,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1316,7 +1339,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
int type0 = CV_MAT_TYPE(flags); int type0 = CV_MAT_TYPE(flags);
CV_Assert( type == type0 || (CV_MAT_CN(type) == 1 && ((1 << type0) & fixedDepthMask) != 0) ); CV_Assert( type == type0 || (CV_MAT_CN(type) == 1 && ((1 << type0) & fixedDepthMask) != 0) );
CV_Assert( dims == 2 && ((size[0] == sz.height && size[1] == sz.width) || CV_Assert( dims == 2 && ((size[0] == sz.height && size[1] == sz.width) ||
(allocateVector && size[0] == sz.width && size[1] == sz.height))); (allowTransposed && size[0] == sz.width && size[1] == sz.height)));
return; return;
} }
...@@ -1331,6 +1354,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1331,6 +1354,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
vector<vector<uchar> >& vv = *(vector<vector<uchar> >*)obj; vector<vector<uchar> >& vv = *(vector<vector<uchar> >*)obj;
if( i < 0 ) if( i < 0 )
{ {
CV_Assert(!fixedSize() || len == vv.size());
vv.resize(len); vv.resize(len);
return; return;
} }
...@@ -1344,6 +1368,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1344,6 +1368,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
CV_Assert( type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) ); CV_Assert( type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) );
int esz = CV_ELEM_SIZE(type0); int esz = CV_ELEM_SIZE(type0);
CV_Assert(!fixedSize() || len == ((vector<uchar>*)v)->size() / esz);
switch( esz ) switch( esz )
{ {
case 1: case 1:
...@@ -1416,6 +1441,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1416,6 +1441,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) ); CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) );
size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0; size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0;
CV_Assert(!fixedSize() || len == v.size());
v.resize(len); v.resize(len);
return; return;
} }
...@@ -1423,21 +1449,41 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc ...@@ -1423,21 +1449,41 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc
CV_Assert( i < (int)v.size() ); CV_Assert( i < (int)v.size() );
Mat& m = v[i]; Mat& m = v[i];
if( allocateVector ) if( allowTransposed )
{ {
if( !m.isContinuous() ) if( !m.isContinuous() )
{
CV_Assert(!fixedType() && !fixedSize());
m.release(); m.release();
}
if( dims == 2 && m.dims == 2 && m.data && if( dims == 2 && m.dims == 2 && m.data &&
m.type() == type && m.rows == size[1] && m.cols == size[0] ) m.type() == type && m.rows == size[1] && m.cols == size[0] )
return; return;
} }
if(fixedType())
{
if(CV_MAT_CN(type) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0 )
type = m.type();
else
CV_Assert(!fixedType() || (CV_MAT_CN(type) == m.channels() && ((1 << CV_MAT_TYPE(flags)) & fixedDepthMask) != 0));
}
if(fixedSize())
{
CV_Assert(m.dims == dims);
for(int j = 0; j < dims; ++j)
CV_Assert(m.size[j] == size[j]);
}
m.create(dims, size, type); m.create(dims, size, type);
} }
} }
void _OutputArray::release() const void _OutputArray::release() const
{ {
CV_Assert(!fixedSize());
int k = kind(); int k = kind();
if( k == MAT ) if( k == MAT )
...@@ -1474,6 +1520,7 @@ void _OutputArray::clear() const ...@@ -1474,6 +1520,7 @@ void _OutputArray::clear() const
if( k == MAT ) if( k == MAT )
{ {
CV_Assert(!fixedSize());
((Mat*)obj)->resize(0); ((Mat*)obj)->resize(0);
return; return;
} }
......
...@@ -822,3 +822,26 @@ TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); } ...@@ -822,3 +822,26 @@ TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); } TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
TEST(Core_IOArray, submat_assignment)
{
Mat1f A = Mat1f::zeros(2,2);
Mat1f B = Mat1f::ones(1,3);
EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
EXPECT_EQ( 1.0f, A(0,0) );
EXPECT_EQ( 1.0f, A(0,1) );
}
void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
TEST(Core_IOArray, submat_create)
{
Mat1f A = Mat1f::zeros(2,2);
EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
}
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