三、Mat对象的-属性

1、Mat对象的作用

Mat类用于表示一个多维的单通道或者多通道的稠密数组(稠密与稀疏矩阵的稀疏相对)。它能够用来保存实数或复数的向量、矩阵、灰度或彩色图像,三维像素(voxel volumes),向量场(vector fields),点云(point clouds),张量(tensors),直方图(高维的直方图用SparseMat保存比较好)。
其实Mat就是存储多维矩阵的

2、Mat对象常用的属性

  • data uchar型的指针。Mat类分为了两个部分,矩阵头和指向矩阵数据部分的指针,data就是指向矩阵数据的指针
  • rows 矩阵的行数
  • cols 矩阵的列数
  • channels 矩阵元素具有的通道数
  • dims 矩阵的维度二维矩阵为2
  • size 矩阵的大小,size(cols,rows),Mat.size()返回的是[columu_number,row_number];注意返回的数据顺序是先列后行
    如果矩阵的维度大于2,则是返回size(-1,-1)
  • type表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量。
    其命名规则是
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]​
CV_ [每个通道的位数] [符号或无符号] [数据类型前缀] C [通道数]

下面是OpenCV中的宏定义:

CV_8UC1 - 0CV_8UC2 - 8CV_8UC3 - 16CV_8UC4 - 24
CV_8SC1 - 1CV_8SC2 - 9CV_8SC3 - 17CV_8SC4 - 25
CV_16UC1 - 2CV_16UC2 - 10CV_16UC3 - 18CV_16UC4 - 26
CV_16SC1 - 3CV_16SC2 - 11CV_16SC3 - 19CV_16SC4 - 27
CV_32SC1 - 4CV_32SC2 - 12CV_32SC3 - 20CV_32SC4 - 28
CV_32FC1 - 5CV_32FC2 - 13CV_32FC3 - 21CV_32FC4 - 29
CV_64FC1 - 6CV_64FC2 - 14CV_64FC3 - 22CV_64FC4 - 30

附:- i i的值为该类型计算出来的值。
注意:
1. F是浮点型数据,其中的C是固定的字符而不是char的C
2. 例如:CV_32SC2含义是32位有符号整数,通道数位2.
3. type一般是在创建Mat对象时设定,如果取得Mat元素的类型,则使用depth;如果是创建Mat则使用type。


type源码:

inline
int Mat::type() const
{
    return CV_MAT_TYPE(flags);
}

  • depth 矩阵中一个通道的数据类型,这个值衍生出type;
    将type的预定义值去掉通道信息就是depth的值
    例如:
    CV_64F、CV_32S、CV_16U、CV_8U

depth的源码

int Mat::depth() const
{
    return CV_MAT_DEPTH(flags);
}

  • elemSize: 矩阵中一个元素占用的字节数。
    如果矩阵的类型是CV_8UC3,那么elemSize = 8/8*3=3 bytes

  • elemSize1: 矩阵中一个通道占用的字节数。
    如果矩阵的类型是CV_8UC3,那么elemSize = 8/8=1 bytes

  • datastart和dataend:返回的是矩阵数据存储位置的头指针与尾指针。


上面属性的测试代码

Mat src(4, 5, CV_8UC4, Scalar_<uchar>(1, 2, 3, 4));

    cout << src << endl;
    cout << "src.channels:" << src.channels() << endl;
    cout << "src.type:" << src.type() << "   CV_16UC3:" << CV_8UC4 << endl;
    cout << "src.depth:" << src.depth() << "   CV_16UC:" << CV_8U << endl;

    cout << "compute:" <<(((CV_8U)&((1 << 3) - 1)) + (((4)-1) << 3)) << endl;//+、-的优先级有按位操作的优先级高

    cout << "src.elemSize:" << src.elemSize() << "   elemSize1:" <<src.elemSize1()<< endl;
    cout << "src.data:" << hex << (int *)src.data << endl;
    cout << "src.datastart:" << hex << (int *)src.datastart << "src.dataend:" << hex << (int *)src.dataend << endl;

上面的compute 是根据
MAKETYPE的宏定义得出来的公式

#define CV_CN_SHIFT   3

#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

#define CV_8U   0

#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)

#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)

#define CV_MAKETYPE(depth,
                    cn
                    ) (CV_MAT_DEPTH(depth)+(((cn)-1)<<CV_CN_SHIFT))
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)

CV_8UC3 的值为: ((CV_8U)&((1<<3)-1)+((cn)-1)<<3)=16
CV_8UC2 的值为:8
CV_8UC1 的值为:0

其中CV_8U是depth,cn是channels;


3、flags属性

flags:这个标志看它的注释,

 /*! includes several bit-fields:
         - the magic signature
         - continuity flag
         - depth
         - number of channels
     */
    int flags;

这个标志包含了the magic signature、submat flag、continuity flag、number of channels、depth。
flags.png
flags是占32个bit,从低到高:

  • 0~2 bit 表示depth,OpenCV中的数据类型共有8个,7个预定义类型,一个用户自定义类型。
