OpenCV中CvMat的初始化[转]

时间:2021-10-20 19:48:39

一)cvCreateMat创建和分配数据
CvCreateMat会创建CvMat,并为CvMat分配数据。cvCreateMat可以配合cvInitMatHeader来初始化CvMat对象。
因为CvCreateMat创建的CvMat,对象在堆上,数据也在堆上,所以cvInitMatHeader在指定新的数据所在的位置的同时,也将CvMat::hdr_refcount和CvMat::refcount都置为0,以便cvReleaseMat释放CvMat对象和数据。

#include <cv.h>
#include <stdio.h>
int main()
{
double a[9]={1,2,3,4,5,6,7,8,9};
double* data=0;

CvMat *pm=cvCreateMat(3,3,CV_64FC1);
cvInitMatHeader(pm,3,3,CV_64FC1,a);
data=pm->data.db;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

cvReleaseData(pm);
cvReleaseMat(&pm);

return 0;
}



二)cvCreateMatHeader创建
cvCreateMatHeader只会创建CvMat,不会为CvMat分配数据。cvCreateMatHeader可以配合cvInitMatHeader来初始化CvMat对象。
因为cvCreateMatHeader创建的CvMat,对象在堆上,所以cvInitMatHeader在指定新的数据所在的位置的同时,也将CvMat::hdr_refcount置为0,以便cvReleaseMat释放CvMat对象和数据。

#include <cv.h>
#include <stdio.h>
int main()
{
double a[9]={1,2,3,4,5,6,7,8,9};
double* data=0;

CvMat *pm=cvCreateMatHeader(3,3,CV_64FC1);
cvInitMatHeader(pm,3,3,CV_64FC1,a);
data=pm->data.db;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

cvReleaseData(pm);
cvReleaseMat(&pm);

return 0;
}


三)cvMat创建和初始化
cvMat可以视作是CvMat的构造函数,它是一个内联函数。cvMat可以为CvMat指定数据所在的位置。

cvMat在栈上创建CvMat,所以CvMat::hdr_refcount置为0。cvMat并未给CvMat分配数据(在堆上),而是直接传入已经创建好的数据(在堆上或在栈上),所以CvMat::refcount置为NULL。正因为前面两者,可以为一个CvMat变量多次使用cvMat(还可以使用cvInitMatHeader)而不用考虑内存泄露,最后用cvReleaseData释放堆上创建的CvMat对象,或称为矩阵头对象就可以了。

这一初始化方式类似于CvSize等的构造方式,只不过比它们复杂些(传入参数多且需要cvReleaseData来释放堆上创建的CvMat对象)。

cvMat和cvCreateMatHeader都是初始化CvMat头,都没有分配数据。他们的区别在于:
1)cvMat在栈上创建CvMat,cvCreateMatHeader在堆上创建CvMat
2)cvMat内头引用数置为0,cvCreateMatHeader内头引用数置为1。
3)cvMat可以指定数据所在位置,cvCreateMatHeader不能。
4)cvMat是内联函数,cvCreateMatHeader的错误处理机制更完善。

#include <cv.h>
#include <stdio.h>
int main()
{
double a[9]={1,2,3,4,5,6,7,8,9};
double b[6]={6,5,4,3,2,1};
double c[4]={4,3,2,1};
double* data=0;

CvMat m=cvMat(3,3,CV_64FC1,a);
data=m.data.db;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

//再次使用cvMat
m=cvMat(2,3,CV_64FC1,b);
data=m.data.db;
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

//使用cvMatcvInitMatHeader
cvInitMatHeader(&m,2,3,CV_64FC1,c,CV_AUTOSTEP);
data=m.data.db;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf("%3.lf",data[i*2+j]);
}
printf("\n");
}
printf("\n");

//cvReleaseData可以使CvMat::data.ptr置为NULL
//不能调用cvReleaseMat,因cvMat未给CvMat分配数据
cvReleaseData(&m);

return 0;
}


四)直接初始化

#include "cxcore.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC3);
cvZero(mat);

float *p = (float*)cvPtr2D(mat, 0, 0);
for(int i = 0; i < 9; i++)
{
*p = (float)i*10;
p++;
*p = (float)i*10+1;
p++;
*p = (float)i*10+2;
p++;
}

p = (float*)cvPtr2D(mat, 0, 0);

for(i = 0; i < 9; i++)
{
printf("%2.1f,%02.1f,%2.1f\t",*p,*(p+1),*(p+2));
p+=3;
if((i+1) % 3 == 0)
printf("\n");
}
}


五)cvInitMatHeader初始化
cvInitMatHeader并不创建CvMat对象,这个对象由用户创建(在堆上或栈上)并传入。cvInitMatHeader也不创建数据,也是作为参数传入。cvInitMatHeader利用传入的数据等参数初始化这个用户传入的CvMat

CvMat::hdr_refcount被置为0,不管传入的CvMat对象在堆上创建还是在栈上创建。CvMat::refcount被置为NULL,不管数据是否创建或指定。cvInitMatHeader可以为CvMat指定新的数据所在的位置。可以为一个CvMat变量多次使用cvInitMatHeader(还可以使用cvMat)。

cvInitMatHeader与cvMat和cvCreateMatHeader的最大区别在于前者不创建CvMat对象,后者创建CvMat对象。
cvInitMatHeader可以独立,也可以配合cvCreateMatHeader和cvCreateMat,来初始化CvMat

#include <cv.h>
#include <stdio.h>
int main()
{
double a[9]={1,2,3,4,5,6,7,8,9};
double b[6]={6,5,4,3,2,1};
double c[4]={4,3,2,1};
double* data=0;

CvMat m;
cvInitMatHeader(&m,3,3,CV_64FC1,a);
data=m.data.db;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

//再次使用cvInitMatHeader
cvInitMatHeader(&m,3,3,CV_64FC1,b);
data=m.data.db;
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
printf("%3.lf",data[i*3+j]);
}
printf("\n");
}
printf("\n");

//使用cvMat
m=cvMat(2,2,CV_64FC1,a);
data=m.data.db;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf("%3.lf",data[i*2+j]);
}
printf("\n");
}
printf("\n");

//cvReleaseData可以使CvMat::data.ptr置为NULL
//不能调用cvReleaseMat,因cvInitMatHeader未给CvMat分配数据
cvReleaseData(&m);

return 0;
}