OPENCV學習筆記1-4_Mat 儲存管理

  Mat是OpenCV最基本的數據結構,Mat即矩陣(Matrix)的縮寫,Mat數據結構主要包含2部分:Header(矩陣頭)和Pointer(矩陣指針)。Header中主要包含矩陣的大小,存儲方式,存儲地址等信息;Pointer中存儲指向像素值的指針。矩陣頭的大小是一個常數,不會隨着圖像的大小而改變,但是保存圖像像素數據的矩陣則會隨着圖像的大小而改變,通常數據量會很大,比矩陣頭大幾個數量級。因此,OpenCV使用了引用次數,當進行圖像複製和傳遞時,不再複製整個Mat數據,而只是複製矩陣頭和指向像素矩陣的指針。

  OpenCV中的內存分配是自動完成(不是特別指定的話),使用OpenCV的C++ 接口不需要考慮內存釋放問題。當Mat實例化後,分配內存;當對象離開作用域後,分配的內存自動釋放。

1.1  image storage method

  在一個彩色圖像中,圖像數據緩衝區中的前三個字節對應圖像左上角像素的三個通道值,接下來的三個字節對應第一行的第二個像素,以此類推。一個寬爲W、高爲H的圖像需要一個大小由W X H X3個uchar構成的內存塊。但是,出於效率考慮,每行會填補一些額外的像素。這是因爲,如果行的長度是4或8的倍數,一些多媒體處理芯片(如Intel的MMX架構)可以更高效的處理圖像。這些額外的像素不會被顯示或者保存,填補的值將被忽略。OpenCV將填補後一行的長度指定爲關鍵字。如果圖像沒有對行進行填補,那麼圖像的有效寬度就等於圖像的真實寬度。

  成員變量cols代表圖像的寬度(圖像的列數),rows代表圖像的高度,step代表以字節爲單位的圖像的有效寬度。即使你的圖像的元素類型不是uchar,step仍然代表着行的字節數。像素的大小可以由elemSize函數得到:對於一個三通道的short型矩陣(CV_16SC3),elemSize返回6。圖像的通道數可以channels方法得到,灰度爲1,彩色爲3。total函數返回矩陣的像素個數。

1.2  isContinuous

  Mat提供了一個檢測圖像是否連續的函數isContinuous()。當圖像連通時,就可以把圖像完全展開,看成是一行。

 

1.3  Deep / Shallow Copies(深拷貝和淺拷貝)

  1. shallow copy

  Mat實現了引用計數以及淺拷貝。引用計數的作用是隻有當所有引用內存數據的對象都被析構後,內存纔會釋放。淺拷貝是指當圖像之間進行賦值時,圖像數據並未發生複製,而是兩個對象都指向同一塊內存塊。

cv::Mat a;                                                 // creates just the header parts(創建矩陣頭)
a = cv::imread("test.jpg");                                // allocate matrix(分配矩陣內存),讀入圖像
cv::Mat b = a;                                             // Assignment operator(賦值運算符),複製
/*
 a,b獨立矩陣頭,但是其矩陣指針指向同一個矩陣,即其中任何一個矩陣數據改變都會影響另外一個當Mat對象每被複制一次時,就會將引用計數加1,故其引用計數ref count爲2
*/

  2. deep copy

  Sometimes you will want to copy the matrix itself too, so OpenCV provides the clone() and copyTo() functions.

cv::Mat c = a.clone();
cv::Mat d;
a.copyTo(d);
/*上面代碼中的c,d各自擁有自己的矩陣,改變自己的矩陣數據不會相互影響。*/

#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
  Mat m1 = (Mat_<double>(3,3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
  cout << "yunfung_opencv_learn_test:" <<"\n\n";
  cout << "m1_refcount=" <<  m1.u->refcount <<endl;

  Mat m2 = m1;          //  m1.u->refcount ,not add 1
  cout << "m1_refcount=" <<  m1.u->refcount <<" "<<"m2_refcount=" <<  m1.u->refcount<<endl;

  Mat m3 = m1.clone();  //  m1.u->refcount ,not add 1
  cout << "m1_refcount=" << m1.u->refcount <<endl;

  m2.release();         //if using m1.release(),no  m1.u->refcount
  cout << "m1_refcount=" <<  m1.u->refcount <<" "<<"m2_refcount=" <<  m1.u->refcount<<endl;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章