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