前言
在數字圖像處理中,圖像分割是很關鍵的一步,當圖像質量較好,光照很均勻的時候只需用全局閾值的方法就能很完美地完成圖像分割任務,但是有些時候會遇到光照不均勻的現象,這個時候就需要用一些技巧才能達到比較好的分割效果,本文要介紹的是一種通過分塊閾值進行分割的方法。
實例
在進入正題之前,我們先看一個實例,下面圖1和圖3為做硬幣面額識別拍攝的,可以看到,由於硬幣表面的反光以及打光角度的原因,圖片存在嚴重的光照不均現象。
如果對兩幅圖像直接進行全局閾值可以得到圖2和圖4的結果,可以看到分割的效果很差,比如第一幅,右上角的光照要強一些,而且右上角的硬幣存在一定的反光,灰度值整體偏高,導致最後分割效果很差。第二幅則是左邊部分光照太強,左邊的硬幣分割效果很差。
本文將用分塊閾值的方法解決這一問題。
圖1 光照不均勻圖像1 圖2 全局閾值處理結果
圖3 光照不均勻圖像2 圖4 全局閾值處理結果
分塊閾值思路
通過將圖像分割成若干塊,分別進行閾值分割,可以在一定程度上解決光照或反射造成的不均勻影響。選擇的塊要足夠小,以便每個塊的光照都近似均勻的,這樣自動閾值時,在高灰度區域就會用高閾值分割,在低灰度區域就會用低閾值分割。
圖5為分塊結果,示例中分塊與硬幣大小相當,分完塊之後就可以按塊進行全局閾值法(這裡採用常用的最大類間方差法,otsu法)處理了,但是需要注意的是有的塊中只有背景,這個時候需要進行判斷,排除對這種塊的處理。
對於這種塊的判斷,筆者嘗試過用otsu方法中提到的可分性度量:
筆者在計算出各個塊的可分性度量之後,發現區分效果並不是很好,後來通過分析最大類間方差法,有個想法就是用分割閾值處的類間平均灰度差判斷圖像塊的可分性,當圖像中只有背景或只有物體時,由於灰度值比較接近,則用otsu法算出的「背景」和「前景」平均灰度差(類間灰度差)會很小,類間平均灰度差 Δm 的數學表達式如下:
如圖5中各塊標註的文字所示,T為分割閾值,d為類間平均灰度差,可以看到當塊中只有背景時,平均灰度差與有物體時相差很大,選取特徵區分效果很好。本示例中,選灰度差20就能將兩種不同的塊很好的區分開。
圖5 分塊情況
之後僅對既有物體又有背景的塊進行自動閾值處理、二值化、填充孔洞,可以得到圖6的結果,可以看到每個硬幣都被很好的分割出來
圖6 分塊閾值處理結果
代碼%功能:對一副圖像進行分塊閾值,可解決光照不均分割不足的問題%通過判斷類間灰度差以排除純背景或純物體的幹擾%作者:wikiwen%日期:2017/10/24%平臺:matlab R2014
clc,clear;close all;
rn=5;cn=5;I = rgb2gray(imread('d.jpg'));[R , C]=size(I);%分別返回行和列數rblk=R/rn;cblk=C/cn;%小塊的行數和列數x = 0:cblk:C;y = 0:rblk:R;M = meshgrid(x,y); %產生網格N = meshgrid(y,x); %產生網格imshow(I);hold onplot(x,N,'r'); %畫出水平橫線plot(M,y,'r'); %畫出垂直豎線
T = zeros(rn,cn);dif = zeros(rn,cn);J = false(R,C);%初始化二值圖X = uint8(zeros(rblk,cblk));%分塊閾值,並判斷類間灰度差以排除純背景或純物體的幹擾for r=1:rn for c=1:cn r0=rblk*(r-1)+1;r1=rblk*r; c0=cblk*(c-1)+1;c1=cblk*c; X = I(r0:r1,c0:c1); T(r,c) = graythresh(X); [h,~] = histcounts(X,0:255); T_int =uint8(T(r,c)*255); dif(r,c) = graydiffer(h,T_int);%計算類間灰度差的函數略
str = ['T=',num2str(T_int),' d=',num2str(dif(r,c))]; text(c0+cblk/4,r0+rblk/2,str,'color','black');%顯示信息 if dif(r,c)>20 J(r0:r1,c0:c1) = ~im2bw(X,T(r,c)); end endendJ = imfill(J,'holes');%填充孔洞figure;imshow(J);%功能:計算一幅圖像前景和背景類間平均灰度差%輸入:直方圖數據h,分割閾值T%輸出:類間平均灰度差%作者:wikiwen%日期:2017/10/26function[differ] = graydiffer(h,T) s1 = sum(h(1:T)); s2 = sum(h(T:255)); n1 = 1:T; n2 = T:255; u1 = double(n1)*h(1:T)' / s1; %背景灰度均值 u2 = double(n2)*h(T:255)' / s2; %前景灰度均值
differ = uint8(u2-u1);end轉自:http://blog.csdn.net/kk55guang2/article/details/78475414
作者:wikiwen