OpenCV中矩陣的定義(Learning OpenCV第三章) OpenCV是Intel?開源計算機視覺庫,。它由一系列 C 函數(shù)和少量 C++ 類構成,實現(xiàn)了圖像處理和計算機視覺方面的很多通用算法,。 關于OpenCV的基本使用,,大家可以去看網(wǎng)站http://www.。我這里是學習一本書Learning OpenCV時,所進行的資料整理,。 當使用OpenCV時,,你會經(jīng)常使用IplImage類型,該類型是OpenCV的基礎圖像類型,。圖像可能是灰度圖,,彩色圖,四通道圖(RGB+Alpha)等,,而每個通道可能是整數(shù)或浮點數(shù)類型,。OpenCV提供了對圖像的大量處理操作函數(shù)。 在我們討論IplImage之前,,我們需要看另一個數(shù)據(jù)類型:CvMat,即OpenCV的矩陣類型,。盡管OpenCV是用C語言實現(xiàn)的,但是CvMat和IplImage的關系其實就類似于C++中的類的繼承關系,。IplImage類繼承自CvMat類,。所以,我們最好先了解一下IplImage的基類CvMat類的情況,,然后再看更復雜的IplImage類,。而CvArr類,是CvMat類的抽象基類,。正因為CvArr類是基類,,所以當我們看到OpenCV的函數(shù)參數(shù)為CvArr*類型的參數(shù)時,我們可以代入CvMat*或者IplImage*類型的實參。 CvMat矩陣數(shù)據(jù)結構 當我們學習CvMat之前,,我們必須知道兩個事情,,首先OpenCV中是沒有"vector(向量)"數(shù)據(jù)類型的,當我們需要一個"vector"時,,我們就使用一個三行一列的矩陣,。其次,,OpenCV中矩陣的概念比線性代數(shù)中矩陣的概念更抽象和復雜一些一些,。例如,創(chuàng)建矩陣的函數(shù):CvMat* cvCreateMat(int rows,int cols,int type),其中type代表預定義的數(shù)據(jù)類型,,即矩陣中每一個元素的數(shù)據(jù)類型,,該類型的形式是:CV_<bit數(shù)>(S|U|F)C<通道數(shù)>,例如,數(shù)據(jù)類型可能是CV32FC1,即32bit的浮點數(shù),,或CV_8UC3,8bit的無符號整數(shù),,或CV_8UC3,無符號8bit整數(shù),3通道,等等。我們會發(fā)現(xiàn),,cvMat里,,矩陣中行和列上的每一個元素,不必是一個單獨的數(shù)字,,可能是一系列數(shù)字(有幾個通道就有幾個數(shù)字),。每一個元素可以代表多個值,就允許了我們在矩陣中包含一個RGB的圖像,。 從內部的結構上看,,CvMat相當?shù)暮唵危覀兛梢酝ㄟ^代碼看一下該數(shù)據(jù)結構的原型(代碼在.../opencv/cxcore/include/cxtypes.h): 其中包含了width,height,type,step(是一行元素的長度,,與width類似,,但以字節(jié)計算),以及指向數(shù)據(jù)的指針.你可以通過CvMat數(shù)據(jù)類型的變量直接接觸該類型內部的成員,,例如,,CvMat* matrix ,就可以用matrix->height,matrix->width來獲得矩陣的尺寸,。又或者通過OpenCV的函 數(shù)來獲得,。例如,可以用cvGetSize(CvMat*)來獲得CvSize對象,,這代表該矩陣的長和寬,。 typedef struct CvMat { int type; int step; /* for internal use only */ int* refcount; int hdr_refcount; union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; #ifdef __cplusplus union { int rows; int height; }; union { int cols; int width; }; #else int rows; int cols; #endif } CvMat; 以上,是該CvMat類型的數(shù)據(jù)的“頭部”,,即矩陣的定義部分,。許多OpenCV的函數(shù),將矩陣的頭部和數(shù)據(jù)部分分開處理,。 矩陣的創(chuàng)建可以用多種方法,,最簡單的一種是CvMat* cvCreateMat(int rows,int cols,int type),該方法既設置了矩陣的頭部,,又為數(shù)據(jù)部分分配了內存空間,該函數(shù)是cvCreateMatHeader()和cvCreateData()的合并縮寫,。cvCreateMatHeader()只創(chuàng)建CvMat頭部,,但不為數(shù)據(jù)部分分配空間。而cvCreateData()則是為矩陣的數(shù)據(jù)部分分配了內存空間,。有時候,,我們只需要cvCreateMatHeader()就可以了,因為基于一些理由,,我們可能已經(jīng)為數(shù)據(jù)部分分配了空間,,或者此時分配空間還不是時候。另一個創(chuàng)建矩陣的方法cvCloneMat(CvMat*)是從一個已經(jīng)有的矩陣,,來“克隆”出一個新的矩陣來,。當我們不再需要某矩陣時,我們需要調用長cvReleaseMat(CvMat*)來釋放它,。 就象其他的OpenCV數(shù)據(jù)類型一樣,,矩陣數(shù)據(jù)類型有一個構造函數(shù),CvMat cvMat( int rows, int cols, int type, void* data=NULL );這個函數(shù)沒有為矩陣的數(shù)據(jù)部分分配空間,,只是初始化了矩陣的頭部,,類似cvInitMatheader()。 以下是這些函數(shù)的原型: 1,,CreateMat 創(chuàng)建矩陣 CvMat* cvCreateMat( int rows, int cols, int type ); rows 矩陣行數(shù),。 cols 矩陣列數(shù)。 type 矩陣元素類型,。 通常以 CV_<比特數(shù)>(S|U|F)C<通道數(shù)>型式描述,, 例如: CV_8UC1 意思是一個8-bit 無符號單通道矩陣, CV_32SC2 意思是一個32-bit 有符號二個通道的矩陣。 函數(shù) cvCreateMat 為新的矩陣分配頭和下面的數(shù)據(jù),,并且返回一個指向新創(chuàng)建的矩陣的指針,。是下列操作的縮寫型式: CvMat* mat = cvCreateMatHeader( rows, cols, type ); cvCreateData( mat ); 矩陣按行存貯。所有的行以4個字節(jié)對齊,。 2,,CreateMatHeader
創(chuàng)建新的矩陣頭 CvMat* cvCreateMatHeader( int rows, int cols, int type ); rows 矩陣行數(shù). cols 矩陣列數(shù). type 矩陣元素類型(見 cvCreateMat). 函數(shù) cvCreateMatHeader 分配新的矩陣頭并且返回指向它的指針. 矩陣數(shù)據(jù)可被進一步的分配,使用cvCreateData 或通過 cvSetData明確的 分配數(shù)據(jù). 3,,ReleaseMat
刪除矩陣 void cvReleaseMat( CvMat** mat ); mat 雙指針指向矩陣. 函數(shù)cvReleaseMat 縮減矩陣數(shù)據(jù)參考計數(shù)并且釋放矩陣頭 : if( *mat ) cvDecRefData( *mat ); cvFree( (void**)mat ); 4,,InitMatHeader 初始化矩陣頭 CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type, void* data=NULL, int step=CV_AUTOSTEP ); mat 指針指向要被初始化的矩陣頭. rows 矩陣的行數(shù). cols 矩陣的列數(shù). type 矩陣元素類型. data 可選的,將指向數(shù)據(jù)指針分配給矩陣頭. step 排列后的數(shù)據(jù)的整個行寬,,默認狀態(tài)下,,使用STEP的最小可能值。也就是說默認情況下假定矩陣的行與行之間無隙. 函數(shù) cvInitMatHeader 初始化已經(jīng)分配了的 CvMat 結構. 它可以被OpenCV矩陣函數(shù)用于處理原始數(shù)據(jù)。 例如, 下面的代碼計算通用數(shù)組格式存貯的數(shù)據(jù)的矩陣乘積. 計算兩個矩陣的積 double a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; double b[] = { 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12 }; double c[9]; CvMat Ma, Mb, Mc ; cvInitMatHeader( &Ma, 3, 4, CV_64FC1, a ); cvInitMatHeader( &Mb, 4, 3, CV_64FC1, b ); cvInitMatHeader( &Mc, 3, 3, CV_64FC1, c ); cvMatMulAdd( &Ma, &Mb, 0, &Mc ); // c 數(shù)組存貯 a(3x4) 和 b(4x3) 矩陣的積 5,,Mat
初始化矩陣的頭 CvMat cvMat( int rows, int cols, int type, void* data=NULL ); rows 矩陣行數(shù) cols 列數(shù). type 元素類型(見CreateMat). data 可選的分配給矩陣頭的數(shù)據(jù)指針 . 函數(shù) cvMat 是個一快速內連函數(shù),,替代函數(shù) cvInitMatHeader. 也就是說它相當于: CvMat mat; cvInitMatHeader( &mat, rows, cols, type, data, CV_AUTOSTEP ); 6,CloneMat 創(chuàng)建矩陣拷貝 CvMat* cvCloneMat( const CvMat* mat ); mat 輸入矩陣. 函數(shù) cvCloneMat 創(chuàng)建輸入矩陣的一個拷貝并且返回該矩陣的指針. 以下的例子中,,我們讓矩陣的數(shù)據(jù)部分指向了已經(jīng)分配好了的數(shù)據(jù): float vals[] = { 0.866025, -0.500000, 0.500000, 0.866025}; CvMat rotmat; cvInitMatHeader( &rotmat, 2, 2, CV_32FC1, vals ); 當我們定義好了矩陣,,我們可以通過一些函數(shù)查看矩陣的屬性,例如:cvGetElemType(const cvArr* arr),cvGetDims(const CvArr* arr,int* sizes=NULL),cvGetDimSize(const CvArr* arr,index) 7.GetElemType 返回數(shù)組元素類型 int cvGetElemType( const CvArr* arr ); arr 輸入數(shù)組. 函數(shù) GetElemType 返回數(shù)組元素類型就像在cvCreateMat 中討論的一樣: CV_8UC1 ... CV_64FC4 8.GetDims, GetDimSize
返回數(shù)組維數(shù)和他們的大小或者特殊維的大小 int cvGetDims( const CvArr* arr, int* sizes=NULL ); int cvGetDimSize( const CvArr* arr, int index ); arr 輸入數(shù)組. sizes 可選的輸出數(shù)組維尺寸向量,,對于2D數(shù)組第一位是數(shù)組行數(shù)(高),,第二位是數(shù)組列數(shù)(寬) index 以0為基準的維索引下標(對于矩陣0意味著行數(shù),1意味著列數(shù),,對于圖象0意味著高,,1意味著寬,。 函數(shù) cvGetDims 返回維數(shù)和他們的大小,。如果是 IplImage 或 CvMat 總是返回2,不管圖像/矩陣行數(shù),。函數(shù) cvGetDimSize 返回特定的維大?。烤S的元素數(shù))。 以下是一個例子: #pragma comment( lib, "cxcore.lib" ) #include "cv.h" #include <stdio.h> void main() { CvMat rotmat; int sizes[2]; float array[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}; //注意,,此句更改為 cvInitMatHeader(&rotmat,3,5,CV_32FC1,NULL);時,,cvGetDimSize不能起作用 cvInitMatHeader(&rotmat,3,5,CV_32FC1,array); int type = cvGetElemType(&rotmat); cvGetDims(&rotmat,sizes); printf("type=%d\n",type); printf("height=%d,width=%d\n",sizes[0],sizes[1]); printf("height=%d,width=%d\n",cvGetDimSize(&rotmat, 0),cvGetDimSize(&rotmat, 1)); }
|