CvMat矩陣資料訪問方法總結

2021-07-24 23:23:51 字數 3785 閱讀 1204

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::cout<

} ///code 3

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

std::cout<

}

///

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

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

}

std::cout<

}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):第二種和第三種方法是每次重新計算起點,這種是精確的。

2 3 訪問CvMat資料塊(矩陣維度與通道)

通過opencv的函式來訪問矩陣的資料 cvget d,cvset d cvgetreal1d,cvgetreal2d,cvgetreal3d,cvgetrealnd cvget1d,cvget2d,cvget3d,cvge cvset d,也有相應的函式系列 這些函式的缺點是,效率低 real表示...

CvMat的宣告及元素訪問總結

最近處理矩陣資料,但是訪問cvmat元素時總會出現錯誤,所以重新翻了一下書,查詢了一些資料,這都屬於最基本的東西。opencv教程基礎篇 p48 1 分配矩陣 cvmat prepoint cvcreatemat 1,2,cv 32fc1 行,列,元素型別 而且用指標訪問元素賦值可以成立 1 pre...

OpenCV 矩陣資料訪問方法

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