Mat-成员变量的flags的含义

    在Mat中flags的定义如下:

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

    从其描述可以看到,flags是一个int型变量,占4字节内存,共32位,我们把最高位称为第32位,最低位称为第1位,存储的内容可以用来表示当前Mat类对象的depth、channels、magic signature以及continuity等信息,那具体是如何通过flags来获取这些信息呢?下面一一来看。首先看到的是如何获取depth。depth在Mat的定义中有如下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

    7种的话用二进制表示只用3个bit就可以表示了。在opencv中,depth不是一个成员变量,而获取depth的方法是通过以下函数:

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

    而其中CV_MAT_DEPTH(flags)是一个宏定义,其定义如下:

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

    而其中CV_MAT_DEPTH_MASK也是一个宏定义,其定义如下:

#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)

    而其中CV_DEPTH_MAX 还是一个宏定义,其定义如下:

#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

    而其中CV_CN_SHIFT依然是一个宏定义,其定义如下:

#define CV_CN_SHIFT   3

    吖的终于到底了。。这下就比较明朗了,3是一个字面值常量,在C++中是将其视为一个int型。那么CV_DEPTH_MAX 就是1 << 3,1也是一个字面值常量,有四个字节的空间,1的二进制表示为0000 0000 0000 0000 0000 0000 0000 0001,在左移3位之后,CV_DEPTH_MAX 的二进制表示为0000 0000 0000 0000 0000 0000 0000 1000,接着可以知道CV_MAT_DEPTH_MASK的值为0000 0000 0000 0000 0000 0000 0000 0111,最后可以知道获取depth即计算 (flags) & CV_MAT_DEPTH_MASK)的值,由于CV_MAT_DEPTH_MASK的最后三位为1,前面皆为0,所以最后flags与其相与的结果取等于前面29位都为0,后面三位是flags的最后三位,而这三位就可以表示Mat的7种depth了。因此得出结论:flags的第1位到第3位总共3bit表示depth。
    然后再来看看如何flags是如何表示channels的信息的。和depth一样,channels也不是Mat的一个成员变量,获取channels的唯一方法是通过以下函数:

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

    而CV_MAT_CN(flags)是一个宏定义,其定义如下:

#define CV_MAT_CN(flags)        ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1)

    而CV_MAT_CN_MASK和CV_CN_SHIFT都是宏定义,其各自的定义如下:

#define CV_MAT_CN_MASK          ((CV_CN_MAX - 1) << CV_CN_SHIFT)
#define CV_CN_SHIFT   3

    而CV_CN_MAX 还是一个宏定义,其定义如下:

#define CV_CN_MAX     512

    终于又到底了。。因为CV_CN_MAX是512,那么CV_MAT_CN_MASK是0000 0000 0000 0000 1111 1111 1000,那么channels就等于((((flags) & 0000 0000 0000 0000 1111 1111 1000) >> CV_CN_SHIFT) + 1),可以看到,最后的channels的 结果取决于flags的第4位到12位总共9bit表示channels,在Mat中channels的最大值为512,这个时候flags中的第4位到第12位为1111 1111 1。
    depth和channels信息共同构成了type信息,获取type的函数及其相关的宏定义如下:

inline int Mat::type() const { return CV_MAT_TYPE(flags); }
#define CV_MAT_TYPE(flags)      ((flags) & CV_MAT_TYPE_MASK)
#define CV_MAT_TYPE_MASK        (CV_DEPTH_MAX*CV_CN_MAX - 1)
#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)
#define CV_CN_SHIFT   3
#define CV_CN_MAX     512

    然后再来看看continuity这个信息,这个信息表示的是Mat的数组在内存中是否是连续存储的,它也不是以一个成员变量的形式表示,要想获取这个信息,必须通过以下函数:

bool isContinuous() const;

    其定义如下:

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

    而CONTINUOUS_FLAG是一个宏定义,其定义以如下:

CONTINUOUS_FLAG=CV_MAT_CONT_FLAG

    CV_MAT_CONT_FLAG也是一个宏定义,其定义如下:

#define CV_MAT_CONT_FLAG        (1 << CV_MAT_CONT_FLAG_SHIFT)

    而CV_MAT_CONT_FLAG_SHIFT 也是一个宏定义,其定义如下:

#define CV_MAT_CONT_FLAG_SHIFT  14

    然后开始反推回去,CV_MAT_CONT_FLAG等于0000 0000 0000 0000 0100 0000 0000 0000,所以CONTINUOUS_FLAG也等于0000 0000 0000 0000 0100 0000 0000 0000,最后isContinuous函数返回flags & 0000 0000 0000 0000 0100 0000 0000 0000) != 0,这是一个bool值,只有当flags的第15位是1时,返回true,如果flags的第15位是0时,返回false。因此得出结论:flags的第15位用来表示Mat在内存中的存储是否连续,且当其为1时表示连续存储,为0时表示不连续存储。
    这个flags还可以用于表示当前的Mat是否是另一个Mat的submatrix。用以下函数可以知道当前的Mat是否是另一个Mat的submatrix,其定义如下:

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

    而SUBMATRIX_FLAG是一个宏定义,其定义如下:

 SUBMATRIX_FLAG=CV_SUBMAT_FLAG

    而CV_SUBMAT_FLAG也是一个宏定义,其定义如下:

#define CV_SUBMAT_FLAG          (1 << CV_SUBMAT_FLAG_SHIFT)

    CV_SUBMAT_FLAG_SHIFT也是一个宏定义,其定义如下:

#define CV_SUBMAT_FLAG_SHIFT    15

    现在开始反推回去,CV_SUBMAT_FLAG等于0000 0000 0000 0000 1000 0000 0000 0000,所以 SUBMATRIX_FLAG也等于0000 0000 0000 0000 1000 0000 0000 0000,所以isSubmatrix函数返回flags & SUBMATRIX_FLAG) != 0,这是一个bool值,只有当flags的第16位是1时,返回true,为0时返回false。所以得出结论:flags的第16位用来表示当前矩阵是否是另一个矩阵的submatrix,如果该位是1则表示是,是0则表示不是。
    17到32位表示的是magic signature的信息,这个的用处我还没有看到,网上也有博客说是用来区分Mat的类型,如果Mat和SparseMat的,后面有看到它的用处再把这部分加上去吧。
    小结:
Mat-成员变量的flags的含义_第1张图片
从低位到高位:

1-3位代表depth即数据类型(如CV_8U),OpenCV的数据类型共7类,故只需3位即可全部表示。

4-12位代表通道数channels,因为opencv默认最大通道数为512,故只需要9位即可全部表示,可参照下面求通道数的部分。

1-12位共同代表type即通道数和数据类型(如CV_8UC3)

13-14位暂没发现用处,也许是留着后用,待发现了再补上。

15位代表Mat的内存是否连续,一般由creat创建的mat均是连续的,如果是连续,将加快对数据的访问。

16位代表该Mat是否为某一个Mat的submatrix,一般通过ROI以及row()、col()、rowRange()、colRange()等得到的mat均为submatrix。

17-32代表magic signature,暂理解为用来区分Mat的类型。

本博客部分内容来自http://blog.csdn.net/yiyuehuan/article/details/43701797

你可能感兴趣的:(OpenCV-Mat源码解析)