Numpyでモルフォロジー演算を実装してみます。
まず、使用する画像を読み込んでグレースケール画像に変換します。
import numpy as np
import matplotlib.pyplot as plt
original_image = plt.imread(image_name)
if np.issubdtype(original_image.dtype, np.floating):
original_image = (original_image * 255).astype(np.uint8)
gray_image = (0.2116 * original_image[:,:,0] + 0.7152 * original_image[:,:,1] + 0.0722 * original_image[:,:,2]).astype(np.uint8)
plt.imshow(gray_image, cmap='gray')
二値画像も作成します。二値画像作成の詳細については以下の記事を参照してください。
【画像処理】Numpyで大津の二値化(判別分析法) - Qiita
def thresholding(image, threshold):
return np.where(image <= threshold, 0, 255)
binary_image = thresholding(gray_image, 128)
plt.imshow(binary_image, cmap='gray')
収縮 (Erosion)
前景(白)を一回り小さくするモルフォロジー演算を収縮(Erosion)と呼びます。注目画素とその近傍画素の最小値を注目画素の値にします。
def erode(image, boundary='edge'):
pad_image = np.pad(image, 1, boundary)
areas = np.lib.stride_tricks.as_strided(pad_image, image.shape + (3, 3), pad_image.strides * 2)
return np.min(areas, axis=(2, 3))
収縮を二値画像に適用します。
erode_binary_image = erode(binary_image)
plt.imshow(erode_binary_image, cmap='gray')
収縮をグレースケール画像に適用します。
erode_gray_image = erode(gray_image)
plt.imshow(erode_gray_image, cmap='gray')
膨張 (Dilation)
前景(白)を一回り大きくする処理を膨張(Dilation)と呼びます。注目画素とその近傍画素の最大値を注目画素の値にします。
def dilate(image, boundary='edge'):
pad_image = np.pad(image, 1, boundary)
areas = np.lib.stride_tricks.as_strided(pad_image, image.shape + (3, 3), pad_image.strides * 2)
return np.max(areas, axis=(2, 3))
膨張を二値画像に適用します。
dilate_binary_image = dilate(binary_image)
plt.imshow(dilate_binary_image, cmap='gray')
膨張をグレースケール画像に適用します。
dilate_gray_image = dilate(gray_image)
plt.imshow(dilate_gray_image, cmap='gray')
オープニング (Opening)
複数回の収縮のあとに、同じ回数膨張する処理をオープニング(Opening)と呼びます。
def opening(image, n=2, boundary='edge'):
for i in range(n):
image = erode(image, boundary)
for i in range(n):
image = dilate(image, boundary)
return image
オープニングを二値画像に適用します。
opening_binary_image = opening(binary_image)
plt.imshow(opening_binary_image, cmap='gray')
オープニングをグレースケール画像に適用します。
opening_gray_image = opening(gray_image)
plt.imshow(opening_gray_image, cmap='gray')
クロージング (Closing)
複数回の膨張のあとに、同じ回数収縮する処理をクロージング(Closing)と呼びます。
def closing(image, n=2, boundary='edge'):
for i in range(n):
image = dilate(image, boundary)
for i in range(n):
image = erode(image, boundary)
return image
クロージングを二値画像に適用します。
closing_binary_image = closing(binary_image)
plt.imshow(closing_binary_image, cmap='gray')
クロージングをグレースケール画像に適用します。
closing_gray_image = closing(gray_image)
plt.imshow(closing_gray_image, cmap='gray')
トップハット (Top-Hat)
元の画像からオープニングを施した画像を引く処理をトップハット(Top-Hat)と呼びます。
トップハット画像にはオープニングにより削除された値が残ります。
def tophat(image, n=2, boundary='edge'):
opening_image = opening(image, n, boundary)
return image - opening_image
トップハットを二値画像に適用します。
tophat_binary_image = tophat(binary_image)
plt.imshow(tophat_binary_image, cmap='gray')
トップハットをグレースケール画像に適用します。
tophat_gray_image = tophat(gray_image)
plt.imshow(tophat_gray_image, cmap='gray')
ブラックハット (Black-Hat)
クロージングを施した画像から元画像を引く処理をブラックハット(Black-Hat)と呼びます。
ブラックハット画像にはクロージングより追加された値が残ります。
def blackhat(image, n=2, boundary='edge'):
closing_image = opening(image, n, boundary)
return closing_image - image
ブラックハットを二値画像に適用します。
blackhat_binary_image = blackhat(binary_image)
plt.imshow(blackhat_binary_image, cmap='gray')
ブラックハットをグレースケール画像に適用します。
blackhat_gray_image = blackhat(gray_image)
plt.imshow(blackhat_gray_image, cmap='gray')
実装したコードはGoogle Colabratoryに置いてあります。