OpenCV 2.4.9 學習筆記(2)—— OpenCV內存自動管理

OpenCV自動內存管理html

  目前版本的OpenCV是自動處理全部本身的內存的,雖然這麼說也不是很嚴謹。OpenCV在2.0版本中引入了一個新的C++接口,利用自動內存管理給出瞭解決問題的新方法。使用這個方法,開發者不須要糾結在管理內存上,並且你的代碼會變得簡潔。算法

  以 Mat爲例 ,首先如今不必再手動地(1)爲其開闢空間(2)在不須要時當即將空間釋放。但手動地作仍是能夠的:大多數OpenCV函數仍會手動地爲輸出數據開闢空間。當傳遞一個已經存在的 Mat 對象時,開闢好的矩陣空間會被重用。也就是說,咱們每次都使用大小正好的內存來完成任務。基本上講 Mat 是一個類,由兩個數據部分組成:矩陣頭(包含矩陣尺寸,存儲方法,存儲地址等信息)和一個指向存儲全部像素值的矩陣(根據所選存儲方法的不一樣矩陣能夠是不一樣的維數)的指針。矩陣頭的尺寸是常數值,但矩陣自己的尺寸會依圖像的不一樣而不一樣,一般比矩陣頭的尺寸大數個數量級。所以,當在程序中傳遞圖像並建立拷貝時,大的開銷是由矩陣形成的,而不是信息頭。OpenCV是一個圖像處理庫,囊括了大量的圖像處理函數,爲了解決問題一般要使用庫中的多個函數,所以在函數中傳遞圖像是屢見不鮮。同時不要忘了咱們正在討論的是計算量很大的圖像處理算法,所以,除非萬不得已,咱們不該該拷貝  的圖像,由於這會下降程序速度。函數

爲了搞定這個問題,OpenCV使用引用計數機制。其思路是讓每一個 Mat 對象有本身的信息頭,但共享同一個矩陣。這經過讓矩陣指針指向同一地址而實現。而拷貝構造函數則 只拷貝信息頭和矩陣指針 ,而不拷貝矩陣。spa

1 Mat A, C;                                 // 只建立信息頭部分
2 A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // 這裏爲矩陣開闢內存
3 Mat B(A);                                 // 使用拷貝構造函數
4 C = A;                                    // 賦值運算符

以上代碼中的全部Mat對象最終都指向同一個也是惟一一個數據矩陣。雖然它們的信息頭不一樣,但經過任何一個對象所作的改變也會影響其它對象。實際上,不一樣的對象只是訪問相同數據的不一樣途徑而已。這裏還要說起一個比較棒的功能:你能夠建立只引用部分數據的信息頭。好比想要建立一個感興趣區域( ROI ),你只須要建立包含邊界信息的信息頭:指針

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

如今你也許會問,若是矩陣屬於多個 Mat 對象,那麼當再也不須要它時誰來負責清理?簡單的回答是:最後一個使用它的對象。經過引用計數機制來實現。不管何時有人拷貝了一個 Mat 對象的信息頭,都會增長矩陣的引用次數;反之當一個頭被釋放以後,這個計數被減一;當計數值爲零,矩陣會被清理。但某些時候你仍會想拷貝矩陣自己(不僅是信息頭和矩陣指針),這時可使用函數 clone() 或者 copyTo() 。code

1 Mat F = A.clone(); 2 Mat G; 3 A.copyTo(G);

如今改變 F 或者 G 就不會影響 Mat 信息頭所指向的矩陣。htm

總結對象

  一、OpenCV函數中輸出圖像的內存分配是自動完成的(若是不特別指定的話)。blog

  二、使用OpenCV的C++接口時不須要考慮內存釋放問題。教程

  三、賦值運算符和拷貝構造函數( ctor )只拷貝信息頭。

  四、使用函數 clone() 或者 copyTo() 來拷貝一副圖像的矩陣。

 

上述部份內容參考了OpenCV的中文教程。(http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/mat%20-%20the%20basic%20image%20container/mat%20-%20the%20basic%20image%20container.html#matthebasicimagecontainer)

相關文章
相關標籤/搜索