opencv中mat詳細解析

2021-08-18 20:47:01 字數 4588 閱讀 8988

##1、起源

opencv作為強大的計算機視覺開源庫,很大程度上參考了matlab的實現細節和風格,比如說,在opencv2.x 版本以後,越來越多的函式實現了matlab具有的功能,甚至乾脆連函式名都一模一樣(如 imread, imshow,imwriter等)。這一做法,不僅拉近了產品開發與學術研究的距離,並極大程度的提高了開發人員的研發效率,不得不說,intel公司真的是乙個偉大的公司。

在計算機記憶體中,數字影象以矩陣的形式儲存和運算,比如,在matlab中,影象讀取之後對應乙個矩陣,在opencv中,同樣也是如此。

在早期的opencv1.x版本中,影象的處理是通過iplimage(該名稱源於intel的另乙個開源庫intel image processing library ,縮寫成iplimage)結構來實現的。早期的opencv是用c語言編寫,因此提供的藉口也是c語言介面,其源**完全是c的程式設計風格。iplimage結構是opencv矩陣運算的基本資料結構。

到opencv2.x版本,opencv開源庫引入了物件導向程式設計思想,大量源**用c++重寫,mat類 (matrix的縮寫) 是opencv用於處理影象而引入的乙個封裝類。從功能上講,mat類在iplimage結構的基礎上進一步增強,並且,由於引入c++高階程式設計特性,mat類的擴充套件性大大提高,mat類的內容在後期的版本中不斷豐富,如果你檢視mat類的定義的話(opencv3.1\sources\modules\core\include\opencv2\core\mat.hpp),會發現其設計實現十分全面而具體,基本覆蓋計算機視覺對於影象處理的基本要求。

繼承 inheritance:

