数据结构操作与运算-CvMat数据结构

再来简单的介绍CvMat矩阵数据结构,这边矩阵数据结构就比IplImage数据结构简单些.

CvMat数据结构程序实例
#include <cv.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    float Array[]={1,2,3,4,5,6,7,8,9,10,11,12};
    CvMat Matrix1;
    Matrix1=cvMat(3,4,CV_32FC1,Array);

    printf("The type is : %d\n",Matrix1.type);
    printf("The depth is : %d\n",cvCvToIplDepth(Matrix1.type));
    printf("The step is : %d\n",Matrix1.step);
    printf("The rows is : %d\n",Matrix1.rows);
    printf("The cols is : %d\n",Matrix1.cols);
    cvmSet(&Matrix1,1,1,50);
    printf("The (1,1) is : %.1f\n\n",cvmGet(&Matrix1,1,1));

    for(int i=0;i<3;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%.1f\n",Matrix1.data.fl[i*Matrix1.cols+j]);
        }
    }

    system("pause");
}

执行结果:


一 开始,用一个一维数组填入信息,使用cvMat()初始化CvMat数据结构的矩阵类型,给它信道1的二维数组,这里制作了一个3*4的矩阵数据结构,而 实际上,CvMat仍然是存在一维数组里的,要看里面的数据则必须要像IplImage数据结构的使用方法一样,这个程序使用了信道1的矩阵结 构,32bits空间大小,列为3栏为4,Matrix1.type就是这个矩阵CV_8UC1的参数数据代号,是经由OpenCV的内部公式代换出来 的,cvCvToIplDepth()则是可以藉由公式转换回它的bit数(32bits),Matrix1.step则是矩阵空间的cols*参数类型 byte数*Channel数也就是它二维数组栏(Colunm)的总bytes长度,CvMat可以用cvmGet()跟cvmSet()存取数据,但 是他这边只能限定用float(32bits)跟double(64bits)的类型,其他uchar,int,short都不能用,但是CvMat可以 用循环直接存取的方式,而当使用了循环存取数据的方法,因为CvMat数据结构是使用union联集变量的方式,因此数据可以直接跟 uchar,short,int,float,double类型通用,data底下分别代表的变量名称为 ptr(uchar*),s(short*),i(int*),fl(float*),db(double*),但是要注意的是,cvMat()的数组喂 什么数据类型进去就要用什么样的数据类型读出来.


+号以下代表OpenCV常用类型,-号以下表示OpenCV内部使用的数据类型

下面是CvMat数据结构读取3个信道的个别矩阵质实做,与前面的IplImage数据结构相似.

CvMat数据结构读取矩阵数据
#include <cv.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    uchar Array[]={1,1,1,2,2,2,3,3,3,4,4,4,
                          5,5,5,6,6,6,7,7,7,8,8,8,
                          9,9,9,10,10,10,11,11,11,12,12,12};

    uchar Channel1[3][4];
    uchar Channel2[3][4];
    uchar Channel3[3][4];

    CvMat Matrix1;
    Matrix1=cvMat(3,4,CV_8UC3,Array);

    for(int i=0;i<3;i++)
    {
        for(int j=0;j<4*3;j=j+3)
        {
            Channel1[i][(int)j/3]=Matrix1.data.ptr[i*Matrix1.cols*3+j];
            Channel2[i][(int)j/3]=Matrix1.data.ptr[i*Matrix1.cols*3+j+1];
            Channel3[i][(int)j/3]=Matrix1.data.ptr[i*Matrix1.cols*3+j+2];
        }
    }
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%d\n",Channel3[i][j]);
        }
    }
    system("pause");
}

执行结果:


由上面的实例,CvMat数据结构的矩阵数据就可以轻易的读出来啦,要注意的是,使用uchar类型的话data就要用ptr,要不然读出来的数据是错误的,在去考虑它的信道个数来读取数据,因此3个信道的矩阵就可以很轻易的读出来了.

cvMat()
初始化CvMat矩阵数据结构,给它二维数组的维度,第一个为列(row),第二个为栏(column),第三个参数为矩阵参数,第四个参数为一维数组的数据输入,矩阵参数的种类为

CV_8UC1 CV_8SC1 CV_16UC1 CV_16SC1 CV_32SC1 CV_32FC1 CV_64FC1
CV_8UC2 CV_8SC2 CV_16UC2 CV_16SC2 CV_32SC2 CV_32FC2 CV_64FC2
CV_8UC3 CV_8SC3 CV_16UC3 CV_16SC3 CV_32SC3 CV_32FC3 CV_64FC3
CV_8UC4 CV_8SC4 CV_16UC4 CV_16SC4 CV_32SC4 CV_32FC4 CV_64FC4


参数的意义则要去参考前面的命名规则
cvMat(row数目,col数目,矩阵参数,一维数组数据)

cvCvToIplDepth()
输入CvMat的矩阵参数数据,可以得知它的深度,也就是一个矩阵被声明的空间大小,可以参考变量对应的部分做适当的分配
cvCvToIplDepth(CvMat矩阵参数代号数据)

cvmSet()
设立CvMat数据结构内的数值,设立的数值要为double类型,但是它只限订单信道矩阵使用.
cvmSet(CvMat数据结构,row列的数据,col栏的数据,double类型数值)

cvmGet()
取得CvMat数据结构内的数值,取得的数值为double类型,但是它只限订单信道使用.
cvmGet(CvMat数据结构,row列的数据,col栏的数据)