From bfaae7dd93878a5db5b75b787edeaadf6c53d8e6 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 26 Mar 2012 08:18:53 +0000 Subject: [PATCH] Input/Output arrays are updated to support fixed-type and fixed-size semantic for all compatible types --- modules/core/include/opencv2/core/core.hpp | 20 +++++++- modules/core/include/opencv2/core/mat.hpp | 21 +++++++-- modules/core/src/matrix.cpp | 73 ++++++++++++++++++++++++------ modules/core/test/test_mat.cpp | 23 ++++++++++ 4 files changed, 117 insertions(+), 20 deletions(-) diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 1c0e301..1e5cbfb 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -1282,7 +1282,11 @@ class CV_EXPORTS _InputArray { public: 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, MAT = 1 << KIND_SHIFT, MATX = 2 << KIND_SHIFT, @@ -1301,6 +1305,7 @@ public: template _InputArray(const vector<_Tp>& vec); template _InputArray(const vector >& vec); _InputArray(const vector& vec); + template _InputArray(const Mat_<_Tp>& m); template _InputArray(const Matx<_Tp, m, n>& matx); _InputArray(const Scalar& s); _InputArray(const double& val); @@ -1350,17 +1355,28 @@ class CV_EXPORTS _OutputArray : public _InputArray { public: _OutputArray(); + _OutputArray(Mat& m); template _OutputArray(vector<_Tp>& vec); template _OutputArray(vector >& vec); _OutputArray(vector& vec); + template _OutputArray(Mat_<_Tp>& m); template _OutputArray(Matx<_Tp, m, n>& matx); template _OutputArray(_Tp* vec, int n); + + _OutputArray(const Mat& m); + template _OutputArray(const vector<_Tp>& vec); + template _OutputArray(const vector >& vec); + _OutputArray(const vector& vec); + template _OutputArray(const Mat_<_Tp>& m); + template _OutputArray(const Matx<_Tp, m, n>& matx); + template _OutputArray(const _Tp* vec, int n); + virtual bool fixedSize() const; virtual bool fixedType() const; virtual bool needed() 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 dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; virtual void release() const; diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 658ae5b..ee3a3af 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -1124,24 +1124,35 @@ process( const Mat_& m1, const Mat_& m2, Mat_& m3, Op op ) /////////////////////////////// Input/Output Arrays ///////////////////////////////// template 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 inline _InputArray::_InputArray(const vector >& vec) - : flags(STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} + : flags(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} template 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 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) - : 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 inline _InputArray::_InputArray(const Mat_<_Tp>& m) + : flags(FIXED_TYPE + MAT + DataType<_Tp>::type), obj((void*)&m) {} template inline _OutputArray::_OutputArray(vector<_Tp>& vec) : _InputArray(vec) {} template inline _OutputArray::_OutputArray(vector >& vec) : _InputArray(vec) {} +template inline _OutputArray::_OutputArray(Mat_<_Tp>& m) : _InputArray(m) {} template inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {} template inline _OutputArray::_OutputArray(_Tp* vec, int n) : _InputArray(vec, n) {} + + +template inline _OutputArray::_OutputArray(const vector<_Tp>& vec) : _InputArray(vec) {flags |= FIXED_SIZE;} +template inline _OutputArray::_OutputArray(const vector >& vec) : _InputArray(vec) {flags |= FIXED_SIZE;} +template inline _OutputArray::_OutputArray(const Mat_<_Tp>& m) : _InputArray(m) {flags |= FIXED_SIZE;} +template inline _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {} +template inline _OutputArray::_OutputArray(const _Tp* vec, int n) : _InputArray(vec, n) {} //////////////////////////////////// Matrix Expressions ///////////////////////////////////////// diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 1c93f9e..c38ff2b 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -888,10 +888,10 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) _InputArray::_InputArray() : flags(0), obj(0) {} _InputArray::_InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {} _InputArray::_InputArray(const vector& 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 MatExpr& expr) : flags(EXPR), obj((void*)&expr) {} -_InputArray::_InputArray(const GlBuffer& buf) : flags(OPENGL_BUFFER), obj((void*)&buf) {} -_InputArray::_InputArray(const GlTexture& tex) : flags(OPENGL_TEXTURE), obj((void*)&tex) {} +_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(FIXED_TYPE + FIXED_SIZE + EXPR), obj((void*)&expr) {} +_InputArray::_InputArray(const GlBuffer& buf) : flags(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER), obj((void*)&buf) {} +_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) {} Mat _InputArray::getMat(int i) const @@ -1070,7 +1070,7 @@ gpu::GpuMat _InputArray::getGpuMat() const int _InputArray::kind() const { - return flags & -(1 << KIND_SHIFT); + return flags & KIND_MASK; } Size _InputArray::size(int i) const @@ -1251,17 +1251,19 @@ bool _InputArray::empty() const _OutputArray::_OutputArray() {} _OutputArray::_OutputArray(Mat& m) : _InputArray(m) {} _OutputArray::_OutputArray(vector& vec) : _InputArray(vec) {} + +_OutputArray::_OutputArray(const Mat& m) : _InputArray(m) {flags |= FIXED_SIZE|FIXED_TYPE;} +_OutputArray::_OutputArray(const vector& vec) : _InputArray(vec) {flags |= FIXED_SIZE;} + bool _OutputArray::fixedSize() const { - int k = kind(); - return k == MATX; + return (flags & FIXED_SIZE) == FIXED_SIZE; } bool _OutputArray::fixedType() const { - int k = kind(); - return k != MAT && k != STD_VECTOR_MAT; + return (flags & FIXED_TYPE) == FIXED_TYPE; } 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 int k = kind(); 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); return; } @@ -1281,6 +1285,8 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo int k = kind(); 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); return; } @@ -1288,7 +1294,7 @@ void _OutputArray::create(int rows, int cols, int type, int i, bool allowTranspo 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(); type = CV_MAT_TYPE(type); @@ -1297,15 +1303,32 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc { CV_Assert( i < 0 ); Mat& m = *(Mat*)obj; - if( allocateVector ) + if( allowTransposed ) { if( !m.isContinuous() ) + { + CV_Assert(!fixedType() && !fixedSize()); m.release(); + } if( dims == 2 && m.dims == 2 && m.data && m.type() == type && m.rows == size[1] && m.cols == size[0] ) 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); return; } @@ -1316,7 +1339,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc int type0 = CV_MAT_TYPE(flags); 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) || - (allocateVector && size[0] == sz.width && size[1] == sz.height))); + (allowTransposed && size[0] == sz.width && size[1] == sz.height))); return; } @@ -1331,6 +1354,7 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc vector >& vv = *(vector >*)obj; if( i < 0 ) { + CV_Assert(!fixedSize() || len == vv.size()); vv.resize(len); return; } @@ -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) ); int esz = CV_ELEM_SIZE(type0); + CV_Assert(!fixedSize() || len == ((vector*)v)->size() / esz); switch( esz ) { case 1: @@ -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) ); size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0; + CV_Assert(!fixedSize() || len == v.size()); v.resize(len); return; } @@ -1423,21 +1449,41 @@ void _OutputArray::create(int dims, const int* size, int type, int i, bool alloc CV_Assert( i < (int)v.size() ); Mat& m = v[i]; - if( allocateVector ) + if( allowTransposed ) { if( !m.isContinuous() ) + { + CV_Assert(!fixedType() && !fixedSize()); m.release(); + } if( dims == 2 && m.dims == 2 && m.data && m.type() == type && m.rows == size[1] && m.cols == size[0] ) 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); } } void _OutputArray::release() const { + CV_Assert(!fixedSize()); + int k = kind(); if( k == MAT ) @@ -1474,6 +1520,7 @@ void _OutputArray::clear() const if( k == MAT ) { + CV_Assert(!fixedSize()); ((Mat*)obj)->resize(0); return; } diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 1970876..e479a82 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -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_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 ); +} -- 2.7.4