From b7fca6d0589ed82c4c1188abc41a866f34cfbc90 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 13 Nov 2024 18:56:40 +0000 Subject: [PATCH 01/19] prepares OpenCV for the arrival of `_ArrayOps` This commit refactors the `init` functions into constructors, so that the incoming `_ArrayOps` member properly initialised. We add a pointer to an `_ArrayOps` object, but don't do anything with it just yet. --- modules/core/include/opencv2/core/mat.hpp | 46 +- modules/core/include/opencv2/core/mat.inl.hpp | 407 +++++++++++------- modules/core/src/matrix_expressions.cpp | 3 +- 3 files changed, 280 insertions(+), 176 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index d1cad11f5c5c..67343b8b5871 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -176,6 +176,7 @@ CV_EXPORTS bool operator != (const MatShape& shape1, const MatShape& shape2); CV__DEBUG_NS_BEGIN +struct CV_EXPORTS _ArrayOpsBase; class CV_EXPORTS _OutputArray; //////////////////////// Input/Output Array Arguments ///////////////////////////////// @@ -289,8 +290,8 @@ class CV_EXPORTS _InputArray STD_ARRAY_MAT =15 << KIND_SHIFT }; - _InputArray(); - _InputArray(int _flags, void* _obj); + _InputArray() = default; + template _InputArray(int flags, T* obj); _InputArray(const Mat& m); _InputArray(const MatExpr& expr); _InputArray(const std::vector& vec); @@ -359,15 +360,18 @@ class CV_EXPORTS _InputArray bool isVector() const; bool isGpuMat() const; bool isGpuMatVector() const; - ~_InputArray(); protected: - int flags; - void* obj; + int flags = static_cast(NONE); + void* obj = nullptr; Size sz; + const _ArrayOpsBase* ops = nullptr; + + template + _InputArray(int flags, T* obj, Size sz); - void init(int _flags, const void* _obj); - void init(int _flags, const void* _obj, Size _sz); + template + _InputArray(int flags, const T* obj, Size sz); }; CV_ENUM_FLAGS(_InputArray::KindFlag) __CV_ENUM_FLAGS_BITWISE_AND(_InputArray::KindFlag, int, _InputArray::KindFlag) @@ -421,8 +425,13 @@ class CV_EXPORTS _OutputArray : public _InputArray DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F }; - _OutputArray(); - _OutputArray(int _flags, void* _obj); + _OutputArray() = default; + + template + _OutputArray(int _flags, T* _obj) + : _InputArray(_flags, _obj) + {} + _OutputArray(Mat& m); _OutputArray(std::vector& vec); _OutputArray(cuda::GpuMat& d_mat); @@ -503,14 +512,23 @@ class CV_EXPORTS _OutputArray : public _InputArray void move(UMat& u) const; void move(Mat& m) const; +protected: + template _OutputArray(int _flags, T* _obj, Size _sz) + : _InputArray(_flags, _obj, _sz) + {} }; class CV_EXPORTS _InputOutputArray : public _OutputArray { public: - _InputOutputArray(); - _InputOutputArray(int _flags, void* _obj); + _InputOutputArray() = default; + + template + _InputOutputArray(int _flags, T* _obj) + : _OutputArray(_flags, _obj) + {} + _InputOutputArray(Mat& m); _InputOutputArray(std::vector& vec); _InputOutputArray(cuda::GpuMat& d_mat); @@ -550,7 +568,11 @@ class CV_EXPORTS _InputOutputArray : public _OutputArray template static _InputOutputArray rawInOut(std::vector<_Tp>& vec); template _InputOutputArray rawInOut(std::array<_Tp, _Nm>& arr); - +private: + template + _InputOutputArray(int _flags, T* _obj, Size _sz) + : _OutputArray(_flags, _obj, _sz) + {} }; /** Helper to wrap custom types. @see InputArray */ diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 649ebd265726..9ddbbc86d785 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -143,95 +143,123 @@ CV__DEBUG_NS_BEGIN //////////////////////// Input/Output Arrays //////////////////////// -inline void _InputArray::init(int _flags, const void* _obj) -{ flags = _flags; obj = (void*)_obj; } - -inline void _InputArray::init(int _flags, const void* _obj, Size _sz) -{ flags = _flags; obj = (void*)_obj; sz = _sz; } inline void* _InputArray::getObj() const { return obj; } inline int _InputArray::getFlags() const { return flags; } inline Size _InputArray::getSz() const { return sz; } -inline _InputArray::_InputArray() { init(0 + NONE, 0); } -inline _InputArray::_InputArray(int _flags, void* _obj) { init(_flags, _obj); } -inline _InputArray::_InputArray(const Mat& m) { init(+MAT+ACCESS_READ, &m); } -inline _InputArray::_InputArray(const std::vector& vec) { init(+STD_VECTOR_MAT+ACCESS_READ, &vec); } -inline _InputArray::_InputArray(const UMat& m) { init(+UMAT+ACCESS_READ, &m); } -inline _InputArray::_InputArray(const std::vector& vec) { init(+STD_VECTOR_UMAT+ACCESS_READ, &vec); } +template +_InputArray::_InputArray(int _flags, T* _obj) +: _InputArray(_flags, _obj, {}) +{} -template inline +template +_InputArray::_InputArray(int _flags, T* _obj, Size _sz) +: flags(_flags) +, obj(_obj) +, sz(_sz) +{} + +template +_InputArray::_InputArray(int _flags, const T* _obj, Size _sz) +: flags(_flags) +, obj(const_cast(_obj)) +, sz(_sz) +{} + +inline _InputArray::_InputArray(const Mat& m) +: _InputArray(+MAT+ACCESS_READ, &m) +{} + +inline _InputArray::_InputArray(const std::vector& vec) +: _InputArray(+STD_VECTOR_MAT+ACCESS_READ, &vec) +{} + +inline _InputArray::_InputArray(const UMat& m) +: _InputArray(+UMAT+ACCESS_READ, &m) +{} + +inline _InputArray::_InputArray(const std::vector& vec) +: _InputArray(+STD_VECTOR_UMAT+ACCESS_READ, &vec) +{} + +template _InputArray::_InputArray(const std::vector<_Tp>& vec) -{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); } +: _InputArray(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec) +{} -template inline +template _InputArray::_InputArray(const std::array<_Tp, _Nm>& arr) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)); } +: _InputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)) +{} -template inline +template _InputArray::_InputArray(const std::array& arr) -{ init(+STD_ARRAY_MAT + ACCESS_READ, arr.data(), Size(1, _Nm)); } +: _InputArray(+STD_ARRAY_MAT + ACCESS_READ, arr.data(), Size(1, _Nm)) +{} inline _InputArray::_InputArray(const std::vector& vec) -{ init(FIXED_TYPE + STD_BOOL_VECTOR + traits::Type::value + ACCESS_READ, &vec); } +: _InputArray(FIXED_TYPE + STD_BOOL_VECTOR + traits::Type::value + ACCESS_READ, &vec) +{} -template inline +template _InputArray::_InputArray(const std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); } +: _InputArray(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec) +{} -template inline +template _InputArray::_InputArray(const std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_READ, &vec); } +: _InputArray(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_READ, &vec) +{} -template inline +template _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, &mtx, Size(n, m)); } +: _InputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, &mtx, Size(n, m)) +{} -template inline +template _InputArray::_InputArray(const _Tp* vec, int n) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, vec, Size(n, 1)); } +: _InputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, vec, Size(n, 1)) +{} -template inline +template _InputArray::_InputArray(const Mat_<_Tp>& m) -{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_READ, &m); } +: _InputArray(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_READ, &m) +{} inline _InputArray::_InputArray(const double& val) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F + ACCESS_READ, &val, Size(1,1)); } +: _InputArray(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F + ACCESS_READ, &val, Size(1,1)) +{} inline _InputArray::_InputArray(const cuda::GpuMat& d_mat) -{ init(+CUDA_GPU_MAT + ACCESS_READ, &d_mat); } +: _InputArray(+CUDA_GPU_MAT + ACCESS_READ, &d_mat) +{} inline _InputArray::_InputArray(const std::vector& d_mat) -{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat);} +: _InputArray(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_READ, &d_mat) +{} inline _InputArray::_InputArray(const ogl::Buffer& buf) -{ init(+OPENGL_BUFFER + ACCESS_READ, &buf); } +: _InputArray(+OPENGL_BUFFER + ACCESS_READ, &buf) +{} inline _InputArray::_InputArray(const cuda::HostMem& cuda_mem) -{ init(+CUDA_HOST_MEM + ACCESS_READ, &cuda_mem); } +: _InputArray(+CUDA_HOST_MEM + ACCESS_READ, &cuda_mem) +{} -template inline +template _InputArray _InputArray::rawIn(const std::vector<_Tp>& vec) { - _InputArray v; - v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_READ; - v.obj = (void*)&vec; - return v; + return _InputArray(_InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_READ, &vec); } -template inline +template _InputArray _InputArray::rawIn(const std::array<_Tp, _Nm>& arr) { - _InputArray v; - v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ; - v.obj = (void*)arr.data(); - v.sz = Size(1, _Nm); - return v; + return _InputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)); } -inline _InputArray::~_InputArray() {} - inline Mat _InputArray::getMat(int i) const { if( kind() == MAT && i < 0 ) @@ -253,128 +281,154 @@ inline bool _InputArray::isGpuMatVector() const { return kind() == _InputArray:: //////////////////////////////////////////////////////////////////////////////////////// -inline _OutputArray::_OutputArray() { init(+NONE + ACCESS_WRITE, 0); } -inline _OutputArray::_OutputArray(int _flags, void* _obj) { init(_flags + ACCESS_WRITE, _obj); } -inline _OutputArray::_OutputArray(Mat& m) { init(+MAT+ACCESS_WRITE, &m); } -inline _OutputArray::_OutputArray(std::vector& vec) { init(+STD_VECTOR_MAT + ACCESS_WRITE, &vec); } -inline _OutputArray::_OutputArray(UMat& m) { init(+UMAT + ACCESS_WRITE, &m); } -inline _OutputArray::_OutputArray(std::vector& vec) { init(+STD_VECTOR_UMAT + ACCESS_WRITE, &vec); } +inline _OutputArray::_OutputArray(Mat& m) +: _OutputArray(+MAT+ACCESS_WRITE, &m) +{} +inline _OutputArray::_OutputArray(std::vector& vec) +: _OutputArray(+STD_VECTOR_MAT + ACCESS_WRITE, &vec) +{} +inline _OutputArray::_OutputArray(UMat& m) +: _OutputArray(+UMAT + ACCESS_WRITE, &m) +{} +inline _OutputArray::_OutputArray(std::vector& vec) +: _OutputArray(+STD_VECTOR_UMAT + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(std::vector<_Tp>& vec) -{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(std::array<_Tp, _Nm>& arr) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)) +{} -template inline +template _OutputArray::_OutputArray(std::array& arr) -{ init(+STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _Nm)); } +: _OutputArray(+STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _Nm)) +{} -template inline +template _OutputArray::_OutputArray(std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(Mat_<_Tp>& m) -{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m); } +: _OutputArray(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m) +{} -template inline +template _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)) +{} -template inline +template _OutputArray::_OutputArray(_Tp* vec, int n) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)) +{} -template inline +template _OutputArray::_OutputArray(const std::vector<_Tp>& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(const std::array<_Tp, _Nm>& arr) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)) +{} -template inline +template _OutputArray::_OutputArray(const std::array& arr) -{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _Nm)); } +: _OutputArray(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_WRITE, arr.data(), Size(1, _Nm)) +{} -template inline +template _OutputArray::_OutputArray(const std::vector >& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(const std::vector >& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec) +{} -template inline +template _OutputArray::_OutputArray(const Mat_<_Tp>& m) -{ init(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m) +{} -template inline +template _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)) +{} -template inline +template _OutputArray::_OutputArray(const _Tp* vec, int n) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)) +{} inline _OutputArray::_OutputArray(cuda::GpuMat& d_mat) -{ init(+CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } +: _OutputArray(+CUDA_GPU_MAT + ACCESS_WRITE, &d_mat) +{} inline _OutputArray::_OutputArray(std::vector& d_mat) -{ init(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat);} +: _OutputArray(+STD_VECTOR_CUDA_GPU_MAT + ACCESS_WRITE, &d_mat) +{} inline _OutputArray::_OutputArray(ogl::Buffer& buf) -{ init(+OPENGL_BUFFER + ACCESS_WRITE, &buf); } +: _OutputArray(+OPENGL_BUFFER + ACCESS_WRITE, &buf) +{} inline _OutputArray::_OutputArray(cuda::HostMem& cuda_mem) -{ init(+CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem); } +: _OutputArray(+CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem) +{} inline _OutputArray::_OutputArray(const Mat& m) -{ init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_WRITE, &m); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_WRITE, &m) +{} inline _OutputArray::_OutputArray(const std::vector& vec) -{ init(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_WRITE, &vec) +{} inline _OutputArray::_OutputArray(const UMat& m) -{ init(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_WRITE, &m); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_WRITE, &m) +{} inline _OutputArray::_OutputArray(const std::vector& vec) -{ init(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_WRITE, &vec); } +: _OutputArray(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_WRITE, &vec) +{} inline _OutputArray::_OutputArray(const cuda::GpuMat& d_mat) -{ init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_WRITE, &d_mat) +{} inline _OutputArray::_OutputArray(const ogl::Buffer& buf) -{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_WRITE, &buf); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_WRITE, &buf) +{} inline _OutputArray::_OutputArray(const cuda::HostMem& cuda_mem) -{ init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem); } +: _OutputArray(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem) +{} template inline _OutputArray _OutputArray::rawOut(std::vector<_Tp>& vec) { - _OutputArray v; - v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_WRITE; - v.obj = (void*)&vec; - return v; + return _OutputArray(_InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_WRITE, &vec); } template inline _OutputArray _OutputArray::rawOut(std::array<_Tp, _Nm>& arr) { - _OutputArray v; - v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE; - v.obj = (void*)arr.data(); - v.sz = Size(1, _Nm); - return v; + return _OutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); } inline @@ -401,130 +455,157 @@ std::vector >& _OutputArray::getVecVecRef() const /////////////////////////////////////////////////////////////////////////////////////////// -inline _InputOutputArray::_InputOutputArray() { init(0+ACCESS_RW, 0); } -inline _InputOutputArray::_InputOutputArray(int _flags, void* _obj) { init(_flags+ACCESS_RW, _obj); } -inline _InputOutputArray::_InputOutputArray(Mat& m) { init(+MAT+ACCESS_RW, &m); } -inline _InputOutputArray::_InputOutputArray(std::vector& vec) { init(+STD_VECTOR_MAT+ACCESS_RW, &vec); } -inline _InputOutputArray::_InputOutputArray(UMat& m) { init(+UMAT+ACCESS_RW, &m); } -inline _InputOutputArray::_InputOutputArray(std::vector& vec) { init(+STD_VECTOR_UMAT+ACCESS_RW, &vec); } +inline _InputOutputArray::_InputOutputArray(Mat& m) +: _InputOutputArray(+MAT+ACCESS_RW, &m) +{} +inline _InputOutputArray::_InputOutputArray(std::vector& vec) +: _InputOutputArray(+STD_VECTOR_MAT+ACCESS_RW, &vec) +{} +inline _InputOutputArray::_InputOutputArray(UMat& m) +: _InputOutputArray(+UMAT+ACCESS_RW, &m) +{} +inline _InputOutputArray::_InputOutputArray(std::vector& vec) +: _InputOutputArray(+STD_VECTOR_UMAT+ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec) -{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(std::array<_Tp, _Nm>& arr) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)) +{} -template inline +template _InputOutputArray::_InputOutputArray(std::array& arr) -{ init(+STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _Nm)); } +: _InputOutputArray(+STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _Nm)) +{} -template inline +template _InputOutputArray::_InputOutputArray(std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(std::vector >& vec) -{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(Mat_<_Tp>& m) -{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m); } +: _InputOutputArray(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m) +{} -template inline +template _InputOutputArray::_InputOutputArray(Matx<_Tp, m, n>& mtx) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)) +{} -template inline +template _InputOutputArray::_InputOutputArray(_Tp* vec, int n) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)) +{} -template inline +template _InputOutputArray::_InputOutputArray(const std::vector<_Tp>& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(const std::array<_Tp, _Nm>& arr) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)) +{} -template inline +template _InputOutputArray::_InputOutputArray(const std::array& arr) -{ init(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _Nm)); } +: _InputOutputArray(FIXED_SIZE + STD_ARRAY_MAT + ACCESS_RW, arr.data(), Size(1, _Nm)) +{} -template inline +template _InputOutputArray::_InputOutputArray(const std::vector >& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(const std::vector >& vec) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec) +{} -template inline +template _InputOutputArray::_InputOutputArray(const Mat_<_Tp>& m) -{ init(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m) +{} -template inline +template _InputOutputArray::_InputOutputArray(const Matx<_Tp, m, n>& mtx) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)) +{} -template inline +template _InputOutputArray::_InputOutputArray(const _Tp* vec, int n) -{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)) +{} inline _InputOutputArray::_InputOutputArray(cuda::GpuMat& d_mat) -{ init(+CUDA_GPU_MAT + ACCESS_RW, &d_mat); } +: _InputOutputArray(+CUDA_GPU_MAT + ACCESS_RW, &d_mat) +{} inline _InputOutputArray::_InputOutputArray(ogl::Buffer& buf) -{ init(+OPENGL_BUFFER + ACCESS_RW, &buf); } +: _InputOutputArray(+OPENGL_BUFFER + ACCESS_RW, &buf) +{} inline _InputOutputArray::_InputOutputArray(cuda::HostMem& cuda_mem) -{ init(+CUDA_HOST_MEM + ACCESS_RW, &cuda_mem); } +: _InputOutputArray(+CUDA_HOST_MEM + ACCESS_RW, &cuda_mem) +{} inline _InputOutputArray::_InputOutputArray(const Mat& m) -{ init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_RW, &m); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_RW, &m) +{} inline _InputOutputArray::_InputOutputArray(const std::vector& vec) -{ init(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_RW, &vec) +{} inline _InputOutputArray::_InputOutputArray(const UMat& m) -{ init(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_RW, &m); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_RW, &m) +{} inline _InputOutputArray::_InputOutputArray(const std::vector& vec) -{ init(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_RW, &vec); } +: _InputOutputArray(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_RW, &vec) +{} inline _InputOutputArray::_InputOutputArray(const cuda::GpuMat& d_mat) -{ init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_RW, &d_mat); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_RW, &d_mat) +{} inline _InputOutputArray::_InputOutputArray(const std::vector& d_mat) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat);} +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat) +{} template<> inline _InputOutputArray::_InputOutputArray(std::vector& d_mat) -{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat);} +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_CUDA_GPU_MAT + ACCESS_RW, &d_mat) +{} inline _InputOutputArray::_InputOutputArray(const ogl::Buffer& buf) -{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_RW, &buf); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_RW, &buf) +{} inline _InputOutputArray::_InputOutputArray(const cuda::HostMem& cuda_mem) -{ init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_RW, &cuda_mem); } +: _InputOutputArray(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_RW, &cuda_mem) +{} template inline _InputOutputArray _InputOutputArray::rawInOut(std::vector<_Tp>& vec) { - _InputOutputArray v; - v.flags = _InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_RW; - v.obj = (void*)&vec; - return v; + return _InputOutputArray(_InputArray::FIXED_TYPE + _InputArray::STD_VECTOR + rawType<_Tp>() + ACCESS_RW, &vec); } template inline _InputOutputArray _InputOutputArray::rawInOut(std::array<_Tp, _Nm>& arr) { - _InputOutputArray v; - v.flags = FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW; - v.obj = (void*)arr.data(); - v.sz = Size(1, _Nm); - return v; + return _InputOutputArray(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); } diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index f42f7bff33c3..05bb76b0a062 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -1838,7 +1838,8 @@ _InputArray::_InputArray(const MatExpr& expr) swap(const_cast(expr), result_expr); } CV_Assert(isIdentity(expr)); - init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ, &expr.a); + flags = FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ; + obj = const_cast(&expr.a); } } // cv:: From 1698ff9ed359fe62b872aa790b8db7944e86485a Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Fri, 15 Nov 2024 18:53:29 +0000 Subject: [PATCH 02/19] adds `_ArrayOps::getMat_` --- .../include/opencv2/core/array_helpers.hpp | 173 ++++++++++++++++++ modules/core/include/opencv2/core/mat.hpp | 1 + modules/core/include/opencv2/core/mat.inl.hpp | 19 -- modules/core/src/matrix_wrap.cpp | 67 ++----- 4 files changed, 189 insertions(+), 71 deletions(-) create mode 100644 modules/core/include/opencv2/core/array_helpers.hpp diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp new file mode 100644 index 000000000000..680f74d37b9a --- /dev/null +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -0,0 +1,173 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef OPENCV_CORE_ARRAY_HELPERS_HPP +#define OPENCV_CORE_ARRAY_HELPERS_HPP + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" + +namespace cv { +struct _ArrayOpsBase { + virtual Mat getMat_(const _InputArray& self, int i = -1) const = 0; +protected: + ~_ArrayOpsBase() = default; +}; + +template +inline constexpr bool is_Mat = std::is_same_v; + +template +inline constexpr bool is_Mat> = true; + +template +inline constexpr bool is_UMat = std::is_same_v; + +template +inline constexpr bool is_cuda_GpuMat = std::is_same_v; + +template +inline constexpr bool is_vector = false; + +template +inline constexpr bool is_vector> = true; + +#ifdef HAVE_CUDA +inline constexpr bool have_cuda = true; +#else +inline constexpr bool have_cuda = false; +#endif // HAVE_CUDA + +template +struct _ArrayOps final : _ArrayOpsBase { + Mat getMat_(const _InputArray& self, const int i) const final + { + T& v = get(self.getObj()); + using value_type = typename T::value_type; + [[maybe_unused]] const auto index = static_cast(i); + + if constexpr (std::is_same_v) { + CV_Assert(i < 0); + constexpr int type = CV_8U; + if (v.empty()) { + return Mat(); + } + + const int n = static_cast(v.size()); + Mat m(1, &n, type); + std::copy(v.begin(), v.end(), m.data); + return m; + } + else if constexpr (is_Mat) { + CV_Assert(0 <= i); + CV_Assert(index < v.size()); + return v[index]; + } + else if constexpr (is_UMat) { + CV_Assert(0 <= i); + CV_Assert(index < v.size()); + return v[index].getMat(self.getFlags() & ACCESS_MASK); + } + else if constexpr (is_vector) { + const int type = self.type(i); + CV_Assert(0 <= i); + CV_Assert(index < v.size()); + auto& sub_v = v[i]; + const int v_size = static_cast(sub_v.size()); + return sub_v.empty() ? Mat() : Mat(1, &v_size, type, sub_v.data()); + } + else { + CV_Assert(i < 0); + const int type = CV_MAT_TYPE(self.getFlags()); + const int width = static_cast(v.size()); + return v.empty() ? Mat() : Mat(1, &width, type, v.data()); + } + } + + static const T& get(const void* const data) { + return *static_cast(data); + } + + static T& get(void* const data) + { + return *static_cast(data); + } +}; + +template<> +Mat _ArrayOps>::getMat_(const _InputArray& self, const int i) const; + +template +inline constexpr _ArrayOps array_ops; + +template +_InputArray::_InputArray(const int _flags, T* const _obj) +: _InputArray(_flags, _obj, {}) +{} + +template +_InputArray::_InputArray(const int _flags, T* const _obj, const Size _sz) +: flags(_flags) +, obj(_obj) +, sz(_sz) +{ + if constexpr (is_vector) { + ops = &array_ops; + } +} + +template +_InputArray::_InputArray(const int _flags, const T* const _obj, const Size _sz) +: flags(_flags) +, obj(const_cast(_obj)) +, sz(_sz) +{ + if constexpr (is_vector) { + ops = &array_ops; + } +} +} // namespace cv + +#pragma GCC diagnostic pop + +#endif // OPENCV_CORE_ARRAY_HELPERS_HPP diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 67343b8b5871..e1c0ab556638 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -4110,5 +4110,6 @@ CV_EXPORTS MatExpr abs(const MatExpr& e); } // cv #include "opencv2/core/mat.inl.hpp" +#include "opencv2/core/array_helpers.hpp" #endif // OPENCV_CORE_MAT_HPP diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 9ddbbc86d785..4bc156abd274 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -148,25 +148,6 @@ inline void* _InputArray::getObj() const { return obj; } inline int _InputArray::getFlags() const { return flags; } inline Size _InputArray::getSz() const { return sz; } -template -_InputArray::_InputArray(int _flags, T* _obj) -: _InputArray(_flags, _obj, {}) -{} - -template -_InputArray::_InputArray(int _flags, T* _obj, Size _sz) -: flags(_flags) -, obj(_obj) -, sz(_sz) -{} - -template -_InputArray::_InputArray(int _flags, const T* _obj, Size _sz) -: flags(_flags) -, obj(const_cast(_obj)) -, sz(_sz) -{} - inline _InputArray::_InputArray(const Mat& m) : _InputArray(+MAT+ACCESS_READ, &m) {} diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index b96dc4077612..b50b2ea36d8d 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -38,53 +38,15 @@ Mat _InputArray::getMat_(int i) const return Mat(sz, flags, obj); } - if( k == STD_VECTOR ) - { - CV_Assert( i < 0 ); - int t = CV_MAT_TYPE(flags); - const std::vector& v = *(const std::vector*)obj; - int v_size = size().width; - - return !v.empty() ? Mat(1, &v_size, t, (void*)&v[0]) : Mat(); - } - - if( k == STD_BOOL_VECTOR ) - { - CV_Assert( i < 0 ); - int t = CV_8U; - const std::vector& v = *(const std::vector*)obj; - int j, n = (int)v.size(); - if( n == 0 ) - return Mat(); - Mat m(1, &n, t); - uchar* dst = m.data; - for( j = 0; j < n; j++ ) - dst[j] = (uchar)v[j]; - return m; + if (k == STD_VECTOR || k == STD_BOOL_VECTOR || k == STD_VECTOR_VECTOR || + k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT) { + CV_Assert(ops != nullptr); + return ops->getMat_(*this, i); } if( k == NONE ) return Mat(); - if( k == STD_VECTOR_VECTOR ) - { - int t = type(i); - const std::vector >& vv = *(const std::vector >*)obj; - CV_Assert( 0 <= i && i < (int)vv.size() ); - const std::vector& v = vv[i]; - int v_size = size(i).width; - - return !v.empty() ? Mat(1, &v_size, t, (void*)&v[0]) : Mat(); - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& v = *(const std::vector*)obj; - CV_Assert( 0 <= i && i < (int)v.size() ); - - return v[i]; - } - if( k == STD_ARRAY_MAT ) { const Mat* v = (const Mat*)obj; @@ -92,15 +54,6 @@ Mat _InputArray::getMat_(int i) const return v[i]; } - - if( k == STD_VECTOR_UMAT ) - { - const std::vector& v = *(const std::vector*)obj; - CV_Assert( 0 <= i && i < (int)v.size() ); - - return v[i].getMat(accessFlags); - } - if( k == OPENGL_BUFFER ) { CV_Assert( i < 0 ); @@ -511,7 +464,7 @@ Size _InputArray::size(int i) const return cuda_mem->size(); } - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } int _InputArray::sizend(int* arrsz, int i) const @@ -2207,4 +2160,14 @@ void _OutputArray::assign(const std::vector& v) const static _InputOutputArray _none; InputOutputArray noArray() { return _none; } +template<> +[[gnu::visibility("default")]] Mat _ArrayOps>::getMat_(const _InputArray& self, const int i) const +{ + std::vector& v = get(self.getObj()); + CV_Assert(i < 0); + const int type = CV_MAT_TYPE(self.getFlags()); + const int width = static_cast(v.size()); + return v.empty() ? Mat() : Mat(1, &width, type, v.data()); +} + } // cv:: From 6bf987d0b4bda40af2ca86c971cbdbfc8124046d Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Fri, 15 Nov 2024 18:58:03 +0000 Subject: [PATCH 03/19] adds `_ArrayOps::size` --- .../include/opencv2/core/array_helpers.hpp | 35 ++++++- modules/core/src/matrix_wrap.cpp | 98 ++++++------------- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 680f74d37b9a..c37d4fccb8f4 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -50,6 +50,7 @@ namespace cv { struct _ArrayOpsBase { virtual Mat getMat_(const _InputArray& self, int i = -1) const = 0; + virtual Size size(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -124,7 +125,36 @@ struct _ArrayOps final : _ArrayOpsBase { } } - static const T& get(const void* const data) { + Size size(const _InputArray& self, const int i) const final { + using value_type = typename T::value_type; + auto& v = get(self.getObj()); + + if constexpr (is_Mat || is_UMat) { + if (i < 0) { + return v.empty() ? Size() : Size(static_cast(v.size()), 1); + } + + const auto index = static_cast(i); + CV_Assert(index < v.size()); + return v[index].size(); + } + else if constexpr (is_vector) { + if (i < 0) { + return v.empty() ? Size() : Size(static_cast(v.size()), 1); + } + + const auto index = static_cast(i); + CV_Assert(index < v.size()); + return Size(static_cast(v[index].size()), 1); + } + else { + CV_Assert(i < 0); + return Size(static_cast(v.size()), 1); + } + } + + static const T& get(const void* const data) + { return *static_cast(data); } @@ -137,6 +167,9 @@ struct _ArrayOps final : _ArrayOpsBase { template<> Mat _ArrayOps>::getMat_(const _InputArray& self, const int i) const; +template<> +Size _ArrayOps>::size(const _InputArray& self, const int i) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index b50b2ea36d8d..c07b2eea0986 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -350,17 +350,13 @@ Size _InputArray::size(int i) const if( k == MAT ) { CV_Assert( i < 0 ); - const Mat* m = (const Mat*)obj; - CV_Assert(m->dims <= 2); - return Size(m->cols, m->rows); + return ((const Mat*)obj)->size(); } if( k == UMAT ) { CV_Assert( i < 0 ); - const UMat* m = (const UMat*)obj; - CV_Assert(m->dims <= 2); - return Size(m->cols, m->rows); + return ((const UMat*)obj)->size(); } if (k == MATX) @@ -368,48 +364,16 @@ Size _InputArray::size(int i) const CV_Assert( i < 0 ); return sz; } - - if( k == STD_VECTOR ) - { - CV_Assert( i < 0 ); - const std::vector& v = *(const std::vector*)obj; - const std::vector& iv = *(const std::vector*)obj; - size_t szb = v.size(), szi = iv.size(); - return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); - } - - if( k == STD_BOOL_VECTOR ) - { - CV_Assert( i < 0 ); - const std::vector& v = *(const std::vector*)obj; - return Size((int)v.size(), 1); + if (k == STD_VECTOR || k == STD_BOOL_VECTOR || k == STD_VECTOR_VECTOR || + k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT || + k == STD_VECTOR_CUDA_GPU_MAT) { + CV_Assert(ops != nullptr); + return ops->size(*this, i); } if( k == NONE ) return Size(); - if( k == STD_VECTOR_VECTOR ) - { - const std::vector >& vv = *(const std::vector >*)obj; - if( i < 0 ) - return vv.empty() ? Size() : Size((int)vv.size(), 1); - CV_Assert( i < (int)vv.size() ); - const std::vector >& ivv = *(const std::vector >*)obj; - - size_t szb = vv[i].size(), szi = ivv[i].size(); - return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return vv.empty() ? Size() : Size((int)vv.size(), 1); - CV_Assert( i < (int)vv.size() ); - - return vv[i].size(); - } - if( k == STD_ARRAY_MAT ) { const Mat* vv = (const Mat*)obj; @@ -420,29 +384,6 @@ Size _InputArray::size(int i) const return vv[i].size(); } - if (k == STD_VECTOR_CUDA_GPU_MAT) - { -#ifdef HAVE_CUDA - const std::vector& vv = *(const std::vector*)obj; - if (i < 0) - return vv.empty() ? Size() : Size((int)vv.size(), 1); - CV_Assert(i < (int)vv.size()); - return vv[i].size(); -#else - CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)"); -#endif - } - - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return vv.empty() ? Size() : Size((int)vv.size(), 1); - CV_Assert( i < (int)vv.size() ); - - return vv[i].size(); - } - if( k == OPENGL_BUFFER ) { CV_Assert( i < 0 ); @@ -464,7 +405,7 @@ Size _InputArray::size(int i) const return cuda_mem->size(); } - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } int _InputArray::sizend(int* arrsz, int i) const @@ -2170,4 +2111,27 @@ template<> return v.empty() ? Mat() : Mat(1, &width, type, v.data()); } +[[noreturn]] static void noCudaError() { + CV_Error( + Error::StsNotImplemented, + "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)"); +} + +template<> +[[gnu::visibility("default")]] Size _ArrayOps>::size(const _InputArray& self, const int i) const +{ + if constexpr (!have_cuda) { + noCudaError(); + } else { + const std::vector& v = get(self.getObj()); + if (i < 0) { + return v.empty() ? Size() : Size(static_cast(v.size()), 1); + } + + const auto index = static_cast(i); + CV_Assert(index < v.size()); + return v[index].size(); + } +} + } // cv:: From 3a15039ff473fb01ca849552bb4063d2df16a605 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 13 Nov 2024 19:53:25 +0000 Subject: [PATCH 04/19] adds `_ArrayOps::getUMat` --- .../core/include/opencv2/core/array_helpers.hpp | 17 ++++++++++++++++- modules/core/src/matrix_wrap.cpp | 6 ++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index c37d4fccb8f4..94de12388c1b 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -50,6 +50,7 @@ namespace cv { struct _ArrayOpsBase { virtual Mat getMat_(const _InputArray& self, int i = -1) const = 0; + virtual UMat getUMat(const _InputArray& self, int i) const = 0; virtual Size size(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; @@ -125,7 +126,21 @@ struct _ArrayOps final : _ArrayOpsBase { } } - Size size(const _InputArray& self, const int i) const final { + UMat getUMat(const _InputArray& self, const int i) const final { + using value_type = typename T::value_type; + + if constexpr (is_UMat) { + T& v = get(self.getObj()); + CV_Assert(0 <= i); + CV_Assert(static_cast(i) < v.size()); + return v[i]; + } + else { + CV_Assert(false && "unreachable"); + } + } + + Size size(const _InputArray& self, const int i) const final { using value_type = typename T::value_type; auto& v = get(self.getObj()); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index c07b2eea0986..091ab5c80ef0 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -93,10 +93,8 @@ UMat _InputArray::getUMat(int i) const if( k == STD_VECTOR_UMAT ) { - const std::vector& v = *(const std::vector*)obj; - CV_Assert( 0 <= i && i < (int)v.size() ); - - return v[i]; + CV_Assert(ops != nullptr); + return ops->getUMat(*this, i); } if( k == MAT ) From 127fe654a8506b683b492bb40f2d2b35feb30f99 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 13 Nov 2024 21:34:56 +0000 Subject: [PATCH 05/19] adds `_ArrayOps::getMatVector` and `_ArrayOps::getUMatVector` --- .../include/opencv2/core/array_helpers.hpp | 59 ++++++++++++++ modules/core/src/matrix_wrap.cpp | 79 +++---------------- 2 files changed, 68 insertions(+), 70 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 94de12388c1b..68953bdade6c 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -51,6 +51,8 @@ namespace cv { struct _ArrayOpsBase { virtual Mat getMat_(const _InputArray& self, int i = -1) const = 0; virtual UMat getUMat(const _InputArray& self, int i) const = 0; + virtual std::vector getMatVector(const _InputArray& self) const = 0; + virtual std::vector getUMatVector(const _InputArray& self) const = 0; virtual Size size(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; @@ -140,6 +142,63 @@ struct _ArrayOps final : _ArrayOpsBase { } } + std::vector getMatVector(const _InputArray& self) const final + { + using value_type = typename T::value_type; + auto& v = get(self.getObj()); + if constexpr (is_Mat) { + return {v.begin(), v.end()}; + } + else if constexpr (!is_cuda_GpuMat) { + const int flags = self.getFlags(); + [[maybe_unused]] const int type = CV_MAT_TYPE(flags); + [[maybe_unused]] const int column_number = CV_MAT_CN(flags); + + std::vector result; + result.reserve(v.size()); + + for (std::size_t i = 0; i < v.size(); ++i) { + if constexpr (is_UMat) { + result.emplace_back(v[i].getMat(flags & ACCESS_MASK)); + } + else if constexpr (is_vector) { + result.emplace_back(size(self, i), type, static_cast(v[i].data())); + } + else if constexpr (!std::is_same_v) { + result.emplace_back(1, column_number, type, static_cast(&v[i])); + } + } + + return result; + } + else { + CV_Assert(false && "unreachable"); + } + } + + std::vector getUMatVector(const _InputArray& self) const final + { + using value_type = typename T::value_type; + auto& v = get(self.getObj()); + [[maybe_unused]] const int flags = self.getFlags(); + + if constexpr (is_UMat) { + return v; + } + else if constexpr (is_Mat) { + std::vector result; + result.reserve(v.size()); + for (std::size_t i = 0; i < v.size(); ++i) { + result.emplace_back(v[i].getUMat(flags & ACCESS_MASK)); + } + + return result; + } + else { + CV_Assert(false && "unreachable"); + } + } + Size size(const _InputArray& self, const int i) const final { using value_type = typename T::value_type; auto& v = get(self.getObj()); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 091ab5c80ef0..a300bcd26205 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -111,7 +111,6 @@ UMat _InputArray::getUMat(int i) const void _InputArray::getMatVector(std::vector& mv) const { _InputArray::KindFlag k = kind(); - AccessFlag accessFlags = flags & ACCESS_MASK; if( k == MAT ) { @@ -136,17 +135,11 @@ void _InputArray::getMatVector(std::vector& mv) const return; } - if( k == STD_VECTOR ) - { - const std::vector& v = *(const std::vector*)obj; - - size_t n = size().width, esz = CV_ELEM_SIZE(flags); - int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags); - mv.resize(n); - - for( size_t i = 0; i < n; i++ ) - mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i)); - return; + if (k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_VECTOR_MAT || + k == STD_VECTOR_UMAT) { + CV_Assert(ops != nullptr); + mv = ops->getMatVector(*this); + return; } if( k == NONE ) @@ -155,32 +148,6 @@ void _InputArray::getMatVector(std::vector& mv) const return; } - if( k == STD_VECTOR_VECTOR ) - { - const std::vector >& vv = *(const std::vector >*)obj; - int n = (int)vv.size(); - int t = CV_MAT_TYPE(flags); - mv.resize(n); - - for( int i = 0; i < n; i++ ) - { - const std::vector& v = vv[i]; - mv[i] = Mat(size(i), t, (void*)&v[0]); - } - return; - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& v = *(const std::vector*)obj; - size_t n = v.size(); - mv.resize(n); - - for( size_t i = 0; i < n; i++ ) - mv[i] = v[i]; - return; - } - if( k == STD_ARRAY_MAT ) { const Mat* v = (const Mat*)obj; @@ -192,17 +159,6 @@ void _InputArray::getMatVector(std::vector& mv) const return; } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& v = *(const std::vector*)obj; - size_t n = v.size(); - mv.resize(n); - - for( size_t i = 0; i < n; i++ ) - mv[i] = v[i].getMat(accessFlags); - return; - } - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } @@ -217,15 +173,10 @@ void _InputArray::getUMatVector(std::vector& umv) const return; } - if( k == STD_VECTOR_MAT ) - { - const std::vector& v = *(const std::vector*)obj; - size_t n = v.size(); - umv.resize(n); - - for( size_t i = 0; i < n; i++ ) - umv[i] = v[i].getUMat(accessFlags); - return; + if (k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT) { + CV_Assert(ops != nullptr); + umv = ops->getUMatVector(*this); + return; } if( k == STD_ARRAY_MAT ) @@ -238,18 +189,6 @@ void _InputArray::getUMatVector(std::vector& umv) const umv[i] = v[i].getUMat(accessFlags); return; } - - if( k == STD_VECTOR_UMAT ) - { - const std::vector& v = *(const std::vector*)obj; - size_t n = v.size(); - umv.resize(n); - - for( size_t i = 0; i < n; i++ ) - umv[i] = v[i]; - return; - } - if( k == UMAT ) { UMat& v = *(UMat*)obj; From fe3fb74a56b9787beb483c43cfa9167442fbe812 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 13 Nov 2024 21:49:08 +0000 Subject: [PATCH 06/19] adds `_ArrayOps::dims` --- .../include/opencv2/core/array_helpers.hpp | 24 +++++++++++++++ modules/core/src/matrix_wrap.cpp | 30 ++----------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 68953bdade6c..a28c928c254d 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -53,6 +53,7 @@ struct _ArrayOpsBase { virtual UMat getUMat(const _InputArray& self, int i) const = 0; virtual std::vector getMatVector(const _InputArray& self) const = 0; virtual std::vector getUMatVector(const _InputArray& self) const = 0; + virtual int dims(const _InputArray& self, int i) const = 0; virtual Size size(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; @@ -199,6 +200,29 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int dims(const _InputArray& self, const int i) const final + { + using value_type = typename T::value_type; + T& v = get(self.getObj()); + if constexpr (is_vector || is_Mat || is_UMat) { + if (i < 0) { + return 1; + } + + if constexpr (is_vector) { + CV_Assert(static_cast(i) < v.size()); + return 2; + } + else { + return v[i].dims; + } + } + else { + CV_Assert(i < 0); + return 1; + } + } + Size size(const _InputArray& self, const int i) const final { using value_type = typename T::value_type; auto& v = get(self.getObj()); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index a300bcd26205..dbed5a510b44 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -524,23 +524,9 @@ int _InputArray::dims(int i) const if( k == NONE ) return 0; - if( k == STD_VECTOR_VECTOR ) - { - const std::vector >& vv = *(const std::vector >*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < (int)vv.size() ); - return 2; - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < (int)vv.size() ); - - return vv[i].dims; + if (k == STD_VECTOR_VECTOR || k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT) { + CV_Assert(ops != nullptr); + return ops->dims(*this, i); } if( k == STD_ARRAY_MAT ) @@ -553,16 +539,6 @@ int _InputArray::dims(int i) const return vv[i].dims; } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < (int)vv.size() ); - - return vv[i].dims; - } - if( k == OPENGL_BUFFER ) { CV_Assert( i < 0 ); From 5aca05d903e0b59c72447c5a0f48d5576d3fac04 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Thu, 14 Nov 2024 01:46:00 +0000 Subject: [PATCH 07/19] adds `_ArrayOps::sizeend` --- .../include/opencv2/core/array_helpers.hpp | 33 +++++++++++++ modules/core/src/matrix_wrap.cpp | 48 ++++++++----------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index a28c928c254d..c7bf894185a1 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -55,6 +55,7 @@ struct _ArrayOpsBase { virtual std::vector getUMatVector(const _InputArray& self) const = 0; virtual int dims(const _InputArray& self, int i) const = 0; virtual Size size(const _InputArray& self, int i) const = 0; + virtual int sizend(const _InputArray& self, int* arraySize, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -251,6 +252,35 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int sizend(const _InputArray& self, int* const arraySize, const int i) const final + { + using value_type = typename T::value_type; + T& v = get(self.getObj()); + if constexpr (is_Mat || is_UMat) { + CV_Assert(i >= 0); + CV_Assert(static_cast(i) < v.size()); + + const auto& m = v[i]; + const int result = m.dims; + if (arraySize != nullptr) { + for (int j = 0; j < result; ++j) { + arraySize[j] = m.size.p[j]; + } + } + + return result; + } + else { + CV_Assert(i < 0); + Size sz2d = Size(v.size(), 1); + if (arraySize != nullptr) { + arraySize[0] = sz2d.width; + } + + return 1; + } + } + static const T& get(const void* const data) { return *static_cast(data); @@ -268,6 +298,9 @@ Mat _ArrayOps>::getMat_(const _InputArray& self, const template<> Size _ArrayOps>::size(const _InputArray& self, const int i) const; +template<> +int _ArrayOps>::sizend(const _InputArray& self, int* const arraySize, const int i) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index dbed5a510b44..20b93cb10b0f 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -350,6 +350,9 @@ int _InputArray::sizend(int* arrsz, int i) const int j, d = 0; _InputArray::KindFlag k = kind(); + const bool is_nd_vector = (k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT) && (i >= 0); + const bool is_1d_vector = k == STD_VECTOR && i < 0; + if( k == NONE ) ; else if( k == MAT ) @@ -370,15 +373,10 @@ int _InputArray::sizend(int* arrsz, int i) const for(j = 0; j < d; j++) arrsz[j] = m.size.p[j]; } - else if( k == STD_VECTOR_MAT && i >= 0 ) + else if( is_nd_vector || is_1d_vector ) { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert( i < (int)vv.size() ); - const Mat& m = vv[i]; - d = m.dims; - if(arrsz) - for(j = 0; j < d; j++) - arrsz[j] = m.size.p[j]; + CV_Assert(ops != nullptr); + return ops->sizend(*this, arrsz, i); } else if( k == STD_ARRAY_MAT && i >= 0 ) { @@ -390,25 +388,6 @@ int _InputArray::sizend(int* arrsz, int i) const 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; - CV_Assert( i < (int)vv.size() ); - const UMat& 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 && i < 0 ) - { - Size sz2d = size(); - d = 1; - if(arrsz) - { - arrsz[0] = sz2d.width; - } - } else { CV_CheckLE(dims(i), 2, "Not supported"); @@ -686,7 +665,7 @@ int _InputArray::type(int i) const if( k == CUDA_HOST_MEM ) return ((const cuda::HostMem*)obj)->type(); - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } int _InputArray::depth(int i) const @@ -2047,4 +2026,17 @@ template<> } } +template<> +[[gnu::visibility("default")]] int _ArrayOps>::sizend(const _InputArray& self, int* const arraySize, const int i) const +{ + std::vector& v = get(self.getObj()); + CV_Assert(i < 0); + Size sz2d = Size(v.size(), 1); + if (arraySize != nullptr) { + arraySize[0] = sz2d.width; + } + + return 1; +} + } // cv:: From b237323b3db8db7e868a094774b809e27b19b4ad Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Fri, 15 Nov 2024 21:18:41 +0000 Subject: [PATCH 08/19] adds `_ArrayOps::type` --- .../include/opencv2/core/array_helpers.hpp | 20 ++++++ modules/core/src/matrix_wrap.cpp | 61 +++++++------------ 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index c7bf894185a1..c81cf6d971b7 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -56,6 +56,7 @@ struct _ArrayOpsBase { virtual int dims(const _InputArray& self, int i) const = 0; virtual Size size(const _InputArray& self, int i) const = 0; virtual int sizend(const _InputArray& self, int* arraySize, int i) const = 0; + virtual int type(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -281,6 +282,25 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int type(const _InputArray& self, const int i) const final + { + using value_type = typename T::value_type; + if constexpr (is_Mat || is_UMat) { + T& v = get(self.getObj()); + if (v.empty()) { + const int flags = self.getFlags(); + CV_Assert((flags & _InputArray::FIXED_TYPE) != 0); + return CV_MAT_TYPE(flags); + } + + CV_Assert(i < static_cast(v.size())); + return v[i >= 0 ? i : 0].type(); + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 20b93cb10b0f..66c81747442d 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -604,28 +604,9 @@ int _InputArray::type(int i) const if( k == NONE ) return -1; - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( vv.empty() ) - { - CV_Assert((flags & FIXED_TYPE) != 0); - return CV_MAT_TYPE(flags); - } - CV_Assert( i < (int)vv.size() ); - return vv[i >= 0 ? i : 0].type(); - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( vv.empty() ) - { - CV_Assert((flags & FIXED_TYPE) != 0); - return CV_MAT_TYPE(flags); - } - CV_Assert( i < (int)vv.size() ); - return vv[i >= 0 ? i : 0].type(); + if (k == STD_VECTOR_UMAT || k == STD_VECTOR_MAT || k == STD_VECTOR_CUDA_GPU_MAT) { + CV_Assert(ops != nullptr); + return ops->type(*this, i); } if( k == STD_ARRAY_MAT ) @@ -640,22 +621,6 @@ int _InputArray::type(int i) const return vv[i >= 0 ? i : 0].type(); } - if (k == STD_VECTOR_CUDA_GPU_MAT) - { -#ifdef HAVE_CUDA - const std::vector& vv = *(const std::vector*)obj; - if (vv.empty()) - { - CV_Assert((flags & FIXED_TYPE) != 0); - return CV_MAT_TYPE(flags); - } - CV_Assert(i < (int)vv.size()); - return vv[i >= 0 ? i : 0].type(); -#else - CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)"); -#endif - } - if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->type(); @@ -665,7 +630,7 @@ int _InputArray::type(int i) const if( k == CUDA_HOST_MEM ) return ((const cuda::HostMem*)obj)->type(); - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } int _InputArray::depth(int i) const @@ -2039,4 +2004,22 @@ template<> return 1; } +template<> +[[gnu::visibility("default")]] int _ArrayOps>::type(const _InputArray& self, const int i) const +{ + if constexpr (!have_cuda) { + noCudaError(); + } else { + std::vector& v = get(self.getObj()); + if (v.empty()) { + const int flags = self.getFlags(); + CV_Assert((flags & _InputArray::FIXED_TYPE) != 0); + return CV_MAT_TYPE(flags); + } + + CV_Assert(i < static_cast(v.size())); + return v[i >= 0 ? i : 0].type(); + } +} + } // cv:: From c629b036ff8abc76a0ee6d1be955c8f11239d987 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Mon, 18 Nov 2024 23:25:39 +0000 Subject: [PATCH 09/19] adds `_ArrayOpsBase::total` --- .../include/opencv2/core/array_helpers.hpp | 16 ++++++++++++++ modules/core/src/matrix_wrap.cpp | 22 ++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index c81cf6d971b7..3b1146da0e5c 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -57,6 +57,7 @@ struct _ArrayOpsBase { virtual Size size(const _InputArray& self, int i) const = 0; virtual int sizend(const _InputArray& self, int* arraySize, int i) const = 0; virtual int type(const _InputArray& self, int i) const = 0; + virtual std::size_t total(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -301,6 +302,21 @@ struct _ArrayOps final : _ArrayOpsBase { } } + std::size_t total(const _InputArray& self, const int i) const final { + using value_type = typename T::value_type; + T& v = get(self.getObj()); + if constexpr (is_Mat || is_UMat) { + if (i < 0) { + return v.size(); + } + + CV_Assert(i < static_cast(v.size())); + return v[i].total(); + } else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 66c81747442d..398a55150014 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -555,14 +555,10 @@ size_t _InputArray::total(int i) const return ((const UMat*)obj)->total(); } - if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT ) { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return vv.size(); - - CV_Assert( i < (int)vv.size() ); - return vv[i].total(); + CV_Assert(ops != nullptr); + return ops->total(*this, i); } if( k == STD_ARRAY_MAT ) @@ -575,16 +571,6 @@ size_t _InputArray::total(int i) const return vv[i].total(); } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return vv.size(); - - CV_Assert( i < (int)vv.size() ); - return vv[i].total(); - } - return size(i).area(); } @@ -750,7 +736,7 @@ bool _InputArray::isContinuous(int i) const if( k == CUDA_GPU_MAT ) return i < 0 ? ((const cuda::GpuMat*)obj)->isContinuous() : true; - CV_Error(cv::Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(cv::Error::StsNotImplemented, "Unknown/unsupported array type"); } bool _InputArray::isSubmatrix(int i) const From b43783716f492d72a36d9acd0763309203300d13 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Mon, 18 Nov 2024 23:26:03 +0000 Subject: [PATCH 10/19] adds `_ArrayOpsBase::isContinuous` --- .../core/include/opencv2/core/array_helpers.hpp | 15 +++++++++++++++ modules/core/src/matrix_wrap.cpp | 16 ++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 3b1146da0e5c..212fa4f223ed 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -58,6 +58,7 @@ struct _ArrayOpsBase { virtual int sizend(const _InputArray& self, int* arraySize, int i) const = 0; virtual int type(const _InputArray& self, int i) const = 0; virtual std::size_t total(const _InputArray& self, int i) const = 0; + virtual int isContinuous(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -317,6 +318,20 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int isContinuous(const _InputArray& self, const int i) const final + { + auto& v = get(self.getObj()); + using value_type = typename T::value_type; + if constexpr (is_Mat || is_UMat) { + CV_Assert(i >= 0); + CV_Assert(i < static_cast(v.size())); + return v[i].isContinuous(); + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 398a55150014..50237d869048 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -712,11 +712,10 @@ bool _InputArray::isContinuous(int i) const k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return true; - if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT ) { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].isContinuous(); + CV_Assert(ops != nullptr); + return ops->isContinuous(*this, i); } if( k == STD_ARRAY_MAT ) @@ -726,17 +725,10 @@ bool _InputArray::isContinuous(int i) const return vv[i].isContinuous(); } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].isContinuous(); - } - if( k == CUDA_GPU_MAT ) return i < 0 ? ((const cuda::GpuMat*)obj)->isContinuous() : true; - CV_Error(cv::Error::StsNotImplemented, "Unknown/unsupported array type"); + CV_Error(cv::Error::StsNotImplemented, "Unknown/unsupported array type"); } bool _InputArray::isSubmatrix(int i) const From 675654289e2e9149e5d25199aafec2a2fe51b453 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Tue, 19 Nov 2024 17:36:21 +0000 Subject: [PATCH 11/19] adds `_ArrayOps::isSubmatrix` --- .../core/include/opencv2/core/array_helpers.hpp | 15 +++++++++++++++ modules/core/src/matrix_wrap.cpp | 14 +++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 212fa4f223ed..ff96c9cd3f51 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -59,6 +59,7 @@ struct _ArrayOpsBase { virtual int type(const _InputArray& self, int i) const = 0; virtual std::size_t total(const _InputArray& self, int i) const = 0; virtual int isContinuous(const _InputArray& self, int i) const = 0; + virtual int isSubmatrix(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -332,6 +333,20 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int isSubmatrix(const _InputArray& self, const int i) const final + { + using value_type = typename T::value_type; + if constexpr (is_Mat || is_UMat) { + T& v = get(self.getObj()); + CV_Assert(i >= 0); + CV_Assert(i < static_cast(v.size())); + return v[i].isSubmatrix(); + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 50237d869048..6f554d2a278f 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -745,11 +745,10 @@ bool _InputArray::isSubmatrix(int i) const k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return false; - if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT ) { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].isSubmatrix(); + CV_Assert(ops != nullptr); + return ops->isSubmatrix(*this, i); } if( k == STD_ARRAY_MAT ) @@ -759,13 +758,6 @@ bool _InputArray::isSubmatrix(int i) const return vv[i].isSubmatrix(); } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].isSubmatrix(); - } - CV_Error(cv::Error::StsNotImplemented, ""); } From 8b14672c4489ec8869bdaa71978127b31c259e9b Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Tue, 19 Nov 2024 18:19:53 +0000 Subject: [PATCH 12/19] adds `_ArrayOps::empty` --- .../include/opencv2/core/array_helpers.hpp | 21 +++++++ modules/core/src/matrix_wrap.cpp | 61 ++++--------------- 2 files changed, 32 insertions(+), 50 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index ff96c9cd3f51..287814036bb3 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -60,6 +60,8 @@ struct _ArrayOpsBase { virtual std::size_t total(const _InputArray& self, int i) const = 0; virtual int isContinuous(const _InputArray& self, int i) const = 0; virtual int isSubmatrix(const _InputArray& self, int i) const = 0; + virtual int empty(const _InputArray& self) const = 0; + virtual int empty(const _InputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -347,6 +349,25 @@ struct _ArrayOps final : _ArrayOpsBase { } } + int empty(const _InputArray& self) const final + { + return get(self.getObj()).empty(); + } + + int empty(const _InputArray& self, const int i) const final + { + using value_type = typename T::value_type; + const T& v = get(self.getObj()); + if constexpr (is_Mat || is_UMat || is_vector) { + CV_Assert(i >= 0); + CV_Assert(i < static_cast(v.size())); + return v[i].empty(); + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 6f554d2a278f..6e26a17801d1 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -405,23 +405,14 @@ int _InputArray::sizend(int* arrsz, int i) const bool _InputArray::empty(int i) const { - _InputArray::KindFlag k = kind(); if (i >= 0) { - if (k == STD_VECTOR_MAT) { - auto mv = reinterpret_cast*>(obj); - CV_Assert((size_t)i < mv->size()); - return mv->at(i).empty(); - } - else if (k == STD_VECTOR_MAT) { - auto umv = reinterpret_cast*>(obj); - CV_Assert((size_t)i < umv->size()); - return umv->at(i).empty(); - } - else if (k == STD_VECTOR_VECTOR) { - auto vv = reinterpret_cast >*>(obj); - CV_Assert((size_t)i < vv->size()); - return vv->at(i).empty(); - } else { + switch (_InputArray::KindFlag k = kind(); k) { + case STD_VECTOR_MAT: + case STD_VECTOR_UMAT: + case STD_VECTOR_VECTOR: + CV_Assert(ops != nullptr); + return ops->empty(*this, i); + default: CV_Error(Error::StsNotImplemented, ""); } } @@ -642,56 +633,26 @@ bool _InputArray::empty() const if (k == MATX) return false; - if( k == STD_VECTOR ) - { - const std::vector& v = *(const std::vector*)obj; - return v.empty(); - } - - if( k == STD_BOOL_VECTOR ) - { - const std::vector& v = *(const std::vector*)obj; - return v.empty(); + if (k == STD_VECTOR || k == STD_BOOL_VECTOR || k == STD_VECTOR_VECTOR || k == STD_VECTOR_MAT || + k == STD_VECTOR_UMAT || k == STD_VECTOR_CUDA_GPU_MAT) { + CV_Assert(ops != nullptr); + return ops->empty(*this); } if( k == NONE ) return true; - if( k == STD_VECTOR_VECTOR ) - { - const std::vector >& vv = *(const std::vector >*)obj; - return vv.empty(); - } - - if( k == STD_VECTOR_MAT ) - { - const std::vector& vv = *(const std::vector*)obj; - 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; - return vv.empty(); - } - if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->empty(); if( k == CUDA_GPU_MAT ) return ((const cuda::GpuMat*)obj)->empty(); - if (k == STD_VECTOR_CUDA_GPU_MAT) - { - const std::vector& vv = *(const std::vector*)obj; - return vv.empty(); - } - if( k == CUDA_HOST_MEM ) return ((const cuda::HostMem*)obj)->empty(); From ce84aa8063ebce3bc48c8b1ebd8a367a0bf5ca3e Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Tue, 19 Nov 2024 18:20:16 +0000 Subject: [PATCH 13/19] adds `_ArrayOps::offset` --- .../include/opencv2/core/array_helpers.hpp | 21 +++++++++++++ modules/core/src/matrix_wrap.cpp | 30 +++++++------------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 287814036bb3..84fcc2938644 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -62,6 +62,7 @@ struct _ArrayOpsBase { virtual int isSubmatrix(const _InputArray& self, int i) const = 0; virtual int empty(const _InputArray& self) const = 0; virtual int empty(const _InputArray& self, int i) const = 0; + virtual std::size_t offset(const _InputArray& self, std::size_t i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -368,6 +369,23 @@ struct _ArrayOps final : _ArrayOpsBase { } } + std::size_t offset(const _InputArray& self, const std::size_t i) const final + { + using value_type = typename T::value_type; + const T& v = get(self.getObj()); + CV_Assert(i < v.size()); + + if constexpr (is_Mat) { + return static_cast(v[i].ptr() - v[i].datastart); + } + else if constexpr (is_UMat) { + return v[i].offset; + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); @@ -388,6 +406,9 @@ Size _ArrayOps>::size(const _InputArray& self, const i template<> int _ArrayOps>::sizend(const _InputArray& self, int* const arraySize, const int i) const; +template<> +std::size_t _ArrayOps>::offset(const _InputArray& self, const std::size_t i) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 6e26a17801d1..d21fe26a6384 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -743,12 +743,10 @@ size_t _InputArray::offset(int i) const k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; - if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT || k == STD_VECTOR_CUDA_GPU_MAT ) { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert( i >= 0 && i < (int)vv.size() ); - - return (size_t)(vv[i].ptr() - vv[i].datastart); + CV_Assert(ops != nullptr); + return ops->offset(*this, i); } if( k == STD_ARRAY_MAT ) @@ -758,13 +756,6 @@ size_t _InputArray::offset(int i) const return (size_t)(vv[i].ptr() - vv[i].datastart); } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].offset; - } - if( k == CUDA_GPU_MAT ) { CV_Assert( i < 0 ); @@ -772,13 +763,6 @@ size_t _InputArray::offset(int i) const return (size_t)(m->data - m->datastart); } - if (k == STD_VECTOR_CUDA_GPU_MAT) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return (size_t)(vv[i].data - vv[i].datastart); - } - CV_Error(Error::StsNotImplemented, ""); } @@ -1953,4 +1937,12 @@ template<> } } +template<> +[[gnu::visibility("default")]] std::size_t _ArrayOps>::offset(const _InputArray& self, const std::size_t i) const +{ + const std::vector& v = get(self.getObj()); + CV_Assert(i < v.size()); + return static_cast(v[i].data - v[i].datastart); +} + } // cv:: From 86d3e755d17d6f1ca295f31060b5f2e454fa5266 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Tue, 19 Nov 2024 18:28:18 +0000 Subject: [PATCH 14/19] add `_ArrayOps::step` --- .../include/opencv2/core/array_helpers.hpp | 18 ++++++++++++ modules/core/src/matrix_wrap.cpp | 28 ++++++++----------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 84fcc2938644..8dfb15450814 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -63,6 +63,7 @@ struct _ArrayOpsBase { virtual int empty(const _InputArray& self) const = 0; virtual int empty(const _InputArray& self, int i) const = 0; virtual std::size_t offset(const _InputArray& self, std::size_t i) const = 0; + virtual std::size_t step(const _InputArray& self, std::size_t i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -386,6 +387,20 @@ struct _ArrayOps final : _ArrayOpsBase { } } + std::size_t step(const _InputArray& self, const std::size_t i) const final + { + using value_type = typename T::value_type; + const auto& v = get(self.getObj()); + CV_Assert(i < v.size()); + + if constexpr (is_Mat || is_UMat) { + return v[i].step; + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); @@ -409,6 +424,9 @@ int _ArrayOps>::sizend(const _InputArray& self, int* c template<> std::size_t _ArrayOps>::offset(const _InputArray& self, const std::size_t i) const; +template<> +std::size_t _ArrayOps>::step(const _InputArray& self, const std::size_t i) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index d21fe26a6384..fdb44e4121b3 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -786,11 +786,10 @@ size_t _InputArray::step(int i) const k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; - if( k == STD_VECTOR_MAT ) + if( k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT || k == STD_VECTOR_CUDA_GPU_MAT ) { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert( i >= 0 && i < (int)vv.size() ); - return vv[i].step; + CV_Assert(ops != nullptr); + return ops->step(*this, i); } if( k == STD_ARRAY_MAT ) @@ -800,24 +799,11 @@ size_t _InputArray::step(int i) const return vv[i].step; } - if( k == STD_VECTOR_UMAT ) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].step; - } - if( k == CUDA_GPU_MAT ) { CV_Assert( i < 0 ); return ((const cuda::GpuMat*)obj)->step; } - if (k == STD_VECTOR_CUDA_GPU_MAT) - { - const std::vector& vv = *(const std::vector*)obj; - CV_Assert(i >= 0 && (size_t)i < vv.size()); - return vv[i].step; - } CV_Error(Error::StsNotImplemented, ""); } @@ -1945,4 +1931,12 @@ template<> return static_cast(v[i].data - v[i].datastart); } +template<> +[[gnu::visibility("default")]] std::size_t _ArrayOps>::step(const _InputArray& self, const std::size_t i) const +{ + const std::vector& v = get(self.getObj()); + CV_Assert(i < v.size()); + return v[i].step; +} + } // cv:: From b9f61c672adeb8eb6fc535ab9a41d09f741bc1ca Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 20 Nov 2024 21:25:51 +0000 Subject: [PATCH 15/19] adds `_ArrayOps::create` --- .../include/opencv2/core/array_helpers.hpp | 147 ++++++++++ modules/core/src/matrix_wrap.cpp | 254 ++---------------- 2 files changed, 175 insertions(+), 226 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 8dfb15450814..47b1c6c26b20 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -64,6 +64,14 @@ struct _ArrayOpsBase { virtual int empty(const _InputArray& self, int i) const = 0; virtual std::size_t offset(const _InputArray& self, std::size_t i) const = 0; virtual std::size_t step(const _InputArray& self, std::size_t i) const = 0; + + virtual void create(const _OutputArray& arr, + int d, + const int* sizes, + int mtype, + int i, + bool allowTransposed, + _OutputArray::DepthMask fixedDepthMask) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -401,6 +409,108 @@ struct _ArrayOps final : _ArrayOpsBase { } } + void create(const _OutputArray& arr, + const int d, + const int* const sizes, + int mtype, + const int i, + const bool allowTransposed, + const _OutputArray::DepthMask fixedDepthMask) const final + { + using value_type = typename T::value_type; + auto& v = get(arr.getObj()); + + if constexpr (is_Mat || is_UMat) { + if (i < 0) { + CV_Assert(d == 2); + CV_Assert(sizes[0] == 1 || sizes[1] == 1 || sizes[0] * sizes[1] == 0); + const std::size_t len = sizes[0] * sizes[1] > 0 ? sizes[0] + sizes[1] - 1 : 0; + const std::size_t len0 = v.size(); + + CV_Assert(!arr.fixedSize() || len == len0); + v.resize(len); + if (arr.fixedType()) { + const int _type = CV_MAT_TYPE(arr.getFlags()); + for (std::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 < static_cast(v.size())); + auto& m = mattify(v[i]); + + if (allowTransposed) { + if (!m.isContinuous()) { + CV_Assert(!arr.fixedType() && !arr.fixedSize()); + m.release(); + } + + const bool same_type = m.type() == mtype; + const bool same_dimensions = d == 2 && m.dims == 2 && m.rows == sizes[1] && m.cols == sizes[0]; + if (get_data(m) != nullptr && same_type && same_dimensions) { + return; + } + } + + if (arr.fixedType()) { + const bool same_channels = CV_MAT_CN(mtype) == m.channels(); + const bool has_depth = ((1 << CV_MAT_TYPE(arr.getFlags())) & fixedDepthMask) != 0; + if (same_channels && has_depth) { + mtype = m.type(); + } + else { + CV_Assert(CV_MAT_TYPE(mtype) == m.type()); + } + } + + if (arr.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; + } + else if constexpr (!std::is_same_v) { + const int size0 = d > 0 ? sizes[0] : 1; + const int size1 = d > 1 ? sizes[1] : 1; + CV_Assert(d <= 2); + CV_Assert(size0 == 1 || size1 == 1 || size0 * size1 == 0); + + const std::size_t len = size0 * size1 > 0 ? size0 + size1 - 1 : 0; + + if constexpr (is_vector) { + if (i < 0) { + CV_Assert(!arr.fixedSize() || len == v.size()); + v.resize(len); + return; + } + + CV_Assert(i < static_cast(v.size())); + v[i].resize(len); + } + else { + CV_Assert(i < 0); + const int type0 = CV_MAT_TYPE(arr.getFlags()); + CV_Assert(mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0)); + v.resize(len); + } + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); @@ -410,6 +520,34 @@ struct _ArrayOps final : _ArrayOpsBase { { return *static_cast(data); } + + template + static auto get_data(U& m) + { + if constexpr (is_Mat) { + return m.data; + } + else if constexpr (is_UMat) { + return m.u; + } + else { + CV_Assert(false && "unreachable"); + } + } + + template + static auto& mattify(U& m) + { + if constexpr (is_Mat) { + return static_cast(m); + } + else if constexpr (is_UMat) { + return m; + } + else { + CV_Assert(false && "unreachable"); + } + } }; template<> @@ -427,6 +565,15 @@ std::size_t _ArrayOps>::offset(const _InputArray& self template<> std::size_t _ArrayOps>::step(const _InputArray& self, const std::size_t i) const; +template<> +void _ArrayOps>::create(const _OutputArray& arr, + int d, + const int* sizes, + int mtype, + int i, + bool allowTransposed, + _OutputArray::DepthMask fixedDepthMask) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index fdb44e4121b3..19713c25f080 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -1064,107 +1064,10 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, return; } - if( k == STD_VECTOR || k == STD_VECTOR_VECTOR ) + if( k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT ) { - CV_Assert( d <= 2 && (size0 == 1 || size1 == 1 || size0*size1 == 0) ); - size_t len = size0*size1 > 0 ? size0 + size1 - 1 : 0; - std::vector* v = (std::vector*)obj; - - if( k == STD_VECTOR_VECTOR ) - { - std::vector >& vv = *(std::vector >*)obj; - if( i < 0 ) - { - CV_Assert(!fixedSize() || len == vv.size()); - vv.resize(len); - return; - } - CV_Assert( i < (int)vv.size() ); - v = &vv[i]; - } - else - CV_Assert( i < 0 ); - - int type0 = CV_MAT_TYPE(flags); - CV_Assert( mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) ); - - int esz = CV_ELEM_SIZE(type0); - CV_Assert(!fixedSize() || len == ((std::vector*)v)->size() / esz); - switch( esz ) - { - case 1: - ((std::vector*)v)->resize(len); - break; - case 2: - ((std::vector*)v)->resize(len); - break; - case 3: - ((std::vector*)v)->resize(len); - break; - case 4: - ((std::vector*)v)->resize(len); - break; - case 6: - ((std::vector*)v)->resize(len); - break; - case 8: - ((std::vector*)v)->resize(len); - break; - case 12: - ((std::vector*)v)->resize(len); - break; - case 16: - ((std::vector*)v)->resize(len); - break; - case 20: - ((std::vector >*)v)->resize(len); - break; - case 24: - ((std::vector*)v)->resize(len); - break; - case 28: - ((std::vector >*)v)->resize(len); - break; - case 32: - ((std::vector*)v)->resize(len); - break; - case 36: - ((std::vector >*)v)->resize(len); - break; - case 40: - ((std::vector >*)v)->resize(len); - break; - case 44: - ((std::vector >*)v)->resize(len); - break; - case 48: - ((std::vector >*)v)->resize(len); - break; - case 52: - ((std::vector >*)v)->resize(len); - break; - case 56: - ((std::vector >*)v)->resize(len); - break; - case 60: - ((std::vector >*)v)->resize(len); - break; - case 64: - ((std::vector >*)v)->resize(len); - break; - case 128: - ((std::vector >*)v)->resize(len); - break; - case 256: - ((std::vector >*)v)->resize(len); - break; - case 512: - ((std::vector >*)v)->resize(len); - break; - default: - CV_Error_(cv::Error::StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz)); - } - return; + CV_Assert(ops != nullptr); + return ops->create(*this, d, sizes, mtype, i, allowTransposed, fixedDepthMask); } if( k == NONE ) @@ -1172,65 +1075,6 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, CV_Error(cv::Error::StsNullPtr, "create() called for the missing output array" ); } - if( k == STD_VECTOR_MAT ) - { - std::vector& v = *(std::vector*)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 = v.size(); - - CV_Assert(!fixedSize() || len == len0); - v.resize(len); - 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 < (int)v.size() ); - 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_ARRAY_MAT ) { Mat* v = (Mat*)obj; @@ -1290,73 +1134,6 @@ void _OutputArray::create(int d, const int* sizes, int mtype, int i, return; } - if( k == STD_VECTOR_UMAT ) - { - std::vector& v = *(std::vector*)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 = v.size(); - - CV_Assert(!fixedSize() || len == len0); - v.resize(len); - 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 < (int)v.size() ); - UMat& m = v[i]; - - if( allowTransposed ) - { - if( !m.isContinuous() ) - { - CV_Assert(!fixedType() && !fixedSize()); - m.release(); - } - - if( d == 2 && m.dims == 2 && m.u && - 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 == CUDA_GPU_MAT || k == CUDA_HOST_MEM) && d <= 2 && - i < 0 && !allowTransposed && fixedDepthMask == 0) - { - create((d < 2 ? 1 : sizes[0]), (d < 1 ? 1 : sizes[d > 1]), - mtype, i, allowTransposed, fixedDepthMask); - return; - } - CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } @@ -1939,4 +1716,29 @@ template<> return v[i].step; } +template<> +[[gnu::visibility("default")]] +void _ArrayOps>::create(const _OutputArray& arr, + const int d, + const int* const sizes, + int mtype, + const int i, + bool /*allowTransposed*/, + const _OutputArray::DepthMask fixedDepthMask) const +{ + std::vector& v = get(arr.getObj()); + const int size0 = d > 0 ? sizes[0] : 1; + const int size1 = d > 1 ? sizes[1] : 1; + CV_Assert(d <= 2); + CV_Assert(size0 == 1 || size1 == 1 || size0 * size1 == 0); + + const std::size_t len = size0 * size1 > 0 ? size0 + size1 - 1 : 0; + + CV_Assert(i < 0); + const int type0 = CV_MAT_TYPE(arr.getFlags()); + CV_Assert(mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && + ((1 << type0) & fixedDepthMask) != 0)); + v.resize(len); +} + } // cv:: From 5f4804caf05409539c9fce61ed2c3f43a3f893b6 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 20 Nov 2024 23:56:09 +0000 Subject: [PATCH 16/19] adds `_ArrayOps::release` --- .../include/opencv2/core/array_helpers.hpp | 9 ++++ modules/core/src/matrix_wrap.cpp | 43 ++++++------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 47b1c6c26b20..bcc975f29645 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -72,6 +72,7 @@ struct _ArrayOpsBase { int i, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const = 0; + virtual void release(const _OutputArray& self) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -511,6 +512,11 @@ struct _ArrayOps final : _ArrayOpsBase { } } + void release(const _OutputArray& self) const override + { + get(self.getObj()).clear(); + } + static const T& get(const void* const data) { return *static_cast(data); @@ -574,6 +580,9 @@ void _ArrayOps>::create(const _OutputArray& arr, bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const; +template<> +void _ArrayOps>::release(const _OutputArray& self) const; + template inline constexpr _ArrayOps array_ops; diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 19713c25f080..3a0173615316 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -1286,38 +1286,13 @@ void _OutputArray::release() const if( k == NONE ) return; - if( k == STD_VECTOR ) + if( k == STD_VECTOR || k == STD_VECTOR_VECTOR || k == STD_VECTOR_MAT || k == STD_VECTOR_UMAT || + k == STD_VECTOR_CUDA_GPU_MAT ) { - create(Size(), CV_MAT_TYPE(flags)); - return; - } - - if( k == STD_VECTOR_VECTOR ) - { - ((std::vector >*)obj)->clear(); - return; - } - - if( k == STD_VECTOR_MAT ) - { - ((std::vector*)obj)->clear(); - return; + CV_Assert(ops != nullptr); + return ops->release(*this); } - if( k == STD_VECTOR_UMAT ) - { - ((std::vector*)obj)->clear(); - return; - } - if (k == STD_VECTOR_CUDA_GPU_MAT) - { -#ifdef HAVE_CUDA - ((std::vector*)obj)->clear(); - return; -#else - CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)"); -#endif - } CV_Error(Error::StsNotImplemented, "Unknown/unsupported array type"); } @@ -1741,4 +1716,14 @@ void _ArrayOps>::create(const _OutputArray& arr, v.resize(len); } +template<> +[[gnu::visibility("default")]] void _ArrayOps>::release(const _OutputArray& self) const +{ + if constexpr (!have_cuda) { + noCudaError(); + } else { + get(self.getObj()).clear(); + } +} + } // cv:: From 208386c0cf4a52f874e9e2f54754670246435f74 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 20 Nov 2024 23:57:11 +0000 Subject: [PATCH 17/19] adds `_ArrayOps::getMatRef` --- .../core/include/opencv2/core/array_helpers.hpp | 14 ++++++++++++++ modules/core/src/matrix_wrap.cpp | 5 ++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index bcc975f29645..17d1798822ce 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -73,6 +73,7 @@ struct _ArrayOpsBase { bool allowTransposed, _OutputArray::DepthMask fixedDepthMask) const = 0; virtual void release(const _OutputArray& self) const = 0; + virtual Mat& getMatRef(const _OutputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -517,6 +518,19 @@ struct _ArrayOps final : _ArrayOpsBase { get(self.getObj()).clear(); } + Mat& getMatRef(const _OutputArray& self, const int i) const final + { + if constexpr (is_Mat) { + CV_Assert(i >= 0); + T& v = get(self.getObj()); + CV_Assert(i < static_cast(v.size())); + return v[i]; + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 3a0173615316..63f71fb53045 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -1328,9 +1328,8 @@ Mat& _OutputArray::getMatRef(int i) const if( k == STD_VECTOR_MAT ) { - std::vector& v = *(std::vector*)obj; - CV_Assert( i < (int)v.size() ); - return v[i]; + CV_Assert(ops != nullptr); + return ops->getMatRef(*this, i); } else { From 01fb9bb00169e0ffa3ca4ed538c289da66d7e2f4 Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 20 Nov 2024 23:58:05 +0000 Subject: [PATCH 18/19] adds `_ArrayOps::getUMatRef` --- .../core/include/opencv2/core/array_helpers.hpp | 14 ++++++++++++++ modules/core/src/matrix_wrap.cpp | 5 ++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index 17d1798822ce..bd8858be7fa4 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -74,6 +74,7 @@ struct _ArrayOpsBase { _OutputArray::DepthMask fixedDepthMask) const = 0; virtual void release(const _OutputArray& self) const = 0; virtual Mat& getMatRef(const _OutputArray& self, int i) const = 0; + virtual UMat& getUMatRef(const _OutputArray& self, int i) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -531,6 +532,19 @@ struct _ArrayOps final : _ArrayOpsBase { } } + UMat& getUMatRef(const _OutputArray& self, const int i) const final + { + if constexpr (is_UMat) { + CV_Assert(i >= 0); + T& v = get(self.getObj()); + CV_Assert(i < static_cast(v.size())); + return v[i]; + } + else { + CV_Assert(false && "unreachable"); + } + } + static const T& get(const void* const data) { return *static_cast(data); diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 63f71fb53045..559e382f3836 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -1350,9 +1350,8 @@ UMat& _OutputArray::getUMatRef(int i) const else { CV_Assert( k == STD_VECTOR_UMAT ); - std::vector& v = *(std::vector*)obj; - CV_Assert( i < (int)v.size() ); - return v[i]; + CV_Assert(ops != nullptr); + return ops->getUMatRef(*this, i); } } From c396012228179e9577da01d268d94bd65b50586b Mon Sep 17 00:00:00 2001 From: Christopher Di Bella Date: Wed, 20 Nov 2024 23:59:13 +0000 Subject: [PATCH 19/19] adds `_ArrayOps::assign` --- .../include/opencv2/core/array_helpers.hpp | 35 +++++++++++ modules/core/src/matrix_wrap.cpp | 58 ++----------------- 2 files changed, 41 insertions(+), 52 deletions(-) diff --git a/modules/core/include/opencv2/core/array_helpers.hpp b/modules/core/include/opencv2/core/array_helpers.hpp index bd8858be7fa4..241af6cb76e0 100644 --- a/modules/core/include/opencv2/core/array_helpers.hpp +++ b/modules/core/include/opencv2/core/array_helpers.hpp @@ -75,6 +75,8 @@ struct _ArrayOpsBase { virtual void release(const _OutputArray& self) const = 0; virtual Mat& getMatRef(const _OutputArray& self, int i) const = 0; virtual UMat& getUMatRef(const _OutputArray& self, int i) const = 0; + virtual void assign(const _OutputArray& self, const std::vector& other) const = 0; + virtual void assign(const _OutputArray& self, const std::vector& other) const = 0; protected: ~_ArrayOpsBase() = default; }; @@ -545,6 +547,16 @@ struct _ArrayOps final : _ArrayOpsBase { } } + void assign(const _OutputArray& self, const std::vector& other) const final + { + return assign_impl(self, other); + } + + void assign(const _OutputArray& self, const std::vector& other) const final + { + return assign_impl(self, other); + } + static const T& get(const void* const data) { return *static_cast(data); @@ -582,6 +594,29 @@ struct _ArrayOps final : _ArrayOpsBase { CV_Assert(false && "unreachable"); } } + + template + static void assign_impl(const _OutputArray& self, const std::vector& other) + { + using value_type = typename T::value_type; + if constexpr (is_Mat || is_UMat) { + auto& this_v = get(self.getObj()); + CV_Assert(this_v.size() == other.size()); + + for (std::size_t i = 0; i < other.size(); ++i) { + const auto& m = other[i]; + auto& this_m = this_v[i]; + if (this_m.u != nullptr && this_m.u == m.u) { + continue; + } + + m.copyTo(this_m); + } + } + else { + CV_Assert(false && "unreachable"); + } + } }; template<> diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 559e382f3836..123f89d8eaa1 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -1533,33 +1533,10 @@ void _OutputArray::move(Mat& m) const void _OutputArray::assign(const std::vector& v) const { _InputArray::KindFlag k = kind(); - if (k == STD_VECTOR_UMAT) + if (k == STD_VECTOR_UMAT || k == STD_VECTOR_MAT) { - std::vector& this_v = *(std::vector*)obj; - CV_Assert(this_v.size() == v.size()); - - for (size_t i = 0; i < v.size(); i++) - { - const UMat& m = v[i]; - UMat& this_m = this_v[i]; - if (this_m.u != NULL && this_m.u == m.u) - continue; // same object (see dnn::Layer::forward_fallback) - m.copyTo(this_m); - } - } - else if (k == STD_VECTOR_MAT) - { - std::vector& this_v = *(std::vector*)obj; - CV_Assert(this_v.size() == v.size()); - - for (size_t i = 0; i < v.size(); i++) - { - const UMat& m = v[i]; - Mat& this_m = this_v[i]; - if (this_m.u != NULL && this_m.u == m.u) - continue; // same object (see dnn::Layer::forward_fallback) - m.copyTo(this_m); - } + CV_Assert(ops != nullptr); + ops->assign(*this, v); } else { @@ -1571,33 +1548,10 @@ void _OutputArray::assign(const std::vector& v) const void _OutputArray::assign(const std::vector& v) const { _InputArray::KindFlag k = kind(); - if (k == STD_VECTOR_UMAT) + if (k == STD_VECTOR_UMAT || k == STD_VECTOR_MAT) { - std::vector& this_v = *(std::vector*)obj; - CV_Assert(this_v.size() == v.size()); - - for (size_t i = 0; i < v.size(); i++) - { - const Mat& m = v[i]; - UMat& this_m = this_v[i]; - if (this_m.u != NULL && this_m.u == m.u) - continue; // same object (see dnn::Layer::forward_fallback) - m.copyTo(this_m); - } - } - else if (k == STD_VECTOR_MAT) - { - std::vector& this_v = *(std::vector*)obj; - CV_Assert(this_v.size() == v.size()); - - for (size_t i = 0; i < v.size(); i++) - { - const Mat& m = v[i]; - Mat& this_m = this_v[i]; - if (this_m.u != NULL && this_m.u == m.u) - continue; // same object (see dnn::Layer::forward_fallback) - m.copyTo(this_m); - } + CV_Assert(ops != nullptr); + ops->assign(*this, v); } else {