OpenCV 矩陣資料訪問方法

2021-06-27 17:34:57 字數 3694 閱讀 3396

cvmat矩陣資料結構是opencv的基礎資料型別,對於影象處理這種密級型運算,經常需要訪問,修改,設定其元素的值。opencv提供了很多優良的函式,能夠很簡單的實現上述功能。在《學習opencv》一書中,作者分別就簡單的方法,麻煩的方法,和恰當的方法對相關函式進行了講解,講得比較清晰。本文主要講解通過指標高效訪問cvmat元素的方法z及平時容易忽視的一些小問題。

1.關於元素資料型別

cvmat中資料型別由幾個部分構成 cv_(s|u|f)channels,s表示有符號的,u表示無符號的,f表示浮點數;比如cv_32f1,表示32位1通道浮點數;cv_8u3,表示8位無符號3通道整形;資料型別重要的原因在於

a.它決定了cvmat資料的分布,比如,若元素型別cv_8uc1(常用於灰度影象 ),那麼cvmat的資料排列是每行按照ggggggg(g表示乙個畫素的灰度值)的格式排列;若元素型別為cv_8uc3,則可以表示彩色影象,其行排列成為bgrbgrbgr(分別表示藍綠紅三個通道值,三個通道值表徵1個畫素)的形式;

b.在訪問其資料型別時,如何正確轉換成對應的資料型別指標;後面的例子會說到;

2.訪問cvmat中的元素

簡單的通過cv_mat_elem巨集,cvgetrealxd()函式即可實現,但是影象處理是計算密集型操作,這些函式雖然簡單易用,但是效率比較低。因此最常用的是採用指標來訪問cvmat中的元素。

cvmat結構中data結構對於指標訪問其元素非常重要.

其data成員為

uniondata;

由於是聯合體,因此在訪問時,

指標可以在這幾種型別的指標之間轉換。當然這還歸功於

cvmat中每行的位元組長度是固定的,成員step記錄了cvmat每行的位元組數。下面的**說明如何高效訪問矩陣元素。

cvmat* mat=cvcreatemat(5,3,cv_32fc1);//建立乙個5行3列的矩陣,元素型別為32位單通道浮點數;資料型別對於後面使用指標訪問矩陣元素非常重要。

cvzero(mat);

int row,col;

//下面的**給矩陣的每個元素賦值

for (row=0;rowheight;row++)

}//下面的3段**功能是一樣的,都是在控制台顯示各個元素的值

///code1

for (row=0;rowheight;row++)

}///code2

for (row=0;rowheight;row++)

std::coutstd::cout<

用指標除了順序訪問cvmat中的元素外,還可以訪問任意位置的元素,當然前提是需要自己計算指標。比如:

cvreleasemat(&mat);//用完釋放相關資源

因此,對cvmat中的元素不要拘泥於書上提供的幾種方式,在程式效率很重要的情況下,可以合理使用指標結合step完美的訪問cvmat中的元素,當然,使用指標,也有缺點,出現錯誤不容易發現,自己曾經遭過道。

自己幾點體會:

(1):和作者前面提到的一樣,陣列的資料型別非常重要。其中通道數表明了資料的排列方式,資料型別對後面的訪問方式有很大影響;

(2):在cvmat中,最重要一點要理解的是step。

其有兩點非常重要;

第一:其是以位元組為單位的;

第二:對於指定的矩陣每行的位元組長度是固定的。

由這兩點可以引申出來兩種訪問方式

第一:對於以位元組為單位的這種形式,在上面的code1、code2表現的非常明顯。這裡對於不同型別的陣列,因為其所佔的空間大小不同,但是每行的位元組長度是固定的,這裡可以通過比例放縮,即除以sizeof(*),來準確定位;

第二:對於指定的矩陣每行的位元組長度是固定這種形式,在第乙個列子中表現明顯。這裡先用簡單的ptr定位,再進行強制轉換。因為是利用了固定的長度,這種一一對應的方式來進行定位,非常方便。這裡是把定位和操作分開進行的。

依據以上分析,下面給出簡單的總結(

cvmat* mat;

mat = cvcreatemat(9,10,cv_64fc3);//注意所申請矩陣元素的型別,不同的型別訪問操作方法不同,但類似可推導,以此為例。

opencv中的多通道矩陣cvmat元素的訪問方法總結如下:1.

mat(i,j,1):  *(mat->data.db + i*(mat->step/8) + 3*j);//.db為double資料型別,step型別為int,代表矩陣每行的位元組數,因此要處以sizeof(double)  =8。

mat(i,j,2): *(mat->data.db + i*(mat->step/8) + 3*j+1);

mat(i,j,3): *(mat->data.db + i*(mat->step/8) + 3*j+2);

基本模式: *(mat->data.型別 + 行號*(該型別資料對應的一行的步長要按照該型別的長度來運算)+按照該型別來說的列數+所取的通道數)

2.

mat(i,j,1):  ((double*)(mat->data.ptr+i*mat->step))[3*j];//ptr的型別為uchar*,step型別為int,代表矩陣每行的位元組數。另外指標可以當做陣列名,因此可以這樣操作。

mat(i,j,2): ((double*)(mat->data.ptr+i*mat->step))[3*j+1];

mat(i,j,3): ((double*)(mat->data.ptr+i*mat->step))[3*j+2];

基本模式:((強轉型別*)

(mat->data.

ptr+行號*mat->step))[3*列號+所取的通道數]

3.

mat(i,j,1):  *( (double*)(mat->data.ptr+i*mat->step) + 3*j );//根據以上也可以這樣

總之就是c語言中的指標操作啦,要注意指標的型別,以及step的單位是位元組就可以了。

4.運用cv_mat_elem巨集來訪問

mat(i,j,3): cv_mat_elem(mat,double,i,3*j+2)

該方法最方便。

自己的幾點體會:

(1):第一種方法是順序訪問的,但是這種最可能出問題。learning opencvp-46中說到,cvmat資料指標可以指向乙個大型陣列中的roi,所以無法保證資料逐行連續訪問。因此,這種容易出問題。

(2):第二種和第三種方法是每次重新計算起點,這種是精確的。

//待看

OpenCV 矩陣訪問

正確的方式 前面介紹的一些讀取和寫入矩陣資料的方式,實際上,你可能很少會使用它們。因為,在大多數情況下,你需要使用最有效率的方式來訪問矩陣中的資料。如果使用以上的函式介面來訪問資料,效率比較低,你應該使用指標方式來直接訪問矩陣中資料。特別是,如果你想遍歷矩陣中所有元素時,就更需要這樣做了。在用指標直...

OpenCV 矩陣訪問

正確的方式 前面介紹的一些讀取和寫入矩陣資料的方式,實際上,你可能很少會使用它們。因為,在大多數情況下,你需要使用最有效率的方式來訪問矩陣中的資料。如果使用以上的函式介面來訪問資料,效率比較低,你應該使用指標方式來直接訪問矩陣中資料。特別是,如果你想遍歷矩陣中所有元素時,就更需要這樣做了。在用指標直...

OpenCv矩陣元素的訪問技巧

本文 cvmat矩陣資料結構是opencv的基礎資料型別,對於影象處理這種密級型運算,經常需要訪問,修改,設定其元素的值。opencv提供了很多優良的函式,能夠很簡單的實現上述功能。在 學習opencv 一書中,作者分別就簡單的方法,麻煩的方法,和恰當的方法對相關函式進行了講解,講得比較清晰。本文主...