OpenCV的主要四種基本資料結構
CvPoint => CvPoint2D32f, CvPoint3D32f,最前面為兩個整數變數x,y 後者則為浮點數
CvSize => CvSize2D32f,兩個整數變數width, height或者為浮點數的結構
CvRect有成員x, y, width, height
CvScalar,四個double的數值,再不考量記憶體使用量可以用來取代前面三者
通常constructor為cvPoint()或者cvSize,也就是第一個字母為小寫的function,在這裡雖然OpenCV是用c語言寫成,但是其實有不少物件的觀念,所以就借用了constructor一詞,但是並非真的是constructor
圖形的資料結構
CvArr
CvMat
IplImage
如果有個function要求CvArray*,則可以放入CvMat*或者IplImage*,同理要求CvMat*則可放入IplImage*,可以將關係視為繼承,也就是說is-a的關係
CvMat * cvCreateMat(int rows,int cols, int type);
表示這為一個二維陣列,望文生義,rows跟cols表示列跟行,type則是
CV_<bit_depth>(S|U|F)C<number_of_channels>
bit_depth也就是色階,S|U|F表示signed|unsigned|floating-point,C表示channel個數
CV8UC3,表示每個pixels由3個channel構成,每個channel用8bits表示
data則是實際儲存資料的地方
而cvCreateMat實際上呼叫了cvCreateMatHeader()與cvCreateMatData(),前者填充rows/cols/type等等,後者對儲存資料的空間作配置,所以如果不需配置記憶體的時候,或者共享某個區塊的時候,就只要呼叫cvCreateMatHeader就可以了。如果是複製某個區塊,使用cvCloneMat(CvMat*),有配置就必要釋放cvReleaseMat(CvMat*)
存取CvMat資料的方式有用Macro
CvMat *mat=cvCreateMat(5,5,CV_32FC1);
CV_MAT_ELE(*mat,float,3,2);
*((float*)CV_MAT_ELE_PRT(*mat,float,3,2))=5.5
由參數得知,必須要知道data的type才能計算到正確位置,還有就是它是一次性計算,也就是非指標運算,對於連續存取很沒效率
另外一種為cvPtr*D與cvGet*D的方式
取得指標,用於各種維度
uchar* cvPtr1D(const CvArr* arr, int idx0, int *type=NULL)
uchar* cvPtr2D(const CvArr* arr, int idx0, int idx1, int *type=NULL)
uchar* cvPtr3D(const CvArr* arr, int idx0, int idx1, int idx2, int *type=NULL)
uchar* cvPtrND(const CvArr* arr, int *idx, int *type=NULL, int create_node=1, unsigned* precalc_hashval=NULL)
或者
double cvGetReal1D(const CvArra *arr, int idx0)
double cvGetReal2D(const CvArra *arr, int idx0, int idx1)
double cvGetReal3D(const CvArra *arr, int idx0, int idx1, int idx2)
double cvGetRealND(const CvArra *arr, int *idx)
CvScalar cvGet1D(const CvArr *arr, int idx0)
CvScalar cvGet2D(const CvArr *arr, int idx0, int idx1)
CvScalar cvGet3D(const CvArr *arr, int idx0, int idx1, int idx2)
CvScalar cvGetND(const CvArr *arr, int *idx)
其中cvPtr*D取得為每個pixel,如果有3個channel,則為rgbrgbrgb...等地排列方式,這部分區自行處理,好處是可以快速地訪問,另外有cvGet*D就有cvSet*D
另外要注意的是CvMat未必是連續空間,最多保證每個row是連續的
從上面可以看到IplImage的成員,大多可以望文生義
重要的有origin,表示原點座標是放置在IPL_ORIGIN_TL左上角(一般電腦圖形)或者IPL_ORIGIN_BL左下角(一般數學座標)
dataOrder表示資料是每個IPL_DATA_ORDER_PIXEL或者IPL_DATA_ORDER_PLANE,前者表示rgbrgbrg這樣的資料排列,後者表示rrrrr...ggggg...bbbbb....這樣三面的排列,所以儲存影像資料的imageData就受到這個參數的影響,必須知道資料正確的排列才能正確處理資料
ROI則是感興趣的範圍,用以將圖形特定範圍切出,用來處理這部分,有mask的觀念,可以使用
void cvSetImageROI(IplImage *img, CvRect rect)
void cvResetImageROI(IplImge *img)
可見一個IplImage只能設定一個ROI,但是要保留多個ROI,書中有範例技巧
參考資料:
http://yester-place.blogspot.tw/2008/07/cvmat.html
http://yester-place.blogspot.tw/2008/07/iplimage1.html