suzuki 輪廓跟蹤算法原理


本文參考了以下文章:

·https://blog.csdn.net/yiqiudream/article/details/75702407 (代碼解釋)

·https://blog.csdn.net/yiqiudream/article/details/76864722 (論文翻譯)

·https://wenku.baidu.com/view/6cb52ede360cba1aa811dad5.html(英文論文解釋)

·https://blog.csdn.net/u013631121/article/details/80504032?utm_source=blogxgwz4(另一篇說明,還不錯)

Suzuki輪廓跟蹤算法

輪廓跟蹤算法,顧名思義,就是通過順序找出邊緣點來跟蹤邊界的本文介紹經典的suzuki 輪廓跟蹤算法,此算法也在opencv中有代碼實現。

tesseract中,輪廓跟蹤算法是建立在種子填充算法得到的二值圖之上的,其目的為找到每個連通域的輪廓點,用Freeman鏈碼表示;

下面主要介紹原理:

算法的正式描述

 

在此算法中,當我們說“the neighborhood”,我們指的是4-(8-)鄰域,在4-(8-)連接的情況下。假設輸入圖像 F={fij}.設置最初的NBD=1(F的邊框形成了一個特殊的孔邊界,分配序列數1;NBD代表當前邊界的序列數)。使用光柵掃描器掃描圖像,對每一個滿足fij≠0的像素點執行以下步驟。每當我們開始掃描新的一行,重置LNBD=1.

 

(1) 確定點邊界類型(outer/hole),選擇下面的一條:

a)如果 fi,j= 1 且 fi,j-1= 0 則確定像素(i,j)是一個外邊界的跟蹤起始點,NBD自增,並且 (i2, j2)<-(i, j-1)。

b)否則如果fi,j ≥ 1 且 fi,j+1 = 0,則確定像素(i,j)是一個孔邊界的跟蹤起始點,NBD自增,(i2, j2)<-(i, j+1) ,當fij>1的情況下,LNBD<-fij。

c)否則,go to (4).

 

(2) 根據最新找到的邊界(newly found border)的類型以及帶有序列號LNBD的邊界(也就是,the last border met on the current row此處是重點,翻譯過來就是:在當前行遇到的上一個NBD值,決定了父子輪廓樹關系)的類型,決定當前邊界的母邊界,判斷規則如表1.

  

(3) 從起始點 (i,j) 開始,跟蹤已檢測到的邊界:這一步由以下步驟3.1到步驟3.5實現。下面配合實例進行說明:

輸入的測試圖片(外邊界)。為了便於說明,我給邊界的每個點標了一個序號,從1到40. 最上面一行最左邊一列的那個像素標為1(i,j)=(1,1).

 

(3.1) 從點(i2, j2)開始,順時針旋轉查找點(i,j)的鄰域,尋找一個非零點,第一個找到的非零點記做(i1, j1)。如果沒有找到非零點,另fij = -NBD,轉到(4)。

     

(3.2) (i2,j2)<- (i1,j1) 且 (i3, j3)<- (i, j)。

 

(3.3) 尋找范圍在當前點(i3, j3)的鄰域中,方向為逆時針方向,出發點為(i2, j2)的下一個元素,查找一個非零點並將第一個找到的非零點設為(i4, j4)。(譯者注:比如點(i3, j3)的0方向的點是(i2, j2),則按逆時針方向轉一格就到了點(i3, j3)的1方向的點,從這個1方向點開始查找非零點,找到了就設置為(i4, j4))。

(3.4) 根據下面的規則修改點(i3, j3)的NBDfi3,j3:

(a) 如果步驟(3.3)中檢查到點(i3, j3+1)是一個0-pixel,則fi3, j3 <- NBD.

即達到了最右側,也就是碰到兩個像素點為10的情況,-NBD設置為負數,防止outer的邊界作為hole的起始點,具體討論參看論文)

(b) 如果步驟(3.3)中檢查到點(i3, j3+1)不是一個0-pixel,且fi3, j3 = 1,則fi3, j3<- NBD.

(c) 否則,不要改變fi3, j3。

 

(3.5) 如果(i4, j4)= (i,j) 且 (i3,j3) = (i1, j1) (輪廓跟蹤了一圈,回到了開始點),轉到步驟(4);否則,(i2, j2)<- (i3, j3),(i3,j3)<-(i4,j4),且回到步驟(3.3)。

