影象的連通域標記演算法及工具介紹
注:本文大部分內容來源於 網路 ,尤其是原理部分圖片全部非本人所作
簡介
之前在 CSDN 上介紹過一個關於如何使用skimage以及opencv標記二值影象的連通域問題。實際上估計不是太多的人懂得標記連通域的原理,加上在醫學影象處理中,我們常常用到3維影象,而上述工具只解決了2維影象上的情況,並不支援3維影象的標記(目前還不支援),因此有必要這個連通域標記進行進一步說明。
本文主要介紹兩點,一是 介紹一種連通域標記的演算法 ,中文翻譯過來我給它叫兩階段法(two pass); 另一個方面在2維連通域標記的基礎上 介紹一個新的高效的3維連通域標記工具 。
通過這個簡單的原理,相信讀者可以根據需求自己去寫一個更高效的連通域標記演算法。
原理
如圖1所示,對於一個二值影象,其前景為1,背景為0,我們希望給其相連的前景部分標記為同一個label,不同的連通域標記為不同的label,我們希望得到的最終結果如圖2所示(我是真的不知道簡書該怎麼並排顯示影象...)。

圖1 簡單示例

圖2 連通域標記最終結果
一種標記連通域的方法叫兩階段法,也就是說,通過遍歷兩次影象上的點就可以完成標記工作,下面我們主要看看它是怎麼工作的。
第一階段
從圖3開始,我們從影象的左上角點遍歷整個影象。對於第一個黃點(0,0),我們檢查它的上邊和左邊有沒有已經標記好的label,顯然沒有,因此給其標記為 1
. 如圖3.

圖3 label-step1
接下來看第二個畫素(0, 1), 繼續檢查它的左邊和上邊是否有標記好的畫素,由於它左邊的一個畫素已經標記為 1
, 因此第二個畫素也標記為 1
. 由於第三個畫素(0, 2)是一個背景點,因此直接跳過。再看第4個畫素(0, 3),由於其左邊是背景,因此認為其左邊沒有標記,同時上邊也沒有標記,因此需要給它一個新的label, 2
. 如圖4.

圖4 label-step2
接下來同理,直到第一行的最後一個畫素,我們有了三個標記。如圖5.

圖5 label-step3
第二行同理,我們看到目前為止還沒有出現什麼意外,只要檢查一個畫素的左邊和上邊是否有標記,如果有,就給它打上同樣的標記即可。如圖6.

圖6 label-step4
到了第三行的第四個元素(2, 3),我們發現了一個意外情況,就是該畫素的上邊有了一個label 2
,而它的左邊同樣也有一個label 1
,這怎麼辦呢? 這種情況下,我們給該畫素標記為兩個label中較小的那個,也就是 1
,同時還要有另一個操作,就是讓label 2
隸屬於 label 1
,如圖7.

圖7 label-step5
有了上述處理矛盾的情況,我們就可以繼續往下標記了。始終堅持以下原則:
- 如果遇上一個背景點,直接跳過,不做處理。
- 如果對於一個畫素點,其上面和左邊都沒有標記好的label,那麼就從小到達給它一個新的label。
- 如果對於一個畫素點,其上面或者/並且左邊已經有了標記好的label,且label不衝突,那就把這個畫素也標記成同樣的label
- 如果對於一個畫素,其上面和左邊都有了label,且兩個label衝突了,那麼就把該畫素標記為較小的那個label,同時記住較大的label隸屬於較小的label。
遵循上述原則可以得到圖8-12的結果:

圖8 label-step6

圖9 label-step7

圖10 label-step8

圖11 label-step9

圖12 label-step10
至此我們標記完了影象上的每一個畫素,並給他們賦了一個值,唯一的問題在於有些連通域我們看著是一個,但是卻給了它兩個label,但是好在我們知道他們label的繼承關係,因此第二遍就是把具有繼承關係的部分給合併成為一個。
第二階段
依然從左上角點開始遍歷,每遍歷一個label,都要查查該畫素是否具有繼承關係。比如第一個畫素(0, 0),由於它是 1
,發現了它有繼承關係,但是好在他是父label,因此不用管他;當到了第三個畫素(0, 2),是個背景,不需要管它,直接跳過,也不用查繼承關係;當到了第四個畫素,查到了label 2
具有繼承關係,且label 2
隸屬於label 1
, 不好意思,我們就不要label 2
了,直接把它改為label 1
,後面的以此類推。圖13-16都遵循上述原則。

圖13 label-step11

圖14 label-step12

圖15 label-step13

圖16 label-step14
至此,我們第二次遍歷完了整個影象,同時也把所有的連通域標記完了。
至此,我們大概瞭解了兩階段法標記連通域的基本原理,希望能夠對讀者有所幫助。
工具介紹
這方面的工具很多,我自己常用的有這麼3個:一個是scikit image, 一個是opencv3,這兩個工具目前只支援2維影象的連通域標記。還有一個是github上的一個開源工具,比較高效的完成了3維影象的連通域標記,也是近期發現的,感謝作者吧,哈哈。
- skimage的連通域標記演算法
skimage.messure.label - opencv3的連通域標記演算法
connectedComponents - 一個高效的3d連通域標記演算法
connected-components-3d