opencv视频学习第九课(访问cvMat数据)笔记整理

时间:2022-04-10 21:51:09

假设现有一维数组 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 ),访问就没有问题了。我真是太机智了,哈哈哈哈哈~