はじめに
画像処理は、デジタル画像を操作してその内容を解析、変換、編集する技術です。この技術は、写真編集、医療画像解析、自動運転車の視覚システムなど、さまざまな分野で利用されています。このシリーズは、実際の画像処理技術をPythonで実装することで、理論と実践を組み合わせた学習を目指しています。画像処理において、ノイズ除去は非常に重要なステップです。ノイズの多い画像では、後続の処理や解析の精度が低下してしまいます。今回は、画像処理の重要な技術であるエッジ検出について学びます。エッジ検出は画像内の重要な情報を抽出するために使用され、多くの画像解析タスクの前処理として不可欠です。この記事では、MAX-MINフィルタと微分フィルタを実装し、画像のエッジを検出する方法を解説します。初心者の方でも理解できるよう、各ステップを丁寧に説明しますので、ぜひ参考にしてください。この記事では、画像処理100本ノックで用意されている「imori_noise.jpg」をダウンロードしてください。ダウンロードのURLはこちらです。
画像処理100本ノック 012. MAX-MINフィルタ
平滑化フィルタ(3×3)を実装せよ。
画像処理100本ノック
平滑化フィルタはフィルタ内の画素の平均値を出力するフィルタである。
方針
MAX-MINフィルタは、フィルタ内の画素の最大値と最小値の差を計算するフィルタです。このフィルタはエッジ検出に使用され、画像内の急激な変化(エッジ)を強調します。エッジ検出は画像内の輪郭や線を抽出する操作で、画像の特徴を抽出する際に非常に重要です。通常、エッジ検出はグレースケール画像に対して行います。MAX-MINフィルタを適用するためには、以下の手順を踏みます:
平滑化フィルタを適用するためには、以下の手順を踏みます:
- 画像を読み込む。
- 画像にゼロパディングを施し、画像の境界部分の処理を行う。
- 各ピクセルに対して3×3の領域内の最大値と最小値の差を計算し、その差を新しい値として設定する。
実装手順
- 画像の読み込み:
- 画像を読み込みます。
- ゼロパディング:
- 画像にゼロパディングを施し、カーネルの適用範囲を確保します。
- MAX-MINフィルタを適用する:
- 各ピクセルに対して3×3の領域内の最大値と最小値の差を計算し、その差を新しい値として設定します。
解答と実行結果
まず、必要なライブラリをインポートし、cv2.imread(‘imori_noise.jpg’)を使用してノイズのあるカラー画像を読み込みます。このとき、img変数に画像データが格納されます。
次に、画像の境界部分を処理するためにゼロパディングを施します。np.pad(img, ((pad_size, pad_size), (pad_size, pad_size), (0, 0)), mode=’constant’)を使用して、画像の周囲に1ピクセルのゼロパディングを追加します。その後、MAX-MINフィルタを適用するための関数apply_max_min_filterを定義します。この関数は、各ピクセルに対して3×3の領域内の最大値と最小値の差を計算し、その差を新しいピクセル値として設定します。カラー画像なので、各カラーチャンネル(RGB)に対してフィルタを適用します。
最後に、apply_max_min_filter(padded_img)を使用してフィルタを適用し、plt.imshow(cv2.cvtColor(output_max_min, cv2.COLOR_BGR2RGB))を使用してフィルタを適用した画像を表示します。
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 画像の読み込み(カラー)
img = cv2.imread('imori_noise.jpg')
# ゼロパディング
pad_size = 1
padded_img = np.pad(img, ((pad_size, pad_size), (pad_size, pad_size), (0, 0)), mode='constant')
# MAX-MINフィルタの適用
def apply_max_min_filter(img):
output = np.zeros_like(img)
for i in range(img.shape[0] - 2):
for j in range(img.shape[1] - 2):
for c in range(img.shape[2]):
region = img[i:i+3, j:j+3, c]
output[i, j, c] = np.max(region) - np.min(region)
return output
output_max_min = apply_max_min_filter(padded_img)
# 結果の表示
plt.imshow(cv2.cvtColor(output_max_min, cv2.COLOR_BGR2RGB))
plt.title('MAX-MIN Filter Output')
plt.show()
このコードを実行すると、次のような結果(右の画像)が得られます。
画像処理100本ノック 013. 微分フィルタ
微分フィルタ(3×3)を実装せよ。
画像処理100本ノック
微分フィルタは輝度の急激な変化が起こっている部分のエッジを取り出すフィルタであり、隣り合う画素同士の差を取る。
(a)縦方向 (b)横方向
0 -1 0 0 0 0
K = [ 0 1 0 ] K = [ -1 1 0 ]
0 0 0 0 0 0
方針
微分フィルタは、隣り合う画素同士の差を計算するフィルタで、画像の輝度の急激な変化を検出するために使用されます。このフィルタもエッジ検出に使用され、画像の輪郭を強調します。一般的な微分フィルタには、横方向と縦方向の変化を検出するためのカーネルが存在します。
横方向の微分フィルタのカーネルは次のようになります:
縦方向の微分フィルタのカーネルは次のようになります:
微分フィルタを適用するためには、以下の手順を踏みます:
- 画像を読み込む。
- 画像にゼロパディングを施し、画像の境界部分の処理を行う。
- 各ピクセルに対して横方向および縦方向の微分フィルタを適用し、エッジを強調する。
実装手順
- 画像の読み込み:
- 画像を読み込みます。
- ゼロパディング:
- 画像にゼロパディングを施し、カーネルの適用範囲を確保します。
- 微分フィルタを適用する:
- 各ピクセルに対して横方向および縦方向の微分フィルタを適用し、エッジを強調します。
解答と実行結果
まず、必要なライブラリをインポートし、ノイズのあるカラー画像を読み込みます。次に、画像の境界部分を処理するためにゼロパディングを施します。ここでは、画像の周囲に1ピクセルのゼロパディングを追加します。
次に、微分フィルタのカーネルを定義します。横方向のカーネルkernel_xと縦方向のカーネルkernel_yをそれぞれ定義します。微分フィルタを適用するための関数apply_derivative_filterを定義します。この関数は、各ピクセルに対してカーネルを適用し、エッジを強調します。具体的には、3×3の領域内の隣り合う画素同士の差を計算し、その差を新しいピクセル値として設定します。
最後に、apply_derivative_filter(padded_img, kernel_x)とapply_derivative_filter(padded_img, kernel_y)を使用して微分フィルタを適用し、フィルタを適用した画像を表示します。
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 画像の読み込み(カラー)
img = cv2.imread('imori_noise.jpg')
# ゼロパディング
pad_size = 1
padded_img = np.pad(img, ((pad_size, pad_size), (pad_size, pad_size), (0, 0)), mode='constant')
# 微分フィルタのカーネル
kernel_x = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
kernel_y = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]])
# 微分フィルタの適用
def apply_derivative_filter(img, kernel):
output = np.zeros_like(img)
for i in range(img.shape[0] - 2):
for j in range(img.shape[1] - 2):
for c in range(img.shape[2]):
region = img[i:i+3, j:j+3, c]
output[i, j, c] = np.abs(np.sum(kernel * region))
return output
output_derivative_x = apply_derivative_filter(padded_img, kernel_x)
output_derivative_y = apply_derivative_filter(padded_img, kernel_y)
# 結果の表示
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(output_derivative_x, cv2.COLOR_BGR2RGB))
plt.title('Derivative Filter Output (X-direction)')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(output_derivative_y, cv2.COLOR_BGR2RGB))
plt.title('Derivative Filter Output (Y-direction)')
plt.show()
このコードを実行すると、次のような結果(右の画像)が得られます。
最後に
この記事では、画像処理の基本的なエッジ検出技術であるMAX-MINフィルタと微分フィルタの原理と実装方法について詳しく解説しました。これらのフィルタを適用することで、画像のエッジを強調し、画像内の重要な情報を抽出することができます。Pythonの関数を使わずにこれらのフィルタを実装する方法を紹介しましたが、理解を深めるために実際にコードを試してみることをお勧めします。今後も、画像処理の様々な技術について解説していきますので、ぜひ参考にしてください。
私の経歴などについては以下の記事から確認することができます!
ブログランキングに参加しています。ぜひクリックで応援お願いします
コメント