對於簡單的灰度圖像,如果目標與背景的灰度存在一定的差異,那么可以用閾值來提取目標。關鍵是確定閾值,常用方法有:
模態法、P參數法、可變閾值法、大津法和迭代逼近法等。
模態法:
取直方圖的波谷作為閾值。適用於目標與背景灰度差異較大,目標與背景的直方圖各有一個波峰的灰度圖像。
如果直方圖凹凸較激烈,尋找波谷存在困難,可以用領域點平均化處理使直方圖相對平滑。
P參數法:
當目標占圖像的面積比例已知,且目標最小灰度值大於背景最大灰度值時,可采用P參數法。具體做法是,如果目標灰度接近白色,則在
直方圖右側開始累計像素,直到累計像素占總像素數比例為P時,將當前的灰度作為閾值(否則從左側開始累計)。
例如下圖,月亮所占比列為0.45,它最低灰度與背景灰度稍有重合,閾值確定為75,最終基本提取出目標。
可變閾值法:
當圖像背景灰度多變時,可以為圖像不同部位設置不同的閾值,這樣可以很好地去除干擾。
例如提取下圖的蒲公英,圖像上部光照多,主要為蒲公英的羽毛,下部光照少,且主要為莖,對上中下采取不同閾值的提取效果會好很多。
大津法:
大津法的應用最廣泛,有很好的自適應閾值。適用於批量圖像提取或者動態灰度圖像提取(然而事實證明,當大津遇到反光時,干擾也會很嚴重)。
大津法的原理如下:
設T為分割閾值,由此划分出區域記為R1和R2。
R1占圖像總像素的比例為θ1,R2占圖像總像素的比例為θ2。
圖像的平均灰度值為μ0,R1的平均灰度為μ1,R2的平均灰度為μ2。
顯然有:
μ0=θ1*μ1+θ2*μ2
如果閾值選得恰當,則R1與R2的灰度差應該較大,那么μ1與μ0、μ2與μ0的差的絕對值也就較大。
定義類間方差,來反應灰度差大小:
σ2=θ1(μ1-μ0)2+θ2(μ2-μ0)2
對於每個選定的閾值T,都有σ對應,而最大σ的閾值T則是最佳閾值。
另外,盡管有化簡公式來減少迭代次數的方法(https://www.cnblogs.com/kensporger/p/11270452.html),大津法的過程計算量還是很大的。
迭代逼近法:
此法是大津法的簡化版,具體步驟如下:
取最大灰度與最小灰度平均值(也可以是圖像平均灰度)為初始閾值T,由此得兩個區域為R1和R2
計算R1和R2的灰度均值μ1、μ2
選擇新閾值T=(μ1+μ2)/2,重復以上步驟,直到T不再變化或變化在一定范圍內。
采用該法的效果如圖所示,大概只迭代了五次左右:
但是,該法確定的閾值很粗糙,往往與最佳閾值會有較大偏差,比如提取之前的月亮,表現得就並不是很好了:
以上大部分matlab仿真測試代碼羅列如下:
%p參數法確定閾值 function thres = pthres(file,p) imga = imread(file); %灰度化 imga = rgb2gray(imga); %獲取大小 [sizex,sizey]=size(imga); %直方圖 histogram = zeros(256,1); for i=1:sizex for j=1:sizey histogram(imga(i,j)+1)=histogram(imga(i,j)+1)+1; end end %累計像素 pixels_cnt=0; thres=256; while(pixels_cnt<p*sizex*sizey) pixels_cnt=pixels_cnt+histogram(thres); thres=thres-1; end %根據閾值二值化 mybw=imbinarize(imga,(thres-1)/255); subplot(1,2,1); imshow(imga); title('原圖'); subplot(1,2,2); imshow(mybw); title('p參數法二值化'); end
%多閾值分割實例 imga=imread('multi_thres.jpg'); imga=rgb2gray(imga); single = imbinarize(a,85/255); multi(250:300,:) = imbinarize(a(250:300,:),85/255); multi(150:250,:) = imbinarize(a(150:250,:),150/255); multi(1:150,:) = imbinarize(a(1:150,:),170/255); subplot(1,3,1); imshow(imga); title('原圖'); subplot(1,3,2); imshow(single); title('單閾值處理'); subplot(1,3,3); imshow(multi); title('多閾值處理');
%迭代逼近法 function thres=iterator(file) imga = imread(file); %灰度化 imga = rgb2gray(imga); %獲取大小 [sizex,sizey]=size(imga); %直方圖與總灰度統計 gray_sum=0; histogram = zeros(256,1); for i=1:sizex for j=1:sizey histogram(imga(i,j)+1)=histogram(imga(i,j)+1)+1; gray_sum= gray_sum+double(imga(i,j)+1); end end %初始閾值 thres=gray_sum/(sizex*sizey); old_thres=0; %迭代逼近 while(abs(thres-old_thres)>1) disp(thres); u1=0;u2=0; cnt1=0;cnt2=0; for i=1:thres u1=u1+histogram(i)*i; %統計R1區域平均灰度 cnt1=cnt1+histogram(i); end for i=256:-1:thres u2=u2+histogram(i)*i; %統計R2區域平均灰度 cnt2=cnt2+histogram(i); end u1=u1/cnt1; u2=u2/cnt2; old_thres=thres; thres=(u1+u2)/2; %新閾值 end mybw=imbinarize(imga,(thres-1)/256); subplot(1,2,1); imshow(imga); title('原圖'); subplot(1,2,2); imshow(mybw); title('迭代逼近法二值化'); end