#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_USRTYPE1 7
  • 3~11 bit 表示channels,OpenCV默认最大通道数为512,所以只需要9-bit就可以表示。
  • 0~11 bit 共同表示type。
  • 12~13 bit 暂时没有发现用处…
  • 14 bit 表示Mat的内存是否连续。一般有create创建的Mat均是连续的,如果是连续,将加快对数据的访问。
  • 15 bit 代表Mat是否为某一Mat的submatrix,一般通过ROI以及row(),col(),rowRange(),colRange()等得到的mat均为submatrix。
  • 16-31 bit 代表magic signature,暂理解为用来区分Mat的。

(1). 得到depth:

inline
int Mat::depth() const
{
    return CV_MAT_DEPTH(flags);
}

定义的宏

#define CV_CN_MAX     512
#define CV_CN_SHIFT   3
#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_USRTYPE1 7

#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)
#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)

由Mat.depth()调用该宏,**这组操作实际上就是取flags,0~2位来计算depth的。这个宏是把flags作为变量传入宏里的flags(值为图片类型的数据),与上面的compute的flags的值不一样(值是CV_8U)

(2). 得到channels

inline
int Mat::channels() const
{
    return CV_MAT_CN(flags);
}

定义的宏:

#define CV_CN_MAX     512
#define CV_CN_SHIFT   3
#define CV_MAT_CN_MASK          ((CV_CN_MAX - 1) << CV_CN_SHIFT)
#define CV_MAT_CN(flags)        ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1)

CV_CN_MAX - 1将通道的可能值变为[0,511],这样就能够用9位来表示所有的可能值,左移三位是为了关闭depth位
(3). 获取type:

inline
int Mat::type() const
{
    return CV_MAT_TYPE(flags);
}

定义的宏

#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
#define CV_MAKE_TYPE CV_MAKETYPE
//注释掉的是具体类型
/*
#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))

#define CV_8SC1 CV_MAKETYPE(CV_8S,1)
#define CV_8SC2 CV_MAKETYPE(CV_8S,2)
#define CV_8SC3 CV_MAKETYPE(CV_8S,3)
#define CV_8SC4 CV_MAKETYPE(CV_8S,4)
#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))

#define CV_16UC1 CV_MAKETYPE(CV_16U,1)
#define CV_16UC2 CV_MAKETYPE(CV_16U,2)
#define CV_16UC3 CV_MAKETYPE(CV_16U,3)
#define CV_16UC4 CV_MAKETYPE(CV_16U,4)
#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))

#define CV_16SC1 CV_MAKETYPE(CV_16S,1)
#define CV_16SC2 CV_MAKETYPE(CV_16S,2)
#define CV_16SC3 CV_MAKETYPE(CV_16S,3)
#define CV_16SC4 CV_MAKETYPE(CV_16S,4)
#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))

#define CV_32SC1 CV_MAKETYPE(CV_32S,1)
#define CV_32SC2 CV_MAKETYPE(CV_32S,2)
#define CV_32SC3 CV_MAKETYPE(CV_32S,3)
#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))

#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
#define CV_32FC4 CV_MAKETYPE(CV_32F,4)
#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))

#define CV_64FC1 CV_MAKETYPE(CV_64F,1)
#define CV_64FC2 CV_MAKETYPE(CV_64F,2)
#define CV_64FC3 CV_MAKETYPE(CV_64F,3)
#define CV_64FC4 CV_MAKETYPE(CV_64F,4)
#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))*/

#define CV_MAT_TYPE_MASK        (CV_DEPTH_MAX*CV_CN_MAX - 1)
#define CV_MAT_TYPE(flags)      ((flags) & CV_MAT_TYPE_MASK)

计算方式上述相似,开启0~11 bit的开关(8*512-1),得到flags低12位的值。
(4). 是否Continuous:

bool Mat::isContinuous() const
{
    return (flags & CONTINUOUS_FLAG) != 0;
}

定义与操作:

//枚举类型
enum { MAGIC_VAL  = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG };
    enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 };

//宏定义的操作
#define CV_MAT_CONT_FLAG_SHIFT  14
#define CV_MAT_CONT_FLAG        (1 << CV_MAT_CONT_FLAG_SHIFT)
#define CV_IS_MAT_CONT(flags)   ((flags) & CV_MAT_CONT_FLAG)
#define CV_IS_CONT_MAT          CV_IS_MAT_CONT

方式与上相同。

(5). 是否为Submatrix

inline
bool Mat::isSubmatrix() const
{
    return (flags & SUBMATRIX_FLAG) != 0;
}

定义与操作:

//定义在上面的那个枚举那

#define CV_SUBMAT_FLAG_SHIFT    15
#define CV_SUBMAT_FLAG          (1 << CV_SUBMAT_FLAG_SHIFT)
#define CV_IS_SUBMAT(flags)     ((flags) & CV_MAT_SUBMAT_FLAG)

isContinuous和isSubmartix的用法

    cout << "src.isContinuous: " << src.isContinuous() << endl;
    cout << "src.isSubmatrix: " << src.isSubmatrix() << endl;

这里介绍了channels,depth,type怎么得到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值