opencv遍歷畫素的方式

2021-09-25 10:23:34 字數 3139 閱讀 7822

我們在實際應用中對影象進行的操作,往往並不是將影象作為乙個整體進行操作,而是對影象中的所有點或特殊點進行運算,所以遍歷影象就顯得很重要,如何高效的遍歷影象是乙個很值得**的問題。

mat類提供了乙個at的方法用於取得影象上的點,它是乙個模板函式,可以取到任何型別的影象上的點。下面我們通過乙個影象處理中的實際來說明它的用法。

在實際應用中,我們很多時候需要對影象降色彩,因為256*256*256實在太多了,在影象顏色聚類或彩色直方圖時,我們需要用一些代表性的顏色代替豐富的色彩空間,我們的思路是將每個通道的256種顏色用64種代替,即將原來256種顏色劃分64個顏色段,每個顏色段取中間的顏色值作為代表色。

通過上面的例子我們可以看出,at方法取影象中的點的用法:

image.at(i,j):取出灰度影象中i行j列的點。

image.at(i,j)[k]:取出彩色影象中i行j列第k通道的顏色點。其中uchar,vec3b都是影象畫素值的型別,不要對vec3b這種型別感覺害怕,其實在core裡它是通過typedef vec來定義的,n代表元素的個數,t代表型別。

更簡單一些的方法:opencv定義了乙個mat的模板子類為mat_,它過載了operator()讓我們可以更方便的取影象上的點。

mat_im=image;

im(i,j)=im(i,j)/div*div+div/2;

上面的例程中可以看到,我們實際喜歡把原圖傳進函式內,但是在函式內我們對原影象進行了修改,而將原圖作為乙個結果輸出,很多時候我們需要保留原圖,這樣我們需要乙個原圖的副本。

1 void colorreduce(const mat& image,mat& outimage,int div)

2 11 for(int i=0;i(i);

14 uchar* outdata=outimage.ptr(i);

15 for(int j=0;j

用指標除了用上面的方法外,還可以用指標來索引固定位置的畫素:

image.step返回影象一行畫素元素的個數(包括空白元素),image.elemsize()返回乙個影象畫素的大小。

&image.at(i,j)=image.data+i*image.step+j*image.elemsize();

下面的方法可以讓我們來為影象中的畫素宣告乙個迭代器:

matiterator_it;

mat_::iterator it;

如果迭代器指向乙個const影象,則可以用下面的宣告:

matconstiteratorit; 或者

mat_::const_iterator it;

下面我們用迭代器來簡化上面的colorreduce程式:

1 void colorreduce(const mat& image,mat& outimage,int div)

2 16 }

如果你想從第二行開始,則可以從image.begin()+image.rows開始。

上面4種方法中,第3種方法的效率最高!

很多時候,我們對影象處理時,要考慮它的鄰域,比如3*3是我們常用的,這在影象濾波、去噪中最為常見,下面我們介紹如果在一次影象遍歷過程中進行鄰域的運算。

下面我們進行乙個簡單的濾波操作,濾波運算元為[0 –1 0;-1 5 –1;0 –1 0]。

它可以讓影象變得尖銳,而邊緣更加突出。核心公式即:sharp(i.j)=5*image(i,j)-image(i-1,j)-image(i+1,j

)-image(i,j-1)-image(i,j+1)。

1 void imgfilter2d(const mat &image,mat& result)

2 17 }

18 // 把影象邊緣畫素設定為0

上面的程式有以下幾點需要說明:

1,staturate_cast是乙個型別轉換函式,程式裡是為了確保運算結果還在uchar範圍內。

2,row和col方法返回影象中的某些行或列,返回值是乙個mat。

3,setto方法將mat對像中的點設定為乙個值,scalar(n)為乙個灰度值,scalar(a,b,c)為乙個彩色值。

mat類把很多算數操作符都進行了過載,讓它們來符合矩陣的一些運算,如果+、-、點乘等。

下面我們來看看用位操作和基本算術運算來完成本文中的colorreduce程式,它更簡單,更高效。

將256種灰度階降到64位其實是拋棄了二進位制最後面的4位,所以我們可以用位操作來做這一步處理。

首先我們計算2^8降到2^n中的n:int n=static_cast(log(static_cast(div))/log(2.0));

然後可以得到mask,mask=0xff用下面簡直的語句就可以得到我們想要的結果:

result=(image&scalar(mask,mask,mask))+scalar(div/2,div/2,div/2);

很多時候我們需要對影象的乙個通訊單獨進行操作,比如在hsv色彩模式下,我們就經常把3個通道分開考慮。

1 vectorplanes;

2 // 將image分為三個通道影象儲存在planes中

3 split(image,planes);

4 planes[0]+=image2;

5 // 將planes中三幅影象合為乙個三通道影象

6 merge(planes,result);

出處:

opencv遍歷畫素的方式

1.使用at i,j mat類提供了乙個at的方法用於取得影象上的點,它是乙個模板函式,可以取到任何型別的影象上的點。一般typename用uchar表示灰度,vec3b表示彩色圖。2.使用指標來遍歷 更高效比第乙個 通過image.ptr i 取出第i行的指標 值得說明的是 程式中將三通道的資料轉...

OpenCV常用訪問畫素的幾種方式

1.直接用at訪問 2.使用mat 模板子類過載 訪問,需要提前知道影象型別 cv mat img image img j,i cv vec3b 注意1 此處的 j,i 並不是座標,是訪問的第j行第i列的畫素。注意2 使用at方法訪問較慢,宜用於隨機訪問,而非迴圈。得到第j行畫素首位址的指標 for...

關於opencv遍歷畫素速度的提高方案

1 二值化演算法經過測試後基本可以,但是在運動中會出現無法檢測特徵影象的地方,另外執行的速度還是不快。因為 中有兩個雙層巢狀的for迴圈,這是給遍歷影象用的。為了優化for迴圈遍歷畫素占用的時間,我的實驗過程如下 我在網上查詢到可以用opencv 的lut查表法來簡化遍歷畫素的時間,這個可以比指標快...