1. 程式人生 > >opencv之core模組

opencv之core模組

Mat - 基本影象容器

參考自:opencv中文網 關於 Mat ,首先要知道的是你不必再手動地(1)為其開闢空間(2)在不需要時立即將空間釋放。 但手動地做還是可以的:大多數OpenCV函式仍會手動地為輸出資料開闢空間。當傳遞一個已經存在的 Mat 物件時,開闢好的矩陣空間會被重用。也就是說,我們每次都使用大小正好的記憶體來完成任務。

基本上講 Mat 是一個類,由兩個資料部分組成:

  1. 矩陣頭(包含矩陣尺寸,儲存方法,儲存地址等資訊)
  2. 一個指向儲存所有畫素值的矩陣(根據所選儲存方法的不同矩陣可以是不同的維數)的指標。

矩陣頭的尺寸是常數值,但矩陣本身的尺寸會依影象的不同而不同,通常比矩陣頭的尺寸大數個數量級。因此,當在程式中傳遞影象並建立拷貝時,大的開銷是由矩陣造成的,而不是資訊頭。OpenCV是一個影象處理庫,囊括了大量的影象處理函式,為了解決問題通常要使用庫中的多個函式,因此在函式中傳遞影象是家常便飯。同時不要忘了我們正在討論的是計算量很大的影象處理演算法,因此,除非萬不得已,我們不應該拷貝 大 的影象,因為這會降低程式速度。為了搞定這個問題,OpenCV使用引用計數機制。其思路是讓每個 Mat 物件有自己的資訊頭,但共享同一個矩陣。這通過讓矩陣指標指向同一地址而實現。而拷貝建構函式則 只拷貝資訊頭和矩陣指標 ,而不拷貝矩陣。

Mat A, C;                                 // 只建立資訊頭部分
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // 這裡為矩陣開闢記憶體

Mat B(A);                                 // 使用拷貝建構函式

C = A;                                    // 賦值運算子

以上程式碼中的所有Mat物件最終都指向同一個也是唯一一個數據矩陣。雖然它們的資訊頭不同,但通過任何一個物件所做的改變也會影響其它物件。實際上,不同的物件只是訪問相同資料的不同途徑而已。這裡還要提及一個比較棒的功能:你可以建立只引用部分資料的資訊頭。比如想要建立一個感興趣區域( ROI ),你只需要建立包含邊界資訊的資訊頭:

Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries

現在你也許會問,如果矩陣屬於多個 Mat 物件,那麼當不再需要它時誰來負責清理?簡單的回答是:最後一個使用它的物件。通過引用計數機制來實現。無論什麼時候有人拷貝了一個 Mat 物件的資訊頭,都會增加矩陣的引用次數;反之當一個頭被釋放之後,這個計數被減一;當計數值為零,矩陣會被清理。但某些時候你仍會想拷貝矩陣本身(不只是資訊頭和矩陣指標),這時可以使用函式 clone() 或者 copyTo() 。

Mat F = A.clone();
Mat G;
A.copyTo(G);

現在改變 F 或者 G 就不會影響 Mat 資訊頭所指向的矩陣。 總結一下,你需要記住的是

  • OpenCV函式中輸出影象的記憶體分配是自動完成的(如果不特別指定的話)。
  • 使用OpenCV的C++介面時不需要考慮記憶體釋放問題。
  • 賦值運算子和拷貝建構函式( ctor )只拷貝資訊頭。
  • 使用函式 clone() 或者 copyTo() 來拷貝一副影象的矩陣.

儲存 方法

這裡講述如何儲存畫素值。需要指定顏色空間和資料型別。顏色空間是指對一個給定的顏色,如何組合顏色元素以對其編碼。最簡單的顏色空間要屬灰度級空間,只處理黑色和白色,對它們進行組合可以產生不同程度的灰色。

對於 彩色 方式則有更多種類的顏色空間,但不論哪種方式都是把顏色分成三個或者四個基元素,通過組合基元素可以產生所有的顏色。RGB顏色空間是最常用的一種顏色空間,這歸功於它也是人眼內部構成顏色的方式。它的基色是紅色、綠色和藍色,有時為了表示透明顏色也會加入第四個元素 alpha (A)。

有很多的顏色系統,各有自身優勢:

  • RGB是最常見的,這是因為人眼採用相似的工作機制,它也被顯示裝置所採用。
  • HSV和HLS把顏色分解成色調、飽和度和亮度/明度。這是描述顏色更自然的方式,比如可以通過拋棄最後一個元素,使演算法對輸入影象的光照條件不敏感。
  • YCrCb在JPEG影象格式中廣泛使用。
  • CIE Lab*是一種在感知上均勻的顏色空間,它適合用來度量兩個顏色之間的 距離 。

每個組成元素都有其自己的定義域,取決於其資料型別。如何儲存一個元素決定了我們在其定義域上能夠控制的精度。最小的資料型別是 char ,佔一個位元組或者8位,可以是有符號型(0到255之間)或無符號型(-127到+127之間)。儘管使用三個 char 型元素已經可以表示1600萬種可能的顏色(使用RGB顏色空間),但若使用float(4位元組,32位)或double(8位元組,64位)則能給出更加精細的顏色分辨能力。但同時也要切記增加元素的尺寸也會增加了影象所佔的記憶體空間。