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;
}

 

posted @ 2017-09-03 21:32  gd_沐辰  阅读(316)  评论(0编辑  收藏  举报