Python入門トップページ


目次

  1. scikit-image のインストール
  2. Matplotlib による画像の表示
  3. 表示関数の定義
  4. RGBA から RGB への変換
  5. グレースケールをイメージする
  6. RGB からグレースケールへの変換
    1. RGB 平均
    2. ITU-R Rec BT.602
    3. Contemporary CRT phosphors (Rec 709)
    4. 3種類の比較
    5. scikit-image の rgb2gray 関数
  7. 平均化フィルタ
    1. 平均化フィルタの自作
    2. 平均化フィルタの一般化
    3. scikit-image の平均化フィルタ関数
  8. ガウシアンフィルタ
  9. バイラテラルフィルタ
  10. ランダムノイズとフィルタ
  11. ソーベルフィルタ
    1. ソーベルフィルタの自作
    2. scikit-image の sobel 関数
    3. 平均化/ガウシアンフィルタとソーベルフィルタの併用

画像フィルタの作成と利用

平均化フィルタ

画像フィルタは,画像のある注目したい画素について,その近傍領域の画素も入力データとして何らかの処理を行い,注目画素の値を出力するものです.様々なフィルタが存在し,フィルタを利用すると画像の何らかの特徴(エッジやコーナーなど)を抽出できるようになります.このようなフィルタは畳み込みニューラルネットワークなどでも利用されています.

まず,平均化フィルタの仕組みを理解しよう.平均化フィルタは注目したい画素の近傍領域(例えば3×3=9画素)の平均値を利用するフィルタです.例えば入力画像の \(x=55\), \(y=85\), 画素値 \(=113\) の画素について,次のように近傍領域の平均値を計算します.

\begin{equation} (179 + 169 + 122 + 158 + 113 + 99 + 106 + 107 + 113) / 9 = 129 \end{equation}
入力画像
filters_20_gray_zoom2.png

平均化フィルタによって得られた画像は次のようになります.

平均化フィルタ
filters_20_mean_zoom2.png

平均化フィルタなどここで考えるフィルタは線形空間フィルタリングと呼ばれます.この線形空間フィルタリングを数学的に定義してみます.入力画像を \(I\),出力画像を \(\tilde{I}\) とします.注目する画素の座標 \((x,y)\) に対する画素値を \(I(x, y)\) とし,近傍領域の大きさを \((2N+1)\times(2N+1)\) とすると線形空間フィルタは次のようになります.

\begin{equation} \tilde{I}(x,y) = \sum_{j=-N}^{N}\sum_{i=-N}^{N} \boldsymbol{F}(i,j)I(x+i, y+j) \end{equation}

ここで,上の式の \(\boldsymbol{F}\) はカーネルと呼ばれ,\((2N+1)\times(2N+1)\) の行列です.例えば,\(N=1\) の平均化フィルタのカーネルは次のようになります.

\begin{equation} \boldsymbol{F} = \frac{1}{9} \left( \begin{array}{ccc} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{array} \right) \end{equation}

平均化フィルタの自作

それでは平均化フィルタのコードを自作してみよう.なお,あらかじめ「表示関数の定義」ページを参照し,ライブラリのインポートと関数の定義を実行しておいてください.

RGBA形式の png 画像ファイルを RGB 形式に変換したのち,さらにグレースケールに変換して表示します.

ink_img = plt.imread('ink.png')
img = color.rgba2rgb(ink_img)
gray_img = color.rgb2gray(img)
show(gray_img)
filters_20_gray.png

繰り返し処理を使って,画素ごとに近傍領域の平均値を計算する処理を記述します.

mean_filter_img = np.copy(gray_img)
h, w = mean_filter_img.shape

for j in range(1, h-1):
    for i in range(1, w-1):
        mean_filter_img[j, i] = (
            gray_img[j-1, i-1] + gray_img[j-1, i] + gray_img[j-1, i+1] +
            gray_img[j, i-1] + gray_img[j, i] + gray_img[j, i+1] +
            gray_img[j+1, i-1] + gray_img[j+1, i] + gray_img[j+1, i+1]
        ) / 9.0
show(mean_filter_img)
filters_20_mean.png

平均化フィルタを利用すると画像が平滑化することができます.つまり,画像中のノイズを低減することができるようになります.

目次に戻る