I m p l e m e n t


 

1. Segmentation

分出區塊的方法,主要是由RGB值判斷,方法如下:

1.      對每一像素判斷其右、右下、下、左下四個方向的像素,若兩像素RGB值差異不超過設定的範圍,

        則設定該方向的像素與此像素為同一區塊;否則,設定該方向的像素為另一個新區塊。

2.      再來,判斷其左、左上、上、右上四個方向的像素,若與其中一個方向的像素,二個像素的RGB值差異不超過我們設定的範圍,

        則將此像素所屬區塊與該方向的像素所屬區塊合併為同一區塊。之所以要進行這一個動作,是因為在某些情況下,

        同一區塊可能被分做二個區塊甚至更多,所以才要進行合併的動作,下圖為簡單的範例:

 

原圖

錯誤(未進行合併動作)

正確

 

 

3.        由於單純只由RGB值作判斷的話,很容易分割出過多過小的區塊,因此做完上述動作後,會再進行過小區塊的合併。

          首先,程式必須計算所有區塊的像素數量,再對每一區塊計算與其相鄰的區塊中,差異度最小的區塊。

4.        設定區塊內像素若少於一定值,則認定此區塊過小,必須與其他區塊合併。

          將過小區塊與步驟3中找到的最相似的區塊合併為一個大區塊。此時若發現二個相鄰區塊會合併到對方的區塊,則設定區塊數較小的區塊合併到對方的區塊。

5.           重複步驟3與步驟4,直到所有區塊夠大為止。

 

使用者輸入部分:

接下來由使用者簡單畫幾條線,標示該影像中何者為前景?何者為背景?

其方法如下:

1.  首先使用者必須先選擇按鈕F代表接下來畫的是前景,或者選擇按鈕B代表背景,選擇按鈕C則可以清除使用者標示的部份。

2.  程式讀入使用者選擇的按鈕後,使用者開始在影像上畫線標示前、背景位置。程式讀入所有使用者標示的位置,記錄在一個矩陣中。

3.  當使用者按下按鈕S,表示使用者已選擇完畢。此時,程式根據剛才存的矩陣判斷區塊為前景或背景;

    若一個區塊內同時有二或多個以上的像素被標示為不同的種類,或者沒有任何像素被標示,則不設定此區塊為前景或背景。

 

 

2. Cutout

在判斷未標示部份是前景或背景之前,我們必須對每個區塊作衡量,我們希望所有前景區塊為一群,

所有背景區塊合為一群,所以我們加上了 鍊結 的概念。鍊結的能量越大,表示兩區塊同為前景 or 背景的可能性越大,

當所有的標示完成,我們用 Maxflow 切斷鍊結最弱的部分,和標示為前景相連的部分即視為前景,反之亦然。

模型如下圖所示:

 

 

圖解:

S 為前景起點

T 為背景起點

水平面上每點代表一個區塊,

切斷點為水平面上較細(能量較小)的鍊結。

 

 

由於目標是把區塊分成前景 (1 ) 或背景 (0) ,故可視為一個 “ binary labeling “ problem

參考 paper 採用的 Gibbs energy E(X) [Geman and Geman. 1984 ]:

其中 V 為圖片上的每個區塊, ε 為兩區塊間的鍊結。

 

n           其中E1 likelihood energy ,可視為 跟標示前/背景的相似度

在上頁的模型中,E1 即為水平面連結到上下兩端點的鍊結能量。因為我們希望越相近的區塊鍊結越大,

所以當某區塊被使用者標示為前景,我們就設該區塊到前景(S)的能量為 Max,到背景(T)的能量為0

反之,當某區塊標示為背景,則和前景(S)的能量為 0 ,和背景(T)的能量為 Max。而未標示的區塊,則必須判斷是前景 or 背景的可能性。

Step 1: K-mean

我們先把標示起來的前背景區塊各當成一個 RGB 樣本,在 RGB 三度空間裡,任意取 k 個標示點{x, y, z}

將每個樣本分類到最接近的標示點。取每個標示點的平均 RGB 值。若標示點{x, y, z}和平均值{R, G , B}不同,

把標示點移至平均點上,重新取平均值,一直重複上述步驟,直到所有標示點不再劇烈更動為止。

Step 2: 求最小距離

當我們遇到一個未標示的區塊,就用區塊的平均 RGB 值,到前背景樣本裡去找最接近的標示點,

計算平均值和最接近標示點的距離。在前景樣本的距離,命之為 df,到背景樣本裡求得的距離命之為  dBn

Step 3: 定義能量

可想而知,若區塊的平均 RGB 值較接近前景,則 dfn 較小,但我們希望越接近前景能量越大,

於是我們將對前景的能量設為   對背景的能量則設為

n           E2 piror ,可視為 與相鄰區塊的相異度定義如  : 

我們取兩相鄰區塊邊界上的 RGB 差異當作 Cij ,差異越大,Cij 值越大。但我們希望兩區塊差異較小時鍊結能量較大,所以我們設兩區塊的能量為

 

3. Maxflow

 

While ( there exists a path p from S to T )

        Do ( flow (p) <- min{ flow (u, v) | (u, v) is in p} )

                For( each edge ( u, v) in p ) {

                        Do F[u, v] <- F[u, v]  -  flow(p)

F[v, u] <- F[v, u]  +  flow(p)

}

 

當所有鍊結能量都標示完成,我們用 Maxflow尋找能量較少的鍊結。

我們可將所有鍊結想像成一片由 S 出發,T結束的水管網,而能量就是水管的截面積大小(亦可視為單位時間可通過的流量)。

 

一開始,由S先任找一條通路到終點,通路 p 的流量應該會被通路上的最小截面積min{ flow (u, v) | (u, v) is in p} 所限制,

我們稱通路 p 的流量為 flow (p) 此時將所有通路上的 S -> T 方向流量減去 flow (p)  ,此時通路上必有一條鍊結能量被減為 0 ,該處便是鍊結最弱處。

但因為我們的目的是求出 ST各自有哪些 node ,所以我們必須把水管看成是雙向流通的。

當我們減掉 S->T 方向的流量,表示 T->S 方向也可以有相同大小的流量,所以除了 F[u, v] - flow (p) ,還要把 F[v , u] 加上flow (p)

重複此動作,我們就可以做到將所有區塊分為 S T 兩群,最後將和 S 相連的輸出為前景,和 T 相連的輸出為背景即可完成。