我記得開始接觸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 )這裡還需要注意乙個問題,很多opencv的函式支援的資料深度只有8位和32位的,所以要少使用cv_64f,但是vs的編譯器又會把float資料自動變成double型,有些不太爽。• 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 )
還有個需要注意的問題,就是流操作符《對於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訪問Mat容器類的畫素單元
1 利用.at函式來訪問mat容器的畫素單元 image.at i,j 1 這就訪問到了unsigned char型的二維矩陣image的第i行第j列的元素。這種情況可以直接應用在灰度影象素的訪問上。因為灰度圖是單通道的,每個元素位置可以單獨表徵的乙個畫素元素的畫素值。2 對於rgb影象來說,有三個...
OpenCV之Mat類詳解
學習mat矩陣,了解影象的儲存和mat矩陣的使用 2001年opencv剛出來的時候,是基於c語言介面而建。為了在記憶體 memory 中存放影象,當時採用名為 iplimage 的c語言結構體。其中最大的不足要數手動記憶體管理,使用者要為開闢和銷毀記憶體負責。一旦 開始變得越來越龐大,會越來越多地...
opencv中mat類引數釋義
type 型別 cv 8uc1 8 位單通道陣列 cv 32fc2 2 通道 復平面 浮點陣列 define cv 8uc1 cv maketype cv 8u,1 define cv 8uc2 cv maketype cv 8u,2 define cv 8uc3 cv maketype cv 8u...