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