今回は空間フィルタリングのpart1ということで、pythonを用いて平滑化フィルタとエッジ抽出フィルタを設計してみます。平滑化フィルタは、画像内のノイズを除去し、ぼかしの効果を与えるのに有効です。また、エッジ抽出フィルタは画像内の輪郭線のみを取り出すことができます。入力画像には様々なノイズ、歪みが含まれるため、こういったフィルタを用いて、人間の目でも見やすい画像をつくることができます。
空間フィルタリングと畳み込み演算
空間フィルタリングとは、画像の任意の座標$(i,j)$における画素$f(i,j)$に対しフィルタの重み$h(m,n)$を用いて
の演算を行い、$g(i,j)$ を座標$(i,j)$の新しい画素として置き換えるような処理です。このように、画像の画素値とフィルタの重みを用いて積和する演算を畳み込み演算と呼びます。
また、フィルタの重みである$h(m,n)$の値を変化させることで、様々な空間フィルタリングを行うことができま す。
空間フィルタリングの種類
空間フィルタリングにも様々な種類があり、フィルタの重みによって画像を鮮明にしたり、逆にぼかしたり、または画像内のある特性のみ取り出したり、画像に凹凸をつけたりすることもできます。
今回はその中から以下の2つの空間フィルタリングを取り上げます。
1. 平滑化フィルタ
平滑化フィルタは、画像全体にぼかしの効果を与え、結果的に画像内のノイズを除去するようなフィルタです。これには、平均化フィルタ、モーションフィルタ、ガウシアンフィルタなどが存在しますが、今回は平均化フィルタについて取り扱います。
平均化フィルタを用いた時の画像の変化
2. エッジ抽出フィルタ
エッジ抽出フィルタは文字どおり画像内の輪郭線のみを取り出すフィルタです。
エッジ抽出フィルタを用いた画像の変化
空間フィルタリングの実行
まず、pythonのライブラリにあるOpenCVとMatplotlibをインポートします。
import cv2 import matplotlib.pyplot as plt
今回はこの画像を使用していきます。
img_example
この白黒画像の画像表示を行います。
img_bgr = cv2.imread("img_example.jpg")
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
img_g = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) plt.gray() plt.imshow(img_g)
pythonのライブラリから、numpyをインポートし平均化フィルタを用いた畳み込み演算を設計します。 平均化フィルタは以下のような行列です。
import numpy as np shp = np.shape(F) ## 画像のshape を保存 H = np.ones([3,3])/9 ## フィルタの要素をセット F = img_g G = np.zeros(shp) for i in range(shp[0]): for j in range(shp[1]): for n in range(-1,2): for m in range(-1,2): G[i,j] = G[i,j] + F[(i+m)%shp[0], (j+n)%shp[1]] * H[m,n]
これを実際の画像に適用させます。
plt.subplot(1,2,1) plt.gray() plt.imshow(F) plt.title("Before") plt.subplot(1,2,2) plt.gray() plt.imshow(G) plt.title("After")
出力結果はこんな感じになります。うまく画像をぼかすことができました。
平滑化フィルタの実行
次に、エッジ抽出フィルタの畳み込み演算を設計します。フィルタは以下のとおりです。
H_p = np.array([[0,-1,0],[0,1,0],[0,0,0]]) F = img_g G = np.zeros(shp) for i in range(shp[0]): for j in range(shp[1]): for n in range(-1,2): for m in range(-1,2): G[i,j] = G[i,j] + F[(i+m)%shp[0], (j+n)%shp[1]] * H_p[m,n]
これも同様に画像に適用させます。
plt.subplot(1,2,1) plt.gray() plt.imshow(F) plt.title("Before") plt.subplot(1,2,2) plt.gray() plt.imshow(G) plt.title("After")
出力結果は以下の通りです。上手く輪郭線のみを取り出すことができました。
エッジ抽出フィルタの実行
このように、フィルタの重みを変えることによって様々な空間フィルタリングを設計できます。皆さんも是非、空間フィルタリングを用いた画像処理をやってみてください。