7矩阵数据访问
矩阵数据访问
在上一讲中,我讲过用cvGet2D()来取得矩阵中的数值。
但是,调用函数还要不断分配内存空间。如果,数据非常大,500X500,那么内存空间够不够呢?
下面就介绍另一个方法,更高效率地访问矩阵。
C语言的优势就是拥有指针,可以直接对内存进行操作。
单通道:
与上一讲同样的例子:
float pArr[18]={10,15,20,25,30,35,
40,45,50,55,60,65,
70,75,80,85,90,95};
for(int y=0;y<mat.rows;++y)
{
float * pValue=(float *)(mat.data.ptr+mat.step*y);
for(int x=0;x<mat.cols;++x)
{
float Value=*(pValue+x);
printf("%f ",Value);
}
}
注意点:
1.mat.data.ptr是CvMat中的结构体成员。指向首地址。即指向10位置。
2.mat.step可以得到每一行的字节数,比如:第一行有6个float的数值,即
24个字节。那么mat.step=24.
难点:
当mat.data.pt=10,我们要mat.data.pt=40,如何做?
方法:因为数组在内存的的地址是连续的。10与40间相距24个字符。10与70间相距48个字节。即每一24个字节,而y就是行数。
所以:mat.data.ptr+mat.step*y 指向某一行
3.要找个一个数值,就要有具体的坐标,现在找了行数,就要找到列数。
float Value=*(pValue+x);
pValue 是一个指针。指针右移x列,即(y,x),再解引用,取值。
双通道例子:
float * pValue=(float *)(mat.data.ptr+mat.step*y);
int size=2
for(int y=0;y<mat.rows;++y)
{
float * pValue=(float *)(mat.data.ptr+mat.step*y);
float Value[2]={0};
for(int x=0;x<mat.cols;++x)
{
Value[0]=*(pValue+x*size);
Value[1]=*(pValue+x*size+1);
printf("(%f %f)",Value[0],Value[1]);
}
printf("\n");
}
注意点:
1.双通道的一个坐标点有2个数值,找行数可以与单通道一样。
float * pValue=(float *)(mat.data.ptr+mat.step*y);
2.找列数就有问题了。
此时,只有3列,每一列有2个float数,输出时,要同时输出第一数值、第二数值。
方法:
定义size,代表通道的数量,例子是双通道,size=2。
先找一个数值
Value[0]=*(pValue+x*size);
比如:
float pArr[10]={(10,15),(20,25),(30,35)}
X代表列数,pValue指向10。要指针指向20呢?
10与20间相距8个字节,刚好就是一个通道size。
所以,Value[0]=*(pValue+x*size);可以找所需要的某坐标的第一个数值。
双通道是2个数值的,在第一数值的基础上,再在移动一个数,float。就可以得到第二个数值了。。。。
单通道源代码: // cvND.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "stdio.h" #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; float pArr[18]={10,15,20,25,30,35, 40,45,50,55,60,65, 70,75,80,85,90,95}; int _tmain(int argc, _TCHAR* argv[]) { CvMat mat; cvInitMatHeader(&mat,3,6,CV_32FC1,pArr); for(int y=0;y<mat.rows;++y) { float * pValue=(float *)(mat.data.ptr+mat.step*y); for(int x=0;x<mat.cols;++x) { float Value=*(pValue+x); printf("%f ",Value); } printf("\n"); } system("pause"); return 0; }
双通道源代码; // cvND.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "stdio.h" #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; float pArr[18]={10,15,20,25,30,35, 40,45,50,55,60,65, 70,75,80,85,90,95}; int size=2; int _tmain(int argc, _TCHAR* argv[]) { CvMat mat; cvInitMatHeader(&mat,3,3,CV_32FC2,pArr); for(int y=0;y<mat.rows;++y) { float * pValue=(float *)(mat.data.ptr+mat.step*y); float Value[2]={0}; for(int x=0;x<mat.cols;++x) { Value[0]=*(pValue+x*size); Value[1]=*(pValue+x*size+1); printf("(%f %f)",Value[0],Value[1]); } printf("\n"); } system("pause"); return 0; }