假设现有一维数组 Data[18]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};

通过 CvMat mat;创建一个CvMat对象。


情况1、cvInitMatHeader(&mat,3,6,CV_32FC1,data);//3行6列二维的32位浮点型单通道的矩阵

将一维数组转换为单通道二维矩阵

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


情况2、cvInitMatHeader(&mat,3,3,CV_32FC2,data);//3行3列二维的32位浮点型双通道的矩阵


转换为双通道二维矩阵

(1,2)

(3,4)

(5,6)

(7,8)

(9,10)

(11,12)

(13,14)

(15,16)

(17,18)



情况3、cvInitMatHeader(&mat,3,2,CV_32FC3,data);//3行2列二维的32位浮点型三通道的矩阵

转换为三通道二维矩阵

(1,2,3)

(4,5,6)

(7,8,9)

(10,11,12)

(13,14,15)

(16,17,18)



通道数,通俗的说,就是一个点上有几个数值

维数,代表一个点的表现方式,二维的就是两个数表示一个点,三维就是三个数表示一个点


可以通过cvGetReal2D(&mat,y,x);访问单通道中的元素,通过cvGet2D(&mat,y,x);访问多通道中的元素。但是通过函数去访问会存在栈溢出问题,为了防止这种情况,我们可以通过指针的方式去访问。

由于CvMat中的data是个联合体,访问它的时候,可以使用多种数据类型。如我们想要得到uchar类型的数据时,可以通过mat.data.ptr得到mat中的数据块首地址。

如果是情况1

value = *( (float*)(mat.data.ptr + mat.step*y ) +  x )

可以访问到第y行的第x列元素里面的值,step是Cvmat里面的一个元素,表示一行的字节数

如果是情况2

value[0] = *( (float*)(mat.data.ptr + mat.step*y ) + x*2 );
value[1] = *( (float*)(mat.data.ptr + mat.step*y ) +  (x*2+1) );

可以访问到第y行的第x列元素里面的值,x乘以2表示是双通道

如果是情况3

value[0] = *( (float*)(mat.data.ptr + mat.step*y ) +  x*3 );
value[1] = *( (float*)(mat.data.ptr + mat.step*y ) +  (x*3+1) );
value[2] = *( (float*)(mat.data.ptr + mat.step*y ) +  (x*3+2) );


可以访问到第y行的第x列元素里面的值

看视频的时候我很好奇,为什么要使用uchar类型的指针去访问,之后又强制转换成float类型指针。CvMat明明就有float类型的指针提供,为什么不直接用?

然后。我以情况1为实验,使用mat.data.fl为首地址,通过value = *( (mat.data.fl+ mat.step*y ) +  x )去访问。发现访问到第二行时就出现问题了。后来一想,好像和step有关。这个实验中,CvMat是32位浮点型,那么step = 6*4=24。mat.data.fl是浮点型指针,加上mat.step*y其实是加上了mat.step*y * sizeof(float)个字节。所以会出现问题,

接着,我把语句修改为value = *( (mat.data.fl+ mat.step*y / sizeof(float) ) +  x ),访问就没有问题了。我真是太机智了,哈哈哈哈哈~