您的位置:首页 > 运维架构

opencv矩阵元素类型

2012-12-18 14:23 176 查看
一基础

1 位移操作

移位操作有两种类型,一种是逻辑移位(logical shift)和算术移位(arithmetic shift)。逻辑移位中被移出的位被丢弃,空缺位(variant
bit)用0填充。算术移位中移出位被丢弃,空缺位用符号位填充。

在c/c++中,整数分为有符号和无符号两种类型,它们的移位操作有所区别。对于无符号整数,左移右移均采用逻辑移位;对于有符号整数,右移使用算术移位,左移使用逻辑移位。

所以对于有符号整数的右移,并不会改变整数的正负,但是左移中却有可能会改变。

2 负数存储

在机器里,有符号的整数的存储,对于负整数来说,它是用补码存储的,这里需要知道原码,反码和补码。原码指的本来的数据,反码则是对原码按位取反,补码则是对原码取反后加1,即补码=反码+1

以占两个字节长度的数据为例,它的取值范围是-32768-32767。

1000 0000 0000 0000(原码) --->0111 1111 1111 1111(反码)-->1000 0000 0000 0000(补码)

该补码的值是32768,因为它本来是负值,所以1000 0000 0000 0000(原码)表示的值即为-32768

1111 1111 1111 1111(原码)--->0000 0000 0000 0000(反码)-->0000 0000 0000 0001(补码),所以这里原码表示的值是-1

二 opencv矩阵元素类型

1 CV_MAKETYPE

创建矩阵的时候,有几个函数,下面是其中的

CvMat cvMat(introws,int
cols, inttype,void*data
CV_DEFAULT(NULL))

cvCreateMat( intheight,intwidth,
int type )

从这些函数可以看出,第三个参数type用来确定矩阵的类型,它是int类型的,在当前的32位程序中,它占4个字节。矩阵元素类型包括了两部分信息,首先是元素数据的类型,还有就是该元素包含的通道个数。

opencv中矩阵的类型有如下几种:

#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_8UC1 CV_MAKETYPE(CV_8U,1)
#define
CV_8UC2 CV_MAKETYPE(CV_8U,2)
....
#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_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_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_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_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_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_64FC(n)CV_MAKETYPE(CV_64F,(n))

这些数据类型都以宏的形式定义,它们的具体含义通过宏CV_MAKETYPE来确定,该宏包含两个参数,第一个参数指明数据的类型,第二个指明每个元素的通道数,每个元素至少需要有一个通道,直接使用CV_8U这样的类型表示的是一个通道。进一步查看它们的定义

#define CV_CN_MAX 512

#define
CV_CN_SHIFT 3
#define CV_DEPTH_MAX (1 <<CV_CN_SHIFT) //值为1000(2进制)

#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX- 1) //值为0111

#define CV_MAT_DEPTH(flags) ((flags) &CV_MAT_DEPTH_MASK)//取flags的低3位

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

在CV_MAKETYPE的使用过程中,cn的取值可以是1到n,n一般不超过CV_CN_MAX。(((cn)-1) <<CV_CN_SHIFT)得到的结果是低三位必然0,只有高于低三位的位才有值,也就是说CV_MAKETYPE(depth,cn)得到的结果有两部分组成,第一部分是低3位的数据,这部分数据指明了数据的类型,第二部分则是高于低3位的其他位,这部分指明了矩阵元素的通道个数,这两部分互补干扰。

同时该宏生成的数据被传递给int类型的参数,由于该宏中只包含左移操作,所以无需考虑符号位的问题。

2 其他常用宏

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

0010 0000 0000 - 1 -->0001 1111 1111<< 3 -->1111 1111 1000

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

这个操作是取出矩阵的通道个数,(flags) &
CV_MAT_CN_MASK)首先是取出通道位,为什么可以使用CV_MAT_CN_MASK <--((CV_CN_MAX - 1)<<CV_CN_SHIFT)来取出通道位呢,从上面的矩阵类型的定义宏可以看出

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

这里面就是((cn)-1) << CV_CN_SHIFT)定义了通道位,而又因为cn的值不超过CV_CN_MAX,所以可以使用(flags) & ((CV_CN_MAX - 1) << CV_CN_SHIFT)来取出通道位。CV_MAT_CN就是CV_MAKETYPE里计算通道的逆操作。

l #define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1)

值为8*512 -1 = 0001 0000 0000 0000 = 1111 1111 1111

可以用它来提取出表示矩阵类型的位,这里需要验证一下表示类型的数据的大小,也就是使用

max((cn-1)>> CV_CN_SHIFT) = (CV_CN_MAX-1)>> CV_CN_SHIFT= (0010 0000 0000-1)>>3 = (0001 1111 1111)>>3 = 1111 1111 1000

从这里可以看出,表示通道数的最大值如上,而表示数据类型的最大值为0111,所以表示矩阵元素类型的值的大小不超过11111111 1111,因而可以用掩码CV_MAT_TYPE_MASK提取出来

l #define CV_MAT_TYPE(flags) ((flags) &CV_MAT_TYPE_MASK)

使用取出表示矩阵元素类型的位,包括数据类型和通道数信息,也就是提取出使用CV_MAKETYPE(depth,cn)生成的数据

|#define CV_MAT_DEPTH(flags)

#define
CV_CN_SHIFT 3
#define CV_DEPTH_MAX (1 <<CV_CN_SHIFT) //值为1000(2进制)

#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX- 1) //值为0111

#define CV_MAT_DEPTH(flags) ((flags) &CV_MAT_DEPTH_MASK)//取flags的低3位

即该宏取数据的低三位,这三位表示的是单个通道对应的数据类型,最大值为7,表示用户自定义类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: