opencv函式系列 自適應閾值

2021-06-24 11:12:44 字數 3379 閱讀 4555

在影象處理中較為常用的二值化方法有:1)全域性固定閾值;2)區域性自適應閾值;3)otsu等。

全域性固定閾值很容易理解,就是對整幅影象都是用乙個統一的閾值來進行二值化。

區域性自適應閾值則是根據畫素的鄰域塊的畫素值分布來確定該畫素位置上的二值化閾值。這樣做的好處在於每個畫素位置處的二值化閾值不是固定不變的,而是由其周圍鄰域畫素的分布來決定的。亮度較高的影象區域的二值化閾值通常會較高,而亮度較低的影象區域的二值化閾值則會相適應地變小。不同亮度、對比度、紋理的區域性影象區域將會擁有相對應的區域性二值化閾值。常用的區域性自適應閾值有:1)區域性鄰域塊的均值;2)區域性鄰域塊的高斯加權和。

而在opencv中實現了一下以上幾種二值化方法:

一、全域性閾值函式

threshold ( const void* src, void* dst, double thresh, double maxval, int type )

src源陣列,dst為目標陣列,thresh為閾值,maxval(m)為欲設最大值,type為閾值處理的型別,有如下幾種:

cv_thresh_binary,表示dst=(src>t)?m:0。

cv_thresh_binary_inv,表示dst=(src>t)?0:m。

cv_thresh_trunc,表示dst=(src>t)?m:src。

cv_thresh_tozero_inv,表示dst=(src>t)?0:src。

cv_thresh_tozero,表示dst=(src>t)?src:0。

二、自適應閾值函式

adaptivethreshold(

const cvarr* src,    輸入影象. 

cvarr* dst,     輸出影象.

double max_value,

int adaptive_method=cv_adaptive_thresh_mean_c,

int threshold_type=cv_thresh_binary,

int block_size=3,

double param=5 )

max_value:使用 cv_thresh_binary 和 cv_thresh_binary_inv 的最大值(見上文).

adaptive_method:自適應閾值演算法使用:cv_adaptive_thresh_mean_c 或 cv_adaptive_thresh_gaussian_c .

threshold_type:取閾值型別:必須是cv_thresh_binary或者cv_thresh_binary_inv

block_size:用來計算閾值的象素鄰域大小: 3, 5, 7, ...

param:與方法有關的引數。對方法 cv_adaptive_thresh_mean_c 和 cv_adaptive_thresh_gaussian_c, 它是乙個從均值或加權均值提取的常數(見討論), 儘管它可以是負數。

對於max_value中的兩個方式中的t是為每乙個象素點單獨計算的閾值,即每個畫素點的閾值都是不同的,就是將該畫素點周圍b*b區域內的畫素加權平均然後減去乙個常數param,從而得到該點的閾值。b由block_size指定,常數由param1指定

對方法 cv_adaptive_thresh_mean_c,先求出塊中的均值,再減掉param。

對方法 cv_adaptive_thresh_gaussian_c ,那麼區域中(x,y)周圍的畫素根據高斯函式按照他們離中心點的距離進行加權計算, 再減掉param。

三、使用方法

threshold(gray, t, 50, 255,cv_thresh_binary);  

adaptivethreshold(gray, iat, 255, cv_adaptive_thresh_mean_c, cv_thresh_binary, 3, 5);

但是網上有人看到有帖子說,adaptivethreshold的作用不是二值化而是提取物件邊緣的觀點,關鍵在於裡面的block_size引數,該引數是決定區域性閾值的block的大小,當block很小時,如block_size=3 or 5 or 7時,「自適應」的程度很高,即容易出現block裡面的畫素值都差不多,這樣便無法二值化,而只能在邊緣等梯度大的地方實現二值化,結果顯得它是邊緣提取函式。當把block_size設為比較大的值時,如block_size=21 or 31 or 41時,adaptivethreshold便是二值化函式。

四、ostu演算法

otsu法(最大類間方差法,有時也稱之為大津演算法)使用的是聚類的思想,把影象的灰度數按灰度級分成2個部分,使得兩個部分之間的灰度值差異最大,每個部分之間的灰度差異最小,通過方差的計算來尋找乙個合適的灰度級別 來劃分。  所以 可以在二值化的時候 採用otsu演算法來自動選取閾值進行二值化。otsu演算法被認為是影象分割中閾值選取的最佳演算法,計算簡單,不受影象亮度和對比度的影響。因此,使類間方差最大的分割意味著錯分概率最小。

用數學的表示就是:設分割前景點和背景點的閾值為t,則w0為前景點在影象中所佔的畫素比例,u0為所有前景點的均值,w1為背景點在影象中所佔的畫素比例,u1為所有背景點的均值,則整個影象的均值為u=w0*u0+w1*u1,目標函式g(t)=w0*(u0-u)^2+w1*(u1-u)^2為閾值t時的類間方差表示式。otsu就是使得g(t)取得全域性最大值,當g(t)為最大時所對應的t稱為最佳閾值(遍歷所有的灰度級然後找到使其最大的灰度)。由於otsu演算法是對影象的灰度級進行聚類,在執行otsu演算法之前,需要計算該影象的灰度直方圖。 五、

函式實現:

int main()

int otsu(const mat& src)

int width = src.cols;

int height = src.rows;

int pixelnum[256];

float pixelpro[256];

int pixelsum = width*height;

//初始化

for(int i=0; i<256; i++)

//計算每個畫素的個數

下面是ostu:

OpenCV自適應閾值處理

區域性自適應閾值則是根據畫素的鄰域塊的畫素值分布來確定該畫素位置上的二值化閾值。這樣做的好處在於每個畫素位置處的二值化閾值不是固定不變的,而是由其周圍鄰域畫素的分布來決定的。亮度較高的影象區域的二值化閾值通常會較高,而亮度較低的影象區域的二值化閾值則會相適應地變小。不同亮度 對比度 紋理的區域性影象...

OpenCV 閾值處理 二 自適應閾值

因此在同一副影象上的不同區域採用的是不同的閾值,從而使我們能在亮度不同的情況下得到更好的結果。自適應閾值函式 dst cv.adaptivethreshold src,maxvalue,adaptivemethod,thresholdtype,blocksize,c dst 引數 src 8位單通道...

OpenCV使用全域性閾值和自適應閾值

1 均值法 2 otsu 3 三角法 include include using namespace cv using namespace std intmain int argc,char ar namedwindow image window freeratio imshow image src...