領域分割処理

領域分割処理#

グラフカット法#

画像処理における グラフカット法(Graph Cuts) は主に画像のセグメンテーションに使われる最適化手法の1つで、画像を前景と背景などに分割するために用いられる。

領域項(データ項)と境界項(平滑化項)と呼ばれる2つの項からなるコスト関数\(E(L)\)

\[ E(L)= R(L) + \lambda \cdot B(L) \]

を最小化する

\[\begin{split} \begin{aligned} R(L)&=\sum_{p\in P} R_p(L_p) \\ B(L)&=\sum_{\{p, q\} \in N} B_{\{p, q\}} \cdot \delta(L_p, L_q) \\ \delta(L_p, L_q) &= \begin{cases}1 & (L_p \neq L_q) \\ 0 & (\text { それ以外 })\end{cases} \end{aligned} \end{split}\]
  • \(P\):画素の全集合、\(p\)は1画素

  • \(N\):隣接する画素同士の組の全集合、\(\{p, q\}\)はその要素

  • \(\lambda\):領域項と境界項の相対的な重み。\(\lambda \geq 0\)

  • \(L\):ラベル(前景・背景)

グラフカット(Graph Cut) - 大人になってからの再学習

GrabCut#

Graph Cut を改良した半自動の画像セグメンテーション手法。

GrabCutは2004年にMicrosoft Researchによって提案された(Rother et al., 2004)。

特徴:

  • 最初に矩形で前景をざっくり指定するだけで良い。

  • 背景/前景の色分布を GMM(Gaussian Mixture Model) でモデル化。

  • Graph Cut を使って、GMMに基づくエネルギー関数を反復的に最小化する。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("sample_images/cat2.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

plt.imshow(img)
plt.title("Original Image")
plt.show()
../_images/50e845232ba5b6b7c13621c45d48de20244287ab1ede55b9583fb05ef3b945b7.png
mask = np.zeros(img.shape[:2], np.uint8)

# 背景・前景モデル(内部的に使われる)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)

# 矩形で前景をざっくり指定
rect = (50, 50, 300, 400)

# GrabCutの実行
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)

# マスクの整形
mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8')
result = img * mask2[:, :, np.newaxis]

plt.imshow(result)
plt.title("Cutted Image")
plt.show()
../_images/95e37aea03190faef84a2975c9724d89aa69c870d0454458ca8ff510cc1cc80e.png