mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #27757 from vpisarev:matshape_inside_mat
Use MatShape instead of MatSize inside cv::Mat/cv::UMat #27757 **Merge together with https://github.com/opencv/opencv_contrib/pull/3996** --- This PR continues cv::Mat/cv::UMat refactoring. See #26056, where `MatShape` was introduced. Now it's put inside cv::Mat/cv::UMat instead of a weird `MatSize`. MatSize is now an alias for MatShape: **before:** ``` struct MatShape { ... }; struct MatSize { ... }; struct Mat { ... int dims; int rows; int cols; ... MatShape shape() const { ... /* constructs MatShape out of MatSize and returns it; layout is always 'unknown', because we don't store it */ } MatSize size; // size is not valid without the parent cv::Mat, // because size.p may point to Mat::rows or to Mat::cols, // depending on the dimensionality, and dims() returns Mat::dims. MatStep step; // may allocate memory, depending on the dimensionality. ... }; ``` **after:** ``` struct MatShape { ... }; typedef MatShape MatSize; // they are now synonyms struct Mat { ... int dims; int rows; int cols; ... MatShape shape() const { return size; } // just return the embedded shape (including the proper layout information) MatSize size; // size is self-contained data structure that can be used without the parent cv::Mat. // size.dims is now a copy of dims; size.p[*] contains copies of Mat::rows and Mat::cols when dims <= 2. MatStep step; // does not allocate extra memory buffers. ... }; ``` There are several reasons to do that: 1. the main reason is to be able to store data layout (MatShape::layout) inside each cv::Mat/cv::UMat. This is necessary for the proper shape inference in DNN module. In particular, it's necessary for the next step of DNN inference optimization where we introduce block-layout-optimized convolution and other operations. Later on, we can use layout information to support non-interleaved images (e.g. RRR...GGG...BBB...) or even batches of such images in core/imgproc modules. 2. the other reason is to represent 3D/4D/5D etc. tensors as cv::Mat/cv::UMat instances more conveniently, without extra dynamic memory allocation. Before this patch we allocated some memory buffers dynamically to store shape & steps for more than 2D arrays. Now the whole cv::Mat/cv::UMat header can be stored completely on stack/in a container. Creating another copy of Mat/UMat header is now done more efficiently. 3. the third reason is to introduce the new coding pattern: `dst.create(src.size, <dst_type>);`. The pattern is suitable for most of element-wise (including cloning) and filtering operations. This pattern does not only look crisp and self-documenting, it will also automatically copy shape (including layout) from the source tensor into the destination matrix/tensor. 4. in the future we might add `colorspace` member to MatShape that will allow to distinguish RGB from BGR or NV12. `dst.create(src.size, <dst_type>);` will then copy the colorspace information as well. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
+11
-11
@@ -187,7 +187,7 @@ void add(const Mat& _a, double alpha, const Mat& _b, double beta,
|
||||
if( ctype < 0 )
|
||||
ctype = a.depth();
|
||||
ctype = CV_MAKETYPE(CV_MAT_DEPTH(ctype), a.channels());
|
||||
c.create(a.dims, &a.size[0], ctype);
|
||||
c.create(a.size, ctype);
|
||||
const Mat *arrays[] = {&a, &b, &c, 0};
|
||||
Mat planes[3], buf[3];
|
||||
|
||||
@@ -349,7 +349,7 @@ void convert(const Mat& src, cv::OutputArray _dst,
|
||||
int ddepth = CV_MAT_DEPTH(dtype);
|
||||
|
||||
dtype = CV_MAKETYPE(ddepth, src.channels());
|
||||
_dst.create(src.dims, &src.size[0], dtype);
|
||||
_dst.create(src.size, dtype);
|
||||
Mat dst = _dst.getMat();
|
||||
if( alpha == 0 )
|
||||
{
|
||||
@@ -424,7 +424,7 @@ void convert(const Mat& src, cv::OutputArray _dst,
|
||||
|
||||
void copy(const Mat& src, Mat& dst, const Mat& mask, bool invertMask)
|
||||
{
|
||||
dst.create(src.dims, &src.size[0], src.type());
|
||||
dst.create(src.size, src.type());
|
||||
|
||||
if(mask.empty())
|
||||
{
|
||||
@@ -576,7 +576,7 @@ void insert(const Mat& src, Mat& dst, int coi)
|
||||
|
||||
void extract(const Mat& src, Mat& dst, int coi)
|
||||
{
|
||||
dst.create( src.dims, &src.size[0], src.depth() );
|
||||
dst.create( src.size, src.depth() );
|
||||
CV_Assert( 0 <= coi && coi < src.channels() );
|
||||
|
||||
const Mat* arrays[] = {&src, &dst, 0};
|
||||
@@ -1770,7 +1770,7 @@ void logicOp( const Mat& src1, const Mat& src2, Mat& dst, char op )
|
||||
{
|
||||
CV_Assert( op == '&' || op == '|' || op == '^' );
|
||||
CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
|
||||
dst.create( src1.dims, &src1.size[0], src1.type() );
|
||||
dst.create( src1.size, src1.type() );
|
||||
const Mat *arrays[]={&src1, &src2, &dst, 0};
|
||||
Mat planes[3];
|
||||
|
||||
@@ -1792,7 +1792,7 @@ void logicOp( const Mat& src1, const Mat& src2, Mat& dst, char op )
|
||||
void logicOp(const Mat& src, const Scalar& s, Mat& dst, char op)
|
||||
{
|
||||
CV_Assert( op == '&' || op == '|' || op == '^' || op == '~' );
|
||||
dst.create( src.dims, &src.size[0], src.type() );
|
||||
dst.create( src.size, src.type() );
|
||||
const Mat *arrays[]={&src, &dst, 0};
|
||||
Mat planes[2];
|
||||
|
||||
@@ -1887,7 +1887,7 @@ compareS_(const _Tp* src1, _WTp value, uchar* dst, size_t total, int cmpop)
|
||||
void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop)
|
||||
{
|
||||
CV_Assert( src1.type() == src2.type() && src1.channels() == 1 && src1.size == src2.size );
|
||||
dst.create( src1.dims, &src1.size[0], CV_8U );
|
||||
dst.create( src1.size, CV_8U );
|
||||
const Mat *arrays[]={&src1, &src2, &dst, 0};
|
||||
Mat planes[3];
|
||||
|
||||
@@ -1949,7 +1949,7 @@ void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop)
|
||||
void compare(const Mat& src, double value, Mat& dst, int cmpop)
|
||||
{
|
||||
CV_Assert( src.channels() == 1 );
|
||||
dst.create( src.dims, &src.size[0], CV_8U );
|
||||
dst.create( src.size, CV_8U );
|
||||
const Mat *arrays[]={&src, &dst, 0};
|
||||
Mat planes[2];
|
||||
|
||||
@@ -2749,7 +2749,7 @@ minmax16f_(const _Tp* src1, const _Tp* src2, _Tp* dst, size_t total, char op)
|
||||
|
||||
static void minmax(const Mat& src1, const Mat& src2, Mat& dst, char op)
|
||||
{
|
||||
dst.create(src1.dims, src1.size, src1.type());
|
||||
dst.create(src1.size, src1.type());
|
||||
CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
|
||||
const Mat *arrays[]={&src1, &src2, &dst, 0};
|
||||
Mat planes[3];
|
||||
@@ -2845,7 +2845,7 @@ minmax_16f(const _Tp* src1, _Tp val_, _Tp* dst, size_t total, char op)
|
||||
|
||||
static void minmax(const Mat& src1, double val, Mat& dst, char op)
|
||||
{
|
||||
dst.create(src1.dims, src1.size, src1.type());
|
||||
dst.create(src1.size, src1.type());
|
||||
const Mat *arrays[]={&src1, &dst, 0};
|
||||
Mat planes[2];
|
||||
|
||||
@@ -2947,7 +2947,7 @@ muldiv_16f(const _Tp* src1, const _Tp* src2, _Tp* dst, size_t total, double scal
|
||||
|
||||
static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, int ctype, double scale, char op)
|
||||
{
|
||||
dst.create(src2.dims, src2.size, (ctype >= 0 ? ctype : src2.type()));
|
||||
dst.create(src2.size, (ctype >= 0 ? ctype : src2.type()));
|
||||
CV_Assert( src1.empty() || (src1.type() == src2.type() && src1.size == src2.size) );
|
||||
const Mat *arrays[]={&src1, &src2, &dst, 0};
|
||||
Mat planes[3];
|
||||
|
||||
Reference in New Issue
Block a user