再談OpenCV資料結構Mat詳解

2021-08-15 03:45:31 字數 3441 閱讀 7651

我記得開始接觸opencv就是因為乙個演算法裡面需要2維動態陣列,那時候看core這部分也算是走馬觀花吧,隨著使用的增多,對mat這個結構越來越喜愛,也覺得有必要溫故而知新,於是這次再看看mat。

mat最大的優勢跟stl很相似,都是對記憶體進行動態的管理,不需要之前使用者手動的管理記憶體,對於一些大型的開發,有時候投入的lpimage記憶體管理的時間甚至比關注演算法實現的時間還要多,這顯然是不合適的。除了有些嵌入式場合必須使用c語言,我任何時候都強烈像大家推薦mat。

mat這個類有兩部分資料。乙個是matrix header,這部分的大小是固定的,包含矩陣的大小,儲存的方式,矩陣儲存的位址等等。另乙個部分是乙個指向矩陣包含畫素值的指標。

[cpp]view plain

copy

mat a, c; 

// creates just the header parts

a = imread(argv[1], cv_load_image_color); // here we』ll know the method used (allocate matrix)

mat b(a); // use the copy constructor

c = a; // assignment operator

需要注意的是,

copy這樣的操作只是copy了矩陣的matrix header和那個指標,而不是矩陣的本身,也就意味著兩個矩陣的資料指標指向的是同乙個位址,需要開發者格外注意。比如上面這段程式,a、b、c指向的是同一塊資料,他們的header不同,但對於a的操作同樣也影響著b、c的結果。剛剛提高了記憶體自動釋放的問題,那麼當我不再使用a的時候就把記憶體釋放了,那時候再操作b和c豈不是很危險。不用擔心,opencv的大神為我們已經考慮了這個問題,是在最後乙個mat不再使用的時候才會釋放記憶體,咱們就放心用就行了。

如果想建立互不影響的mat,是真正的複製操作,需要使用函式

clone()或者copyto()。

說到資料的儲存,這一直就是乙個值得關注的問題,mat_對應的是cv_8u,mat_對應的是cv_8u,mat_對應的是cv_8s,mat_對應的是cv_32s,mat_對應的是cv_32f,mat_對應的是cv_64f,對應的資料深度如下:

• cv_8u - 8-bit unsigned integers ( 0..255 )

• cv_8s - 8-bit signed integers ( -128..127 )

• cv_16u - 16-bit unsigned integers ( 0..65535 )

• cv_16s - 16-bit signed integers ( -32768..32767 )

• cv_32s - 32-bit signed integers ( -2147483648..2147483647 )

• cv_32f - 32-bit floating-point numbers ( -flt_max..flt_max, inf, nan )

• cv_64f - 64-bit floating-point numbers ( -dbl_max..dbl_max, inf, nan )

這裡還需要注意乙個問題,很多opencv的函式支援的資料深度只有8位和32位的,所以要少使用cv_64f,但是vs的編譯器又會把float資料自動變成double型,有些不太爽。

還有個需要注意的問題,就是流操作符《對於mat的操作,僅限於mat是2維的情況。

還有必要說一下mat的儲存是逐行的儲存的。

再說說mat的建立,方式有兩種,羅列一下:1.呼叫create(行,列,型別)2.mat(行,列,型別(值))。例如:

[cpp]view plain

copy

// make a 7x7 complex matrix filled with 1+3j.

mat m(7,7,cv_32fc2,scalar(1,3));  

// and now turn m to a 100x60 15-channel 8-bit matrix.

// the old content will be deallocated

m.create(100,60,cv_8uc(15));  

要是想建立更高維的矩陣,要寫成下面的方式

[cpp]view plain

copy

// create a 100x100x100 8-bit array

intsz = ;  

mat bigcube(3, sz, cv_8u, scalar::all(0));  

對於矩陣的行操作或者列操作,方式如下:(

注意對列操作時要新建乙個mat,我想應該跟列位址不連續有關)

[cpp]view plain

copy

// add the 5-th row, multiplied by 3 to the 3rd row

m.row(3) = m.row(3) + m.row(5)*3;  

// now copy the 7-th column to the 1-st column

// m.col(1) = m.col(7); // this will not work

mat m1 = m.col(1);  

m.col(7).copyto(m1);  

下面的東西就比較狂暴了,

對於外來的資料,比如你從別的地方接受了一幅,但可以不是mat結構的,而只有乙個資料的指標,看看接下來的**是如何應付的,重點哦,親

[cpp]view plain

copy

void

process_video_frame(

const

unsigned 

char

* pixels,  

intwidth, 

intheight, 

intstep)    

親,有木有很簡單!!!

還有一種快速初始化資料的辦法,如下:

[cpp]view plain

copy

double

m[3][3] = , , };  

mat m = mat(3, 3, cv_64f, m).inv();  

也可以把原來的iplimage格式的直接用mat(iplimage)的方式轉成mat結構,也可以像matlab一樣呼叫zeros()、ones()、eye()這樣的函式進行初始化。

如果你需要提前釋放資料的指標和記憶體,可以呼叫release()。

對於資料的獲取,當然還是呼叫at(3, 3)這樣的格式為最佳。其他的方法我甚少嘗試,就不敢介紹了。

最後要提的一點是關於mat的表示式,這個也非常多,加減乘除,轉置求逆,我怎麼記得我以前介紹過呢。那就不多說啦~

OpenCV學習再談OpenCV資料結構Mat

我記得開始接觸opencv就是因為乙個演算法裡面需要2維動態陣列,那時候看core這部分也算是走馬觀花吧,隨著使用的增多,對mat這個結構越來越喜愛,也覺得有必要溫故而知新,於是這次再看看mat。mat最大的優勢跟stl很相似,都是對記憶體進行動態的管理,不需要之前使用者手動的管理記憶體,對於一些大...

OpenCV中Mat資料結構使用舉例

mat mtx img1 iplimage mat,新的mat型別與原來的iplimage型別共享影象資料,轉換只是建立乙個mat矩陣頭 or mat mtx img1 cvmat oldmat mtx mat cvmat 只是建立矩陣頭,而沒有複製資料,oldmat不用手動釋放 cv assert...

OpenCV基礎篇之Mat資料結構

filename matobj.cpp author xiahouzuoxin 163.com version v1.0 date thu 15 may 2014 09 12 45 pm cst brief include include include using namespace std us...