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