【OpenCV】elemSize()、elemSize1()

在Mat类中有两个成员函数:elemSize()和elemSize1():

inline size_t Mat::elemSize() const { return dims > 0 ? step.p[dims-1] : 0; }
inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); }

先看第二个函数elemSize1(),该函数的作用是计算depth所占的字节数(与通道数无关)。可参考对应的内置类型Mat中的depth与对应的内置类型。根据其函数体可看出它其实是通过宏CV_ELEM_SIZE1()来工作的,来看看这个宏的细节

  1. /* Size of each channel item,

  2. 0x124489 = 1000 0100 0100 0010 0010 0001 0001 ~ array of sizeof(arr_type_elem) */ // 0x124489-->0x8442211

  3. #define CV_ELEM_SIZE1(type) ((((sizeof(size_t)<<28)|0x8442211) >> CV_MAT_DEPTH(type)*4) & 15)

首先说明一下个人觉得在注释中的0x124489应该是有问题的,貌似该改成0x8442211。接下来分析实现过程。

size_t是为了增强程序的可移植性,在我64位的系统上,如果编译32位程序的则sizeof(size_t)等于4,若编译64位程序的则sizeof(size_t)等于8,这里以8为例:

如图

对于宏CV_MAT_DEPTH(type),可以参考从Mat的flags中可以读到的信息,以及相关宏定义,取type=CV_8UC3为例。

则CV_MAT_DEPTH(CV_8UC3)等于0,过程如下图:

最后的结果为1,我们知道CV_8UC3对应的的depth是CV_8U,占8位,故字节数为1,这与计算结果是相吻合的。

对于宏CV_ELEM_SIZE1(type)的理解,重点还是掌握((sizeof(size_t)<<28)|0x8442211)的规律性,它与相应的depth是一一对应的。

接下来看函数elemSize(),其作用是计算Mat中单个像素点所占的字节数(与通道数有关)。根据其函数体来看,它是通过Mat的两个成员变量dim和step来实现,但实际上在Mat实例化对应时elemSize()也是通过宏来实现的,该宏为:

  1. /* 0x3a50 = 11 10 10 01 01 00 00 ~ array of log2(sizeof(arr_type_elem)) */

  2. #define CV_ELEM_SIZE(type) (CV_MAT_CN(type) << ((((sizeof(size_t)/4+1)*16384|0x3a50) >> CV_MAT_DEPTH(type)*2) & 3))

在此就不一步一步的分析了,主要说明一下0x3a50的作用:


0x3a50 = 11 10 10 01 01 00 00,对照上图的最后一行即可看出它的含义。

CV_ELEM_SIZE(type)=CV_MAT_CN(type)*CV_ELEM_SIZE1(type)=CV_MAT_CN(type)<<log2(CV_ELEM_SIZE1(type))。

即:Mat.elemSize() = Mat.elemSize1() * Mat.channels()。

特别注意当depth为CV_USRTYPE1的情形。

猜你喜欢

转载自blog.csdn.net/W614171629/article/details/81908513