[外鏈轉存失敗(img-4ew220lz-1562988915046)(

##2、建構函式

// 預設建構函式 mat a;

mat ()

// 常用建構函式 mat a(10,10,8uc3);

mat (int rows, int cols, int type)

//mat a(300, 400, cv_8uc3,scalar(255,255,255));

mat (int ndims, const int *sizes, int type, const scalar &s)

mat (size size, int type)

mat (int rows, int cols, int type, const scalar &s)

mat (size size, int type, const scalar &s)

mat (int ndims, const int *sizes, int type)

mat (const mat &m)

mat (int rows, int cols, int type, void *data, size_t step=auto_step)

mat (size size, int type, void *data, size_t step=auto_step)

mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)

mat (const mat &m, const range &rowrange, const range &colrange=range::all())

//mat d (a, rect(10, 10, 100, 100) );

mat (const mat &m, const rect &roi)

mat (const mat &m, const range *ranges)

##3、初始化

初始化乙個mat檔案出來一般有兩種形式:

// 1、imread

mat src = imread("csdn.png");

//2、create

mat src;

if(src.empty())

##3、mat結構

我們先來看看mat結構,在你初始化乙個mat結構時,它的全部結構是這樣的。

mat類可以分為兩個部分:矩陣頭和指向畫素資料的矩陣指標。

[外鏈轉存失敗(img-si6ematv-1562988915047)(

###1.flags

[外鏈轉存失敗(img-aodengab-1562988915047)(

從定義可以看出flags是int型別,共佔32位,結合上圖可以看出各位所代表的意思。

從低位到高位:

0-2位代表depth即資料型別(如cv_8u),opencv的資料型別共7類,故只需3位即可全部表示。

3-11位代表通道數channels,因為opencv預設最大通道數為512,故只需要9位即可全部表示,可參照下面求通道數的部分。

0-11位共同代表type即通道數和資料型別(如cv_8uc3)

12-13位暫沒發現用處,也許是留著後用,待發現了再補上。

14位代表mat的記憶體是否連續,一般由creat建立的mat均是連續的,如果是連續,將加快對資料的訪問。

15位代表該mat是否為某乙個mat的submatrix,一般通過roi以及row()、col()、rowrange()、colrange()等得到的mat均為submatrix。

16-31代表magic signature,暫理解為用來區分mat的型別,如果mat和sparsemat

###2.dims

int cv::mat::dims   ()  const
the matrix dimensionality >= 2

矩陣的維數,但是這裡一般結果都是2,因為opencv好像儲存多維矩陣也是通過二維矩陣來計,它和基本的channels不一樣。

###3.channels

int cv::mat::channels   ()  const
返回影象的通道數。

###4.cols rows

int cv::mat::cols; //返回矩陣的列數

int cv::mat::rows // 返回矩陣行數

###5.data

uchar* cv::mat::data // 指向矩陣的資料單元的指標
###6.refcount

refcount它記錄了這個矩陣的資料被其他變數引用了多少次。在c++中矩陣的一些賦值操作往往只給新的變數賦予乙個新的標頭檔案,而資料部分只把資料指標指過去,而不重新分為記憶體,需要程式設計師來管理記憶體。這樣的話就會有隱患,因為如果原始的變數的資料記憶體釋放了,新的變數卻還在,指向了已經被釋放的記憶體區域,如果對新變數進行操作,很可能出現意想不到的問題。不過不用擔心,opencv的開發者早就想到了這個問題,並為我們想到了乙個解決方法,那就是靠這個refcount來記錄該資料被多少變數共用,直到最後乙個變數被釋放時,才釋放掉這個儲存資料記憶體塊。這也是為什麼類定義中refcount為指標,讓實際記錄次數的變數跟在矩陣資料最後面。

儲存影象畫素資料的矩陣則會隨著影象的大小而改變,通常資料量會很大,比矩陣頭大幾個數量級。這樣,在影象複製和傳遞過程中,主要的開銷是由存放影象畫素的矩陣而引起的。因此,opencv使用了引用次數,當進行影象複製和傳遞時,不再複製整個mat資料,而只是複製矩陣頭和指向畫素矩陣的指標,但是其矩陣指標指向同乙個矩陣,也就是其中任何乙個改變了矩陣資料都會影響另外乙個。

那麼,多個mat共用乙個矩陣資料,最後誰來釋放矩陣資料呢?

這就是引用計數的作用,當mat物件每被複製一次時,就會將引用計數加1,而每銷毀乙個mat物件(共用同乙個矩陣資料)時引用計數會被減1,當引用計數為0時,矩陣資料會被清理。這就是refcount的作用。

###7.datastart dataend datalimit

const uchar* cv::mat::dataend

const uchar* cv::mat::datalimit

const uchar* cv::mat::datastart

helper fields used in locateroi and adjustroi

這些都是用來控制roi區域,來獲取一些影象的區域性切片,減少計算量或者特殊需求的。

cv::rect rect(100, 100, 100, 100); 

srcimage(rect).copyto(roiimage);

###8.allocator

custom allocator

如果需要建立乙個新矩陣的記憶體空間,系統會呼叫matallocator類作為分配符進行記憶體的分配。

###9.size

matsize cv::mat::size // 返回矩陣大小
###10.step

矩陣元素定址

addr(mi0,...,im.dims−1)=m.data+m.step[0]∗i0+m.step[1]∗i1+...+m.step[m.dims−1]∗im.dims−1
step[i]是mat類中十分重要的乙個屬性,表示第i維的總大小,單位位元組

m.data指向儲存這列的首位址(類似於陣列名)

m.dims是總維度

##後續

更複雜細節後續再更

OpenCV中mat記憶體管理

opencv中大部分物件都像被std share ptr包裝過的行為一樣,你不需要自己手動釋放資源。同標準庫的智慧型指標一樣,你不需要自己去手動刪除指標,也許對於被智慧型指標管理的物件,根本就不建議你直接使用指標。所有的物件都應該建立在棧上,使用 object obj 的方式獲得物件,而不應該使用o...

opencv中的Mat詳解

1.初始化 mat the basic image container 最最基本的函式,所有在opencv中都是用mat形式來操作的。初始化乙個mat mat a,c a imread ar 1 imread color mat b a 複製a給b c a 賦值運算 mat d a,rect 10,...

opencv中Mat的屬性

類似cv 8uc1是mat的型別,其定義為type cv 位數 資料型別 通道數 cv 8uc1 0 cv 8uc2 8 cv 8uc3 16 cv 8uc4 24 depth 0 cv 8sc1 1 cv 8sc2 9 cv 8sc3 17 cv 8sc4 25 depth 1 cv 16uc1 ...