python連通區域計算長度 連通區域演算法小結

2021-10-11 19:26:45 字數 2669 閱讀 2530

聯通區域標記(connected component labeling)是影象處理裡面常用的乙個技術,它是用來檢測二值影象中聯通的區域,在許多跟蹤檢測演算法中充當目標區域檢測的作用。常見的ccl(connected component labeling)包括two-pass的方法和one-pass的方法,這裡pass就是掃瞄的遍數,two-pass就是掃瞄兩遍的演算法,one-pass就是掃瞄一遍的演算法。下面僅就這兩類演算法中有代表性的演算法做乙個簡單的介紹。

two-pass

傳統的two-pass:

逐行掃瞄影象上的點,檢查每個點是否是前景點,如果不是,繼續掃瞄;

檢查該前景點的左邊的點和上邊的點 如果有乙個為前景點,則為當前掃瞄點標記和此點相同編號;

如果兩個都是前景點,則選擇標號小的,為當前掃瞄點標記編號;這裡注意如果兩個都是前景點且標號不同,需要把標號小的點設為標號大的點的父節點,以方便第二遍掃瞄的時候用並查集演算法(參考 利用不相交集實現等價元素的聚類

)合併;

如果都不是,則賦值目前標號label,label++(label初始值為零);

再次掃瞄影象,利用並查集演算法合併聯通的不同的label的區域。

run-based的two-pass:

該演算法定義每一行聯通的乙個區域叫做 run

,把run看成乙個整體,逐行搜尋時,完成乙個run掃瞄好後再進行整個run的標記,標記的準則是按照上一行是否有run和自己聯通來判斷如何標記當前的run;

每個run有兩個label:representative label和乙個provisional label,這裡我們用r和p表示。當出現上一行n個run聯通當前行的run的時候,更改n個run的r為最小的r,我們設為rmin,同時標記當前run的p和r為rmin;

該演算法的優勢在於減少了第一遍掃瞄時標號的數量,從而減少了第二遍中聯通區域的合併任務。具體演算法可以參考 「a run-based two-scan labeling algorithm」

one-pass

基於區域生長的方法

單次掃瞄的演算法有一種基於區域生長的聯通區域標記演算法,基本的思路可以參考部落格 二值影象連通區標記之區域生長法

輸入待標記影象bitmap,初始化乙個與輸入影象同樣尺寸的標記矩陣labelmap,乙個佇列queue以及標記計數labelindex;

按從左至右、從上至下的順序掃瞄bitmap,當掃瞄到乙個未被標記的前景畫素p時,labelindex加1,並在labelmap中標記p(相應點的值賦為labelindex),同時,掃瞄p的八鄰域點,若存在未被標記的前景畫素,則在labelmap中進行標記,並放入queue中,作為區域生長的種子;

當queue不為空時,從queue中取出乙個生長種子點p1,掃瞄p1的八鄰域點,若存在未被標記過的前景畫素,則在labelmap中進行標記,並放入queue中;

重複3直至queue為空,乙個連通區標記完成;

轉到2,直至整幅影象被掃瞄完畢,得到標記矩陣labelmap和連通區的個數labelindex。

基於輪廓跟蹤的方法

還有一種經典的單次掃瞄的的演算法是由台灣的**研究院資訊科學研究所的 張復

提出的,源**可以在其 實驗室**

,就是實現的這個演算法。演算法的詳細介紹可以參考 「a linear-time component-labeling algorithm using contour tracing technique」

,這裡作乙個簡單的介紹。

逐行掃瞄影象,設當前畫素為p

如果p為為背景點,則繼續,直到掃瞄到前景點;

如果p是 unlabeled

的,且正上方的畫素為背景畫素(如圖1所示),認為p是乙個新遇見的 外輪廓

的起點,然後以p為起點,開始進行contour tracing跟蹤外輪廓,為該輪廓上的所有點標記為新的的標號c,然後c=c+1;

圖 1如果p的正下方的畫素是 unmarked

(這裡marked是指在contour tracing中外圍輪廓周圍的背景點會被mark)的背景畫素。這裡有兩種情況:如果p是labeled的(如圖2所示),則p既是外輪廓點,又是內輪廓點;如果p是unlabled的(如圖3所示),則p左邊的點n一定是labeled,則設定p和n相同的標號。無論是那種情況,都以p為起點進行contour tracing跟蹤內輪廓,並把輪廓上所有的點標記和p相同的標號。

圖 2圖 3如果p不是以上兩種情況,即p不是輪廓點,則p的左邊點n一定是標記點,把p標記成和n相同標號即可。

contour tracking

當遇到乙個外輪廓或是內輪廓的起點時,首先通過 tracker

搜尋輪廓的下乙個點,直到輸出點又一次為起點位置,從而實現輪廓的跟蹤。

tracker

如圖4所示,tracker的目的是搜尋當前點p周圍八鄰域的點,找到輪廓的下乙個點。按照順時針方向搜尋,對於乙個外輪廓的起點,其起始搜尋點為7,因為6已經知道是個背景點,而對於乙個內輪廓點,其起始搜尋點為3,因為2已經知道是個背景點。對於輪廓上的任意乙個點,其下乙個點的搜尋起始位置為(d+2) mod 8, 這裡d是當前點的前一點的在當前的八鄰域的位置,如圖5所示。一旦起始搜尋點確定,按照順時針方向搜尋第乙個前景點就是下乙個輪廓的點。但是cvblobslib上的實現方法是採用逆時針搜尋的方式,所以**上和原**中稍有不同。

圖 4圖 5總結

以上僅是我這幾天查閱文獻得到的乙個初步總結,所以難免有疏漏,這裡記下來僅僅是做個筆記,以備後來查閱。對於輪廓的檢測在opencv中也有相應的函式findcontours,這裡列出供參考。

Mysql函式length計算長度問題

在乙個專案中在統計字串長度的時候使用了length函式來判斷當前字串是否過長,結果發現不太好用。在檢視mysql的docment之後,發現是自己用錯了。包含中文字元的應該要使用char length函式來處理。在mysql中的字串長度函式有 length和 length 例如bit length,c...

Vue中 使用 calc 計算長度並傳參

1.定義與用法 calc 函式用於動態計算長度值 運算子前後都需要保留乙個空格,例如 width calc 100 10px 任何長度值都可以使用 calc 函式進行計算 calc 函式支援 運算 calc 函式使用標準的數 算優先順序規則 2.使用 calc 計算長度並傳參 需求 根據服務端返回的...

OpenCV計算連通區域數目與最大連通區域並標示出

cpp view plain copy print?include include include pragma comment lib,cv.lib pragma comment lib,cxcore.lib pragma comment lib,highgui.lib intmain intar...