算法的整體描述:
1.從上到下,從左到右,依次遍歷整幅圖像
2.如上圖A所示,A點為遇到的外輪廓點(步驟1遍歷的過程中遇到的第一個像素值為255的點即為外輪廓點),且沒有被標記過,則給A一個新的標記號;從A點出發,按照一定的規則,將A所在的外輪廓點全部跟蹤到,然后回到A點,並將路徑上的點全部標記為A的標號.
3.如上圖B所示,如果遇到已經標記過的點A',則從A'開始向右,將它的右邊所有的點都標記為A'的標號,直到遇到像素值為0的點為止.
4.如上圖C所示,如果遇到了一個已經標記的點B,且是內輪廓點(它的正下方像素值為0,且不在外輪廓上),則從B開始跟蹤內輪廓,將路徑上的點全部標記為B的標號,又因為B已經標記過,且和A相同,所以,外輪廓\內輪廓將用相同的標號進行標記.
5.如上圖D所示,如果遇到已經標記的內輪廓點B',則從B'開始向右,將它右邊所有的點均標記為B'的標號,直到遇到像素值為0的點為止.
6.結束
算法的詳細描述:
對於一個需要標記的圖像image,定義一個與它相對應的標記圖像label,用來保存標記信息,開始將label上的所有像素的值全部置為0,同時設置一個標簽變量C,初始化為1.然后開始掃描圖像image,遇到像素值為255的點,設置這個點為P點,下面針對不同的情況進行不同的處理:
1)如果P(i,j)點是一個像素值為255的點,在label圖像上這個點未被標記,且P點的上方是像素值為0的點,則P點是一個新的外輪廓點,這時將C的標簽值標記給label圖像上P點的位置(x,y),即label.data[x*width+y]=C,接着沿着P點做輪廓跟蹤,將輪廓上的所有點對應的label圖像上都標記為C,完成整個輪廓的標記后,將回到P點,最后,將C的值加1.整個標記過程如上圖所示.
2)如果P點的下方是unMark(參考步驟3)的點,則P點一定是內輪廓上的點,這時候有兩種情況,一種是P點在label上已經被標記過,說明它同時屬於外輪廓上的點;另一種情況是P點還沒有被標記過,按步驟1)介紹的情況來說,P點的左邊一定是一個已經被標記的點,則此時采用P點左邊點的標號來標記P點,接着從P點開始來跟蹤內輪廓,把內輪廓上的點全部標記為P點的標號.如上圖所示,兩幅圖像分別對應不同的情況,通過左邊的那張圖可以看出P點既是外輪廓點又是內輪廓點,
3)如果一個點P不是上述兩種情況,則它的左邊的點一定被標記過,只需要用它左邊的標號來標記label上的P點.
下面介紹一下,什么是unMark點,因為內輪廓的開始點P的下方肯定是像素值為0的點,很顯然,像素值為0的點並不一定是unMark點,如上圖右圖所示的Q點,它的下面像素值為0,但Q點並不在內輪廓上.
實際上,在外輪廓跟蹤的過程中,我們在外輪廓的周圍也做了標記,在輪廓的周圍像素點上對應的label圖像上被標記為負值,這樣Q點的下方就不是一個unMark點,所以,unMark點指的是label圖像上沒有被修改過的0點.
算法的重點是輪廓的查找與標記,下面將介紹一下外輪廓和內輪廓的查找跟蹤規則.
對某一像素點的周圍的8個像素點進行分析,做一個標號0-7,因為在遍歷圖像的過程中,遇到的第一個點肯定是外輪廓點,所以,首先來確定外輪廓點的搜索策略,對於外輪廓點P,有兩種情況,
1)如果P是外輪廓的起點,即是從P點開始跟蹤的,那么,從P的右上角即7的位置P1開始,看它的像素值是否為255,如果是,則把這個點加入外輪廓點,並將它標記為與P相同的標號,如果它的像素值為0,則按順序7-0-1-2-3-4-5-6進行搜索,直到遇到像素值為255的點為止,把這個點賦給P1,並加入外輪廓,並把它的標號設置為P的標號.假設2號點位置處的像素值為255,則7-0-1處的點都已經被搜索過,所以將這些點處對應的label圖像上標為負值,如下圖所示,
2)如果P不是外輪廓的起點,則它肯定是由某一個點進入的,我們設置為P1點,P1點的位置為x則0 <= x <= 7,則P點從(x+2)mod 8開始搜索下一個路徑,其中表達式的意思是+2取模,它反應在圖像上就是從P1點開始順時針數2個格子的位置.
外輪廓的跟蹤方式,確定之后,開始進行內輪廓的標記,不同之處在於如果P點是內輪廓的開始點,則它的開始搜索位置是從3處而不是7的位置開始的.