注記
完全なサンプルコードをダウンロードするには、こちらへ またはBinder経由でブラウザでこの例を実行します。
形態学的フィルタリング#
形態学的画像処理とは、境界線、スケルトンなど、画像内の特徴の形状または形態に関連する非線形操作の集合です。任意の技術において、私たちは構造要素と呼ばれる小さな形状またはテンプレートを使用して画像を調べます。これは、ピクセル周囲の関心領域または近傍を定義します。
このドキュメントでは、以下の基本的な形態学的演算の概要を示します。
侵食
膨張
開口
閉包
ホワイトトップハット
ブラックトップハット
スケルトン化
凸包
io.imread
を使用して画像を読み込みます。形態学関数はグレースケール画像またはバイナリ画像でのみ機能するため、as_gray=True
を設定します。
import matplotlib.pyplot as plt
from skimage import data
from skimage.util import img_as_ubyte
orig_phantom = img_as_ubyte(data.shepp_logan_phantom())
fig, ax = plt.subplots()
ax.imshow(orig_phantom, cmap=plt.cm.gray)

<matplotlib.image.AxesImage object at 0x7f036a3059a0>
比較をプロットするための便利な関数を定義しましょう。
def plot_comparison(original, filtered, filter_name):
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4), sharex=True, sharey=True)
ax1.imshow(original, cmap=plt.cm.gray)
ax1.set_title('original')
ax1.set_axis_off()
ax2.imshow(filtered, cmap=plt.cm.gray)
ax2.set_title(filter_name)
ax2.set_axis_off()
侵食#
形態学的erosion
は、(i, j)のピクセルを、(i, j)を中心とする近傍内のすべてのピクセル上の最小値に設定します。erosion
に渡される構造要素footprint
は、この近傍を記述するブール配列です。以下では、ほとんどの例で使用される円形の構造要素を作成するためにdisk
を使用します。
from skimage.morphology import erosion, dilation, opening, closing, white_tophat
from skimage.morphology import black_tophat, skeletonize, convex_hull_image
from skimage.morphology import disk
footprint = disk(6)
eroded = erosion(orig_phantom, footprint)
plot_comparison(orig_phantom, eroded, 'erosion')

ディスクのサイズを大きくすると、画像の白い境界線が消えたり、侵食されたりする様子に注目してください。また、中央の2つの黒い楕円のサイズが増加し、画像の下部にある3つの薄い灰色のパッチが消える様子にも注目してください。
膨張#
形態学的dilation
は、(i, j)のピクセルを、(i, j)を中心とする近傍内のすべてのピクセル上の最大値に設定します。膨張は明るい領域を拡大し、暗い領域を縮小します。
dilated = dilation(orig_phantom, footprint)
plot_comparison(orig_phantom, dilated, 'dilation')

ディスクのサイズを大きくすると、画像の白い境界線が太くなったり、膨張されたりする様子に注目してください。また、中央の2つの黒い楕円のサイズが小さくなり、中央の薄い灰色の円と画像下部にある3つのパッチが太くなる様子にも注目してください。
開口#
画像に対する形態学的opening
は、侵食に続いて膨張を行うこととして定義されます。開口は小さな明るい斑点(すなわち「塩」)を除去し、小さな暗い亀裂を接続することができます。
opened = opening(orig_phantom, footprint)
plot_comparison(orig_phantom, opened, 'opening')

opening
は侵食演算から始まるため、構造要素よりも小さい明るい領域は除去されます。それに続く膨張演算により、構造要素よりも大きい明るい領域は元のサイズを維持します。中央の明暗の形状は元の太さを維持していますが、下部の3つの薄いパッチは完全に侵食される様子に注目してください。サイズ依存性は、外側の白いリングによって強調されています。リングのうち構造要素よりも薄い部分は完全に消去され、上部のより厚い領域は元の太さを維持します。
閉包#
画像に対する形態学的closing
は、膨張に続いて侵食を行うこととして定義されます。閉包は小さな暗い斑点(すなわち「胡椒」)を除去し、小さな明るい亀裂を接続することができます。
これをより明確に説明するために、白い境界に小さな亀裂を追加しましょう。

closing
は膨張演算から始まるため、構造要素よりも小さい暗い領域は除去されます。それに続く侵食演算により、構造要素よりも大きい暗い領域は元のサイズを維持します。下部の白い楕円が膨張のために接続される様子、他の暗い領域が元のサイズを維持する様子に注目してください。また、追加した亀裂がほとんど除去される様子にも注目してください。
ホワイトトップハット#
画像のwhite_tophat
は、画像からその形態学的開口を引いたものとして定義されます。この演算は、構造要素よりも小さい画像の明るい斑点を返します。
面白くするために、画像に明るい斑点と暗い斑点を加えましょう。
phantom = orig_phantom.copy()
phantom[340:350, 200:210] = 255
phantom[100:110, 200:210] = 0
w_tophat = white_tophat(phantom, footprint)
plot_comparison(phantom, w_tophat, 'white tophat')

ご覧のとおり、10ピクセルの幅の白い正方形は、構造要素よりも小さいため強調表示されます。また、楕円の周りのほとんどの薄い白いエッジは、構造要素よりも小さいため維持されますが、上部のより厚い領域は消えます。
ブラックトップハット#
画像のblack_tophat
は、その形態学的閉包から元の画像を引いたものとして定義されます。この演算は、構造要素よりも小さい画像の暗い斑点を返します。

ご覧のとおり、10ピクセルの幅の黒い正方形は、構造要素よりも小さいため強調表示されます。
双対性
お気づきかもしれませんが、これらの操作の多くは、単に別の操作の逆です。この双対性は、次のように要約できます。
侵食 <-> 膨張
開口 <-> 閉包
ホワイトトップハット <-> ブラックトップハット
スケルトン化#
間引き処理は、二値画像内の各連結成分を1ピクセルの幅のスケルトンに削減するために使用されます。これは二値画像に対してのみ実行されることに注意することが重要です。
horse = data.horse()
sk = skeletonize(horse == 0)
plot_comparison(horse, sk, 'skeletonize')

名前が示すように、この手法は間引きを連続して適用することにより、画像を1ピクセルの幅のスケルトンに細くするために使用されます。
凸包#
convex_hull_image
は、入力画像内のすべての白色ピクセルを囲む最小の凸多角形に含まれるピクセルの集合です。これも二値画像に対してのみ実行されることに注意してください。
hull1 = convex_hull_image(horse == 0)
plot_comparison(horse, hull1, 'convex hull')

図に示すように、convex_hull_image
は、画像内の白色またはTrueを完全に覆う最小の多角形を与えます。
画像に小さな粒を追加すると、凸包がその粒を囲むようにどのように適応するかを確認できます。
horse_mask = horse == 0
horse_mask[45:50, 75:80] = 1
hull2 = convex_hull_image(horse_mask)
plot_comparison(horse_mask, hull2, 'convex hull')

追加のリソース#
1. MathWorksの形態学的処理に関するチュートリアル
2. オークランド大学の形態学的画像処理に関するチュートリアル
plt.show()
スクリプトの総実行時間:(0分2.234秒)