圖像腐蝕、膨脹、細化 算法
這三個內容屬於數學形態學(Mathematical Morphology),它是法國和德國的科學家在研究岩石結構時創建的一門學科。形態學的用途主要是獲取物體拓撲和結構信息,它經過物體和結構元素相互做用的某些運算,獲得物體更本質的形態。在圖象處理中的應用主要是:(1)利用形態學的基本運算,對圖象進行觀察和處理,從而達到改善圖象質量的目的;(2)描述和定義圖象的各類幾何參數和特徵,如面積、周長、連通度、顆粒度、骨架和方向性等。這裏介紹二值圖象的形態學運算,對於灰度圖象的形態學運算。 spa
先來定義一些基本符號和關係。 對象
1. 元素 索引
設有一幅圖象X,若點a在X的區域之內,則稱a爲X的元素,記做a∈X,如圖6.1所示。 ci
2. B包含於X element
設有兩幅圖象B,X。對於B中全部的元素ai,都有ai∈X,則稱B包含於(included in)X,記做B X,如圖6.2所示。 數學
3. B擊中X it
設有兩幅圖象B,X。若存在這樣一個點,它便是B的元素,又是X的元素,則稱B擊中(hit)X,記做B↑X,如圖6.3所示。 io
4. B不擊中X table
設有兩幅圖象B,X。若不存在任何一個點,它便是B的元素,又是X的元素,即B和X的交集是空,則稱B不擊中(miss)X,記做B∩X=Ф;其中∩是集合運算相交的符號,Ф表示空集。如圖6.4所示。
|
|
|
|
5. 補集
設有一幅圖象X,全部X區域之外的點構成的集合稱爲X的補集,記做Xc,如圖6.5所示。顯然,若是B∩X=Ф,則B在X的補集內,即B Xc。
6. 結構元素
設有兩幅圖象B,X。若X是被處理的對象,而B是用來處理X的,則稱B爲結構元素(structure element),又被形象地稱作刷子。結構元素一般都是一些比較小的圖象。
7. 對稱集
設有一幅圖象B,將B中全部元素的座標取反,即令(x,y)變成(-x,-y),全部這些點構成的新的集合稱爲B的對稱集,記做Bv,如圖6.6所示。
8. 平移
設有一幅圖象B,有一個點a(x0,y0),將B平移a後的結果是,把B中全部元素的橫座標加x0,縱座標加y0,即令(x,y)變成(x+x0,y+y0),全部這些點構成的新的集合稱爲B的平移,記做Ba,如圖6.7所示。
|
|
好了,介紹了這麼多基本符號和關係,如今讓咱們應用這些符號和關係,看一下形態學的基本運算。
把結構元素B平移a後獲得Ba,若Ba包含於X,咱們記下這個a點,全部知足上述條件的a點組成的集合稱作X被B腐蝕(Erosion)的結果。用公式表示爲:E(X)={a| Ba X}=X B,如圖6.8所示。
圖6.8中X是被處理的對象,B是結構元素。不難知道,對於任意一個在陰影部分的點a,Ba 包含於X,因此X被B腐蝕的結果就是那個陰影部分。陰影部分在X的範圍以內,且比X小,就象X被剝掉了一層似的,這就是爲何叫腐蝕的緣由。
值得注意的是,上面的B是對稱的,即B的對稱集Bv=B,因此X被B腐蝕的結果和X被 Bv腐蝕的結果是同樣的。若是B不是對稱的,讓咱們看看圖6.9,就會發現X被B腐蝕的結果和X被 Bv腐蝕的結果不一樣。
圖6.8和圖6.9都是示意圖,讓咱們來看看其實是怎樣進行腐蝕運算的。
在圖6.10中,左邊是被處理的圖象X(二值圖象,咱們針對的是黑點),中間是結構元素B,那個標有origin的點是中心點,即當前處理元素的位置,咱們在介紹模板操做時也有過相似的概念。腐蝕的方法是,拿B的中心點和X上的點一個一個地對比,若是B上的全部點都在X的範圍內,則該點保留,不然將該點去掉;右邊是腐蝕後的結果。能夠看出,它仍在原來X的範圍內,且比X包含的點要少,就象X被腐蝕掉了一層。
圖6.10 腐蝕運算
圖6.11爲原圖,圖6.12爲腐蝕後的結果圖,可以很明顯地看出腐蝕的效果。
膨脹(dilation)能夠看作是腐蝕的對偶運算,其定義是:把結構元素B平移a後獲得Ba,若Ba擊中X,咱們記下這個a點。全部知足上述條件的a點組成的集合稱作X被B膨脹的結果。用公式表示爲:D(X)={a | Ba↑X}=X B,如圖6.13所示。圖6.13中X是被處理的對象,B是結構元素,不難知道,對於任意一個在陰影部分的點a,Ba擊中X,因此X被B膨脹的結果就是那個陰影部分。陰影部分包括X的全部範圍,就象X膨脹了一圈似的,這就是爲何叫膨脹的緣由。
一樣,若是B不是對稱的,X被B膨脹的結果和X被 Bv膨脹的結果不一樣。
讓咱們來看看其實是怎樣進行膨脹運算的。在圖6.14中,左邊是被處理的圖象X(二值圖象,咱們針對的是黑點),中間是結構元素B。膨脹的方法是,拿B的中心點和X上的點及X周圍的點一個一個地對,若是B上有一個點落在X的範圍內,則該點就爲黑;右邊是膨脹後的結果。能夠看出,它包括X的全部範圍,就象X膨脹了一圈似的。
細化
細化(thinning)算法有不少,這裏介紹一種簡單並且效果很好的算法,用它就可以實現從文本抽取骨架的功能。咱們的對象是白紙黑字的文本,但在程序中爲了處理的方便,仍是採用256級灰度圖,不過只用到了調色板中0和255兩項。
所謂細化,就是從原來的圖中去掉一些點,但仍要保持原來的形狀。實際上,是保持原圖的骨架。所謂骨架,能夠理解爲圖象的中軸,例如一個長方形的骨架是它的長方向上的中軸線;正方形的骨架是它的中心點;圓的骨架是它的圓心,直線的骨架是它自身,孤立點的骨架也是自身。文本的骨架嘛,前言中的例子顯示的很明白。那麼怎樣判斷一個點是否能去掉呢?顯然,要根據它的八個相鄰點的狀況來判斷,咱們給幾個例子(如圖6.22所示)。
圖6.22中,(1)不能刪,由於它是個內部點,咱們要求的是骨架,若是連內部點也刪了,骨架也會被掏空的;(2)不能刪,和(1)是一樣的道理;(3)能夠刪,這樣的點不是骨架;(4)不能刪,由於刪掉後,原來相連的部分斷開了;(5)能夠刪,這樣的點不是骨架;(6)不能刪,由於它是直線的端點,若是這樣的點刪了,那麼最後整個直線也被刪了,剩不下什麼;總結一下,有以下的判據:(1)內部點不能刪除;(2)孤立點不能刪除;(3)直線端點不能刪除;(4)若是P是邊界點,去掉P後,若是連通份量不增長,則P能夠刪除。
咱們能夠根據上述的判據,事先作出一張表,從0到255共有256個元素,每一個元素要麼是0,要麼是1。咱們根據某點(固然是要處理的黑色點了)的八個相鄰點的狀況查表,若表中的元素是1,則表示該點可刪,不然保留。
查表的方法是,設白點爲1,黑點爲0;左上方點對應一個8位數的第一位(最低位),正上方點對應第二位,右上方點對應的第三位,左鄰點對應第四位,右鄰點對應第五位,左下方點對應第六位,正下方點對應第七位,右下方點對應的第八位,按這樣組成的8位數去查表便可。例如上面的例子中(1)對應表中的第0項,該項應該爲0;(2)對應37,該項應該爲0;(3)對應173,該項應該爲1;(4)對應231,該項應該爲0;(5)對應237,該項應該爲1;(6)對應254,該項應該爲0;(7)對應255,該項應該爲0。
這張表我已經替你們作好了,可花了我很多時間呢!
static int erasetable[256]={
0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1,
1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1,
0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1,
1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1,
1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,1,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1,
1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,1,
0,0,1,1,0,0,1,1, 1,1,0,1,1,1,0,1,
1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0,
1,1,0,0,1,1,0,0, 0,0,0,0,0,0,0,0,
1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0,
1,1,0,0,1,1,0,0, 1,1,0,1,1,1,0,0,
1,1,0,0,1,1,1,0, 1,1,0,0,1,0,0,0
};
有了這張表,算法就很簡單了,每次對一行一行的將整個圖象掃描一遍,對於每一個點(不包括邊界點),計算它在表中對應的索引,若爲0,則保留,不然刪除該點。若是此次掃描沒有一個點被刪除,則循環結束,剩下的點就是骨架點,若是有點被刪除,則進行新的一輪掃描,如此反覆,直到沒有點被刪除爲止。
實際上,該算法有一些缺陷。舉個簡單的例子,有一個黑色矩形,如圖6.23所示。
圖6.23通過細化後,咱們預期的結果是一條水平直線,且位於該黑色矩形的中心。實際的結果確實是一條水平直線,但不是位於黑色矩形的中心,而是最下面的一條邊。
爲何會這樣,咱們來分析一下:在從上到下,從左到右的掃描過程當中,咱們遇到的第一個黑點就是黑色矩形的左上角點,經查表,該點能夠刪。下一個點是它右邊的點,經查表,該點也能夠刪,如此下去,整個一行被刪了。每一行都是一樣的狀況,因此都被刪除了。到了最後一行時,黑色矩形已經變成了一條直線,最左邊的黑點不能刪,由於它是直線的端點,它右邊的點也不能刪,由於若是刪除,直線就斷了,如此下去,直到最右邊的點,也不能刪,由於它是直線的右端點。因此最下面的一條邊保住了,但這並非咱們但願的結果。
解決的辦法是,在每一行水平掃描的過程當中,先判斷每一點的左右鄰居,若是都是黑點,則該點不作處理。另外,若是某個黑點被刪除了,那麼跳過它的右鄰居,處理下一個點。這樣就避免了上述的問題。
|
|
解決了上面的問題,咱們來看看處理後的結果,如圖6.24所示。此次變成一小段豎線了,仍是不對,是否是很沮喪?彆着急,讓咱們再來分析一下:在上面的算法中,咱們遇到的第一個能刪除的點就是黑色矩形的左上角點;第二個是第一行的最右邊的點,即黑色矩形的右上角點;第三個是第二行的最左邊的點;第四個是第二行的最右邊的點;……;整個圖象處理這樣一次後,寬度減小2。每次都是如此,直到剩最中間一列,就不能再刪了。爲何會這樣呢?緣由是這樣的處理過程只實現了水平細化,若是在每一次水平細化後,再進行一次垂直方向的細化(只要把上述過程的行列換一下),就能夠了。
這樣一來,每處理一次,刪除點的順序變成:(先是水平方向掃描)第一行最左邊的點;第一行最右邊的點;第二行最左邊的點;第二行最右邊的點;……最後一行最左邊的點;最後一行最右邊的點;(而後是垂直方向掃描)第二列最上邊的點(由於第一列最上邊的點已被刪除);第二列最下邊的點;第三列最上邊的點;第三列最下邊的點;……倒數第二列最上邊的點(由於倒數第一列最上邊的點已被刪除);倒數第二列最下邊的點。咱們發現,恰好剝掉了一圈,這也正是細化要作的事。實際的結果也驗證了咱們的想法。