OpenCV中CvMat的初始化[转]

一)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("
");
	}
	printf("
");

	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("
");
	}
	printf("
");

	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("
");
	}
	printf("
");

	//再次使用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("
");
	}
	printf("
");

	//使用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("
");
	}
	printf("
");

	//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	",*p,*(p+1),*(p+2));
        p+=3;
        if((i+1) % 3 == 0)
            printf("
");
    }
}


五)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("
");
	}
	printf("
");

	//再次使用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("
");
	}
	printf("
");

	//使用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("
");
	}
	printf("
");

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

	return 0;
}
原文地址:https://www.cnblogs.com/xingrun/p/3404436.html