【OpenCV学习笔记】2.1OpenCV基本数据类型
OpenCV提供了多種基本數據類型。雖然這些數據類型在C語言中不是基本類型,但結構都很簡單,可將它們作為原子類型。可以在“…/OpenCV/cxcore/include”目錄下的cxtypes.h文件中查看其詳細定義。?
數據類型中最簡單的就是CvPoint。CvPoint是一個包含integer類型成員x和y的簡單結構體。CvPoint有兩個變體類型:CvPoint2D32f和CvPoint3D32f。前者同樣有兩個成員x,y,但它們是浮點類型;而后者卻多了一個浮點類型的成員z。
CvSize類型與CvPoint非常相似,但它的數據成員是integer類型的width和height。如果希望使用浮點類型,則選用CvSize的變體類型CvSize2D32f。
CvRect類型派生于CvPoint和CvSize,它包含4個數據成員:x,y,width和height。(正如你所想的那樣,該類型是一個復合類型)。
下一個(但不是最后一個)是包含4個整型成員的CvScalar類型,當內存不是問題時,CvScalar經常用來代替1,2或者3個實數成員(在這個情況下,不需要的分量被忽略)。CvScalar有一個單獨的成員val,它是一個指向4個雙精度浮點數數組的指針。
所有這些數據類型具有以其名稱來定義的構造函數,例如cvSize()。(構造函數通常具有與結構類型一樣的名稱,只是首字母不大寫)。記住,這是C而不是C++,所以這些構造函數只是內聯函數,它們首先提取參數列表,然后返回被賦予相關值的結構。??????????????????????????????????????????????????????????????????????????????????????????????????????????????????
各數據類型的內聯構造函數被列在下表中:cvPoint(),cvSize(),cvRect()和cvScalar()。這些結構都十分有用,因為它們不僅使代碼更容易編寫,而且也更易于閱讀。假設要在(5,10)和(20,30)之間畫一個白色矩形,只需簡單調用:
?
?
表3-1:points, size, rectangles和calar三元組的結構
?
| 結構 | 成員 | 意義 |
| CvPoint | int x, y | 圖像中的點 |
| CvPoint2D32f | float x, y | 二維空間中的點 |
| CvPoint3D32f | float x, y, z | 三維空間中的點 |
| CvSize | int width, height | 圖像的尺寸 |
| CvRect | int x, y, width, height | 圖像的部分區域 |
| CvScalar | double val[4] | RGBA 值 |
cvScalar是一個特殊的例子:它有3個構造函數。第一個是cvScalar(),它需要一個、兩個、三個或者四個參數并將這些參數傳遞給數組val[]中的相應元素。第二個構造函數是cvRealScalar(),它需要一個參數,它被傳遞給給val[0],而val[]數組別的值被賦為0。最后一個有所變化的是cvScalarAll(),它需要一個參數并且val[]中的4個元素都會設置為這個參數。
矩陣和圖像類型
下圖為我們展示了三種圖像的類或結構層次結構。使用OpenCV時,會頻繁遇到IplImage數據類型,IplImage是我們用來為通常所說的“圖像”進行編碼的基本結構。這些圖像可能是灰度,彩色,4通道的(RGB+alpha),其中每個通道可以包含任意的整數或浮點數。因此,該類型比常見的、易于理解的3通道8位RGB圖像更通用。
OpenCV提供了大量實用的圖像操作符,包括縮放圖像,單通道提取,找出特定通道最大最小值,兩個圖像求和,對圖像進行閾值操作,等等。
圖3-1:雖然OpenCV是由C語言實現的,但它使用的結構體也是遵循面向對象的思想設計的。實際上,IplImage由CvMat派生,而CvMat由CvArr派生
在開始探討圖像細節之前,我們需要先了解另一種數據類型CvMat,OpenCV的矩陣結構。雖然OpenCV完全由C語言實現,但CvMat和IplImage之間的關系就如同C++中的繼承關系。實質上,IplImage可以被視為從CvMat中派生的。因此,在試圖了解復雜的派生類之前,最好先了解基本的類。第三個類CvArr,可以被視為一個抽象基類,CvMat由它派生。在函數原型中,會經常看到CvArr(更準確地說,CvArr*),當它出現時,便可以將CvMat*或IplImage*傳遞到程序。
??? CvMat矩陣結構:
在開始學習矩陣的相關內容之前,我們需要知道兩件事情。第一,在OpenCV中沒有向量(vector)結構。任何時候需要向量,都只需要一個列矩陣(如果需要一個轉置或者共軛向量,則需要一個行矩陣)。第二,OpenCV矩陣的概念與我們在線性代數課上學習的概念相比,更抽象,尤其是矩陣的元素,并非只能取簡單的數值類型。例如,一個用于新建一個二維矩陣的例程具有以下原型:
cvMat* cvCreateMat ( int rows, int cols, int type );
這里type可以是任何預定義類型,預定義類型的結構如下:CV_<bit_depth> (S|U|F)C<number_of_channels>。于是,矩陣的元素可以是32位浮點型數據(CV_32FC1),或者是無符號的8位三元組的整型數據(CV_8UC3),或者是無數的其他類型的元素。一個CvMat的元素不一定就是個單一的數字。在矩陣中可以通過單一(簡單)的輸入來表示多值,這樣我們可以在一個三原色圖像上描繪多重色彩通道。對于一個包含RGB通道的簡單圖像,大多數的圖像操作將分別應用于每一個通道(除非另有說明)。
?
IplImage數據結構
從本質上講,它是一個CvMat對象,但它還有其他一些成員變量將矩陣解釋為圖像。這個結構最初被定義為Intel圖像處理庫(IPL)的一部分。IplImage結構的準確定義如例3-10所示。
例3-10:IplImage結構
?
?
?
我們試圖討論這些變量的某些功能。有些變量不是很重要,但是有些變量非常重要,有助于我們理解OpenCV解釋和處理圖像的方式。
width和height這兩個變量很重要,其次是depth和nchannals。depth變量的值取自ipl.h中定義的一組數據,但與在矩陣中看到的對應變量不同。因為在圖像中,我們往往將深度和通道數分開處理,而在矩陣中,我們往往同時表示它們。可用的深度值如表3-2所示。????????????????????????????????????????????????????????????????????????????????????????????????表3-2:OpenCV圖像類型
?
| 宏 | 圖像像素類型 |
| IPL_DEPTH_8U | 無符號8位整數 (8u) |
| IPL_DEPTH_8S | 有符號 8位整數(8s) |
| IPL_DEPTH_16S | 有符號16位整數(16s) |
| IPL_DEPTH_32S | 有符號32位整數(32s) |
| IPL_DEPTH_32F | 32位浮點數單精度(32f) |
| IPL_DEPTH_64F | 64位浮點數雙精度(64f) |
通道數nChannels可取的值是1,2,3或4。
隨后兩個重要成員是origin和dataOrder。origin變量可以有兩種取值:IPL_ORIGIN_TL 或者 IPL_ORIGIN_BL,分別設置坐標原點的位置于圖像的左上角或者左下角。
在計算機視覺領域,一個重要的錯誤來源就是原點位置的定義不統一。具體而言,圖像的來源、操作系統、編解碼器和存儲格式等因素都可以影響圖像坐標原點的選取。舉例來說,你或許認為自己正在從圖像上面的臉部附近取樣,但實際上卻在圖像下方的裙子附近取樣。避免此類現象發生的最好辦法是在最開始的時候檢查一下系統,在所操作的圖像塊的地方畫點東西試試。
dataOrder的取值可以是IPL_DATA_ORDER_PIXEL或IPL_DATA_ORDER_PLANE,前者指明數據是將像素點不同通道的值交錯排在一起(這是常用的交錯排列方式),后者是把所有像素同通道值排在一起,形成通道平面,再把平面排列起來。
參數widthStep與前面討論過的CvMat中的step參數類似,包括相鄰行的同列點之間的字節數。僅憑變量width是不能計算這個值的,因為為了處理過程更高效每行都會用固定的字節數來對齊;因此在第i行末和第i+1行開始處可能會有些冗于字節。參數imageData包含一個指向第一行圖像數據的指針。如果圖像中有些獨立的平面(如當dataOrder = IPL_DATA_ORDER_PLANE)那么把它們作為單獨的圖像連續擺放,總行數為height和nChannels的乘積。但通常情況下,它們是交錯的,使得行數等于高度,而且每一行都有序地包含交錯的通道。
最后還有一個實用的重要參數——?感興趣的區域(ROI),實際上它是另一個IPL/IPP 結構IplROI的實例。IplROI包含xOffset,yOffset,height,width和coi成員變量,其中COI代表channel of interest(感興趣的通道)。ROI的思想是:一旦設定ROI,通常作用于整幅圖像的函數便會只對ROI所表示的子圖像進行操作。如果IplImage變量中設置了ROI,則所有的OpenCV函數就會使用該ROI變量。如果COI被設置成非0值,則對該圖像的操作就只作用于被指定的通道上了。不幸的是,許多OpenCV函數都忽略參數COI。
轉載于:https://www.cnblogs.com/xiaoyueqingfeng/archive/2012/03/23/2413475.html
總結
以上是生活随笔為你收集整理的【OpenCV学习笔记】2.1OpenCV基本数据类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vs.net各版本解决方案相互转换工具
- 下一篇: PL/SQL Developer的错误提