graph cut5.1 5.2_takmin
TRANSCRIPT
第2回「コンピュータビジョン最先端ガイド」勉強会
5.1-5.2章
presented by takmin
5. グラフカットによる大域最小化
• この章の目的
–データ項+平滑化項で表される以下のエネルギーを最小切断アルゴリズムを使って,最小化する
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
この章の流れ
• 2値の場合– 5.1 2値の大域最小化– 5.2 実装例
• 大域最小解を持つための辺の重みの決め方– 5.3 劣モジュラ条件– 5.4 劣モジュラでないとき:QPBO
• 多値の場合– 5.5 多値の大域最小化– 5.6 実装例– 5.7 一般の凸な平滑化項
5.1 2値の大域最小化
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
このエネルギーの大域最小化を行う
問題をグラフで表し,最小切断問題として解く
グラフの構築
頂点を設定: VvwV v |1
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
vw
グラフの構築
頂点s,tを追加: tsVV ,1
t
S
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
グラフの構築
辺を追加: Vvtwws vv |),(),,(1
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
t
S
グラフの構築
辺を追加: Evuww vu ),(|),(2
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
t
S
完成!
グラフの切断
このグラフの任意の切断(S,T)について:
)(1
)(0
のとき
のとき
Tw
SwX
v
v
v
0 1 0 0 1 1
t
S
uwvw
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
グラフの切断
各辺の切断コストを定義:
)1(),( vv gwsc
)0(),( vv gtwc
)0,1()1,0(),( vuuvvu hhwwc
t
S
uwvw
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
グラフの切断
切断されたsからtへ向かう辺の切断コストの和とEは等しい
0 1 0 0 1 1
t
S
Evu
vuuv
Vv
vv XXhXgXE),(
),()()(
ノイズ除去の例
Evu
vu
Vv
vv XXXYXE),( 2
)(
(2)
vX
vY
012
102
)00000()(XE
エネルギーを計算する
ノイズ除去の例
Evu
vu
Vv
vv XXXYXE),( 2
)(
(2)
1),( vv Ywsc t
S
vY
00 0λ λ
λ
0),( vv Ytwc
),( vu wwc
λ λ λ0 00
グラフカットで切断コストを計算する
κ
κκ
κ
κ
κ
κ
κ
κ
κ
ノイズ除去の例
Evu
vu
Vv
vv XXXYXE),( 2
)(
(2)
t
S
00000)(XE
vY
00 0λ λ
λ
λ λ λ0 00
κ
κκ
κ
κ
κ
κ
κ
κ
κ
2次元の場合
2次元の場合
3次元の場合
5.2 実装例
• GCライブラリ入手先
– Vladimir Kolmogorovさんのページ
– http://www.cs.ucl.ac.uk/staff/V.Kolmogorov/
– Max Flowライブラリをダウンロード
ライブラリ入手先
http://www.cs.ucl.ac.uk/staff/V.Kolmogorov/
Vladimir Kolmogorovさんのページ
ソースvoid NR2(unsigned char* X, unsigned char* Y, int m, int n){
typedef Graph<int,int,int> GraphType;int lambda=100;int kappa = 25;GraphType* g = new GraphType(n*m, 4*n*m); // 頂点と辺の概数g->add_node(n*m); // 画素の数だけ頂点を作る
int dx[4] = {1,-1,0,1};int dy[4] = {0, 1, 1, 1};for(int j=0; j<m; j++){
for(int i=0; i<n; i++){int g0 = *(Y + n*j + i) * lambda; //g(0)int g1 = (1-*(Y + n*j + i)) * lambda; // g(1)g->add_tweights(j*n+i,g1,g0); // (i,j)の頂点はnj+i番目for(int d=0; d<4; d++){
int x = i + dx[d];int y = j + dy[d];if(0<=x && 0<=y && x<n && y<m){
g->add_edge(j*n+i,y*n+x,kappa,kappa); // 両方向}
}}
}g->maxflow();for(int j=0; j<m; j++){
for(int i=0; i<n; i++){if(g->what_segment(j*n+i)==GraphType::SOURCE)
*(X + n*j + i)=0;else
*(X + n*j + i)=1;}
}delete g;
}
手順
1. GraphTypeインスタンス生成
– GraphType* g = new GraphType(n*m, n*m*4);
2. 画素の数だけ頂点を作る
– g->add_node(n*m);
3. データ項(=C(s, wv),C(wv,t))を設定
– g->add_tweights(j*n+i, g1, g0)
頂点の概数
辺の概数
wu c(wv, t)c(s, wv)
手順
4. 頂点間の辺を作成(双方向)– g->add_edge (j*n+i, y*n+x, kappa, kappa);
5. 最小切断(最大流)を求める– g->maxflow();
6. 各頂点でs,tのどちらが切断されたかを結果に格納– g->what_segment(j*n+i)
wu wv c(wv, wu)c(wu, wv)
結果
最後に
• 図は,石川先生の講演資料から拝借しました。
– http://w01.tp1.jp/~a031464501/indexJ.html