(4) 如果fi,j ≠ 1,則 LNBD <- | fi,j| 且 從點(i, j+1)重新開始掃描。當掃描器到達圖片的右下角的點則算法終止。

 

(譯者注:在這個算法中,(i3,j3)代表當前點,(i2,j2)代表當前點的上一個找到的點,(i4, j4)表示在當前點的鄰域中最新找到的非零點。  當前點是不斷變化的,這些點的名稱是相對的。具體參考開頭給出的博文。) 

******************************************************************************

附補充說明:

1.  關於以上步驟(3)的補充討論。

1輸入的測試圖片。為了便於說明,我給邊界的每個點標了一個序號,從1到40. 最上面一行最左邊一列的那個像素標為1.   

邊界掃描算法從左上角開始逐行掃描,當發現以下兩種情況時,認為找到邊界的起始點。(a)情況表示遇到了外邊界;(b)情況表示遇到孔。所以對於測試圖片,起始點就是第一行遇到的第一個非零像素點。

2)其中定義了幾個指針,指向某個像素點。其中

i0: 指向 contour 的起始點。在輪廓跟蹤過程中,該指針始終不變。對應上圖中,自定義編號中的“1”。是輪廓的第一個像素點。在判斷跟蹤是否結束的時候用到它;

 

i1: 指向 contour 的最后一個點。在輪廓跟蹤過程中,該指針始終不變。對應上圖中,自定義編號中的“40”。在判斷跟蹤是否結束的時候用到它。值得注意的是,輪廓算法中首先找到起始點,緊接着就尋找這個點。找到這個點之后才開始尋找輪廓的第二個像素點;那i1按什么方向搜索呢?算法規定,如果該 contour 是一個 hole, 則從0方向開始;如果是外邊界,則從4方向開始。如下圖。用 do 循環在i0的鄰居內尋找 i1

 

i3: 指向當前中心點。中心點的意思是,當發現某個像素點屬於輪廓,則將該點看做中心點,在它的8鄰域內尋找下一個輪廓點。在輪廓跟蹤過程中,這個指針會隨着中心點的改變而改變;

i4: 指向最新找到的非零點。以i3所指向的點為中心,在8鄰域內尋找非零點,如果找到了,就用i4指向它。在輪廓跟蹤過程中,這個指針會隨時改變;

用三張圖來表示,(a)圖的狀態:已經找到i0(第一個輪廓點) 和 i1(最后一個輪廓點), 並且找到了第2個輪廓點i3,此時i3作為中心點,在8鄰域內找到了非零點,就是i4.  b)圖的狀態:經過某種判斷標准,發現i4是新的輪廓點(即第3個輪廓點),讓i3指向它(更新i3),該點作為當前中心點,在8鄰域內尋找非零點,找到了,讓i4指向它(更新i4)。 (c)圖的狀態:經過某種判斷標准,發現i4是新的輪廓點(即第4個輪廓點),讓i3指向它(更新i3),該點作為當前中心點,在8鄰域內尋找非零點,如果找到則 讓i4指向它(更新i4.

(a)  b) (c) 指針 i3i4 更新示意圖。 

注釋: Freeman鏈碼保存的信息並不是點的坐標,而是初始點以及方向值,從第i個邊界點到第 i+1 個邊界點的移動方向。8個方向的定義在前面的表格中給出了。本例中邊界共有40個像素點,那么就有39個方向值。

 

2.  挖掘出輪廓之間的層次關系。

由於邊界的層次關系復雜,Suzuki的方法是,找到一個邊界,就用一個唯一的數字nbd去標記,最后標記值相同的像素點屬於同一個邊界,不同邊界之間的層次關系通過其標記值保存下來。

Nbd(number of border)就是這個標記值。為什么nbd是從2開始而不是1呢?因為Suzuki 的方法中,一幅二值圖的最上一行,最下一行,最左一行和最右一行都被設置為0,因此,這幅圖像的最外層就是一個 hole, 這個hole稱之為 背景(background),而這最邊上的兩行兩列組成的輪廓就是 一個孔邊界,稱之為frame.  這個 frame 就用1 來標注。其次其他邊界從2開始標注。

 

一個輪廓的nbd標記值可以表示如下:

 

例子:

手推邊界

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM