Python画像処理の膨張と腐食の操作


ことばを引く
膨張と腐食は画像処理における2つの最も基本的な形態学的操作であり、膨張は目標点を背景に融合させ、外部に広がり、腐食は膨張の意味に反し、連結の境界を除去し、境界を内側に収縮させる。本論文では,カーネルを用いた画像膨張と腐食の基本原理を理解する。
始めましょう。必要なライブラリを導入する必要があります。

import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage.draw import circle
from skimage.morphology import erosion, dilation
まず操作しやすい形を作りましょう。簡単な円です。

circ_image = np.zeros((100, 100))
circ_image[circle(50, 50, 25)] = 1
imshow(circ_image);

カーネルを定義しましょう。

cross = np.array([[0,1,0],
   [1,1,1],
   [0,1,0]])
imshow(cross, cmap = 'gray');

作成した円に腐食関数を適用します。

eroded_circle = erosion(circ_image, cross)
imshow(eroded_circle);

画像はほぼ同じに見える。それらの小さな違いを見るには、画像をよく見なければなりません。

linecolor = 'red'
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax[0].imshow(circ_image, cmap = 'gray');
ax[0].set_title('Original', fontsize = 19)
ax[0].axvline(x = 25, color = linecolor)
ax[0].axvline(x = 75, color = linecolor)
ax[0].axhline(y = 25, color = linecolor)
ax[0].axhline(y = 75, color = linecolor)
ax[1].imshow(eroded_circle, cmap = 'gray');
ax[1].set_title('Eroded', fontsize = 19)
ax[1].axvline(x = 25, color = linecolor)
ax[1].axvline(x = 75, color = linecolor)
ax[1].axhline(y = 25, color = linecolor)
ax[1].axhline(y = 75, color = linecolor)
fig.tight_layout()

腐食された円が少し縮んでいるのが見えます。これはオブジェクトを腐食するという意味です。腐食関数を反復すると,その効果は非常に顕著になる。

def multi_erosion(image, kernel, iterations):
 for i in range(iterations):
 image = erosion(image, kernel)
 return image
ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'Iterations : {ites[n]}', fontsize = 16)
 new_circle = multi_erosion(circ_image, cross, ites[n])
 ax.imshow(new_circle, cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

上の図は画像がどのように腐食されているかを明確に示している。今からカーネルを変えてみましょう。交差カーネルの代わりに水平線と垂直線のカーネルを使ったらどうなりますか?

h_line = np.array([[0,0,0],
   [1,1,1],
   [0,0,0]])
v_line = np.array([[0,1,0],
   [0,1,0],
   [0,1,0]])
fig, ax = plt.subplots(1, 2, figsize=(15, 5))
ax[0].imshow(h_line, cmap='gray');
ax[1].imshow(v_line, cmap='gray');
fig.tight_layout()

ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'Horizontal Iterations : {ites[n]}', fontsize = 12)
 new_circle = multi_erosion(circ_image, h_line, ites[n])
 ax.imshow(new_circle, cmap = 'gray');
 ax.axis('off')
fig.tight_layout()
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'Vertical Iterationss : {ites[n]}', fontsize = 12)
 new_circle = multi_erosion(circ_image, v_line, ites[n])
 ax.imshow(new_circle, cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

私たちが見たように、水平と垂直の腐食は画像に異なる方法で影響しています。水平コアを使って,縦方向の細長い円を得た。垂直コアを用いて,水平方向の細長い円を得た。
なぜ垂直なカーネルを使って水平方向の細長い円が得られますか?
腐食関数は、垂直と水平の線をそれぞれ探してゆっくりと削っているからです。膨張関数はこの点をより明確に理解させます。
処理の画像、膨張カーネル、反復回数は以下の関数で設定します。

def multi_dilation(image, kernel, iterations):
 for i in range(iterations):
 image = dilation(image, kernel)
 return image
処理した画像の違いを見せてください。

dilated_circle = multi_dilation(circ_image, cross, 1)
linecolor = 'red'
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
ax[0].imshow(circ_image, cmap = 'gray');
ax[0].set_title('Original', fontsize = 19)
ax[0].axvline(x = 25, color = linecolor)
ax[0].axvline(x = 75, color = linecolor)
ax[0].axhline(y = 25, color = linecolor)
ax[0].axhline(y = 75, color = linecolor)
ax[1].imshow(dilated_circle, cmap = 'gray');
ax[1].set_title('Dilated', fontsize = 19)
ax[1].axvline(x = 25, color = linecolor)
ax[1].axvline(x = 75, color = linecolor)
ax[1].axhline(y = 25, color = linecolor)
ax[1].axhline(y = 75, color = linecolor)
fig.tight_layout()

円がはっきり見えますが、今は赤い糸を越えています。これは明らかに拡大されたことを示しています。水平と垂直拡張を反復します。

ites = [2,4,6,8,10,12,14,16,18,20]
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'Horizontal Iterations : {ites[n]}', fontsize = 
   12)
 new_circle = multi_dilation(circ_image, h_line, ites[n])
 ax.imshow(new_circle, cmap = 'gray');
 ax.axis('off')
fig.tight_layout()
fig, ax = plt.subplots(2, 5, figsize=(17, 5))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'Vertical Iterationss : {ites[n]}', fontsize = 12)
 new_circle = multi_dilation(circ_image, v_line, ites[n])
 ax.imshow(new_circle, cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

水平拡張は画像幅を増加させ,垂直拡張は画像高さを増加させることが,今では非常に明確に見られた。
膨張と腐食の基本原理を理解しました。これからは比較的複雑な画像を見ます。

complex_image = imread('complex_image.png')
imshow(complex_image);

上の画像では、水平線と垂直線と円の混合物を見ました。各形状は膨張と腐食関数を用いて孤立して観察できた。
円を得るためには、垂直な線を先に腐食し、水平な線を腐食することができます。ただし、最後に画像を膨張させることを覚えてください。腐食関数は同じで、円を腐食しています。

step_1 = multi_erosion(complex_image, h_line,3)
step_2 = multi_erosion(step_1, v_line,3)
step_3 = multi_dilation(step_2, h_line,3)
step_4 = multi_dilation(step_3, v_line,3)
steps = [step_1, step_2, step_3, step_4]
names = ['Step 1', 'Step 2', 'Step 3', 'Step 4']
fig, ax = plt.subplots(2, 2, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'{names[n]}', fontsize = 22)
 ax.imshow(steps[n], cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

同様に、下のコードは水平線を得る。

step_1 = multi_erosion(complex_image, cross, 20)
step_2 = multi_dilation(step_1, h_line, 20)
step_3 = multi_dilation(step_2, v_line,2)
steps = [step_1, step_2, step_3]
names = ['Step 1', 'Step 2', 'Step 3']
fig, ax = plt.subplots(1, 3, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'{names[n]}', fontsize = 22)
 ax.imshow(steps[n], cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

垂直な線を得るために新しいカーネルを作成することができます。

long_v_line = np.array([[0,1,0],
   [0,1,0],
   [0,1,0],
   [0,1,0],
   [0,1,0]])
step_1 = multi_erosion(complex_image, long_v_line, 10)
step_2 = multi_dilation(step_1 ,long_v_line, 10)
steps = [step_1, step_2]
names = ['Step 1', 'Step 2']
fig, ax = plt.subplots(1, 2, figsize=(10, 10))
for n, ax in enumerate(ax.flatten()):
 ax.set_title(f'{names[n]}', fontsize = 22)
 ax.imshow(steps[n], cmap = 'gray');
 ax.axis('off')
fig.tight_layout()

注意してください。カーネルはここで述べたこれらに限定されず、必要に応じて適切なカーネルを自分で定義することができます。
締め括りをつける
カーネル腐食と膨張は画像処理の分野で理解すべき基本概念である。これらは画像処理モジュールの第一課でもあり得る。それらを直感的に理解することが、今後この分野で成功する鍵になります。
ここでPythonの画像処理の膨張と腐食に関する操作についての記事を紹介します。Pythonの画像膨張と腐食に関する詳細については、以前の記事を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。