空間フィルター
空間の情報は直線、カーブする曲線、円や四角など形を表す情報である。このような形を取り出す方法として、空間フィルターという画像処理がある。
フィルターは2次元の行列で表し、画像の一部とフィルターの要素の積の和を、画像をスライドさせながら画像の現領域で求めていく。このような計算を畳み込み演算と呼ぶ。
元画像の位置(i, j)のピクセル値をx(i, j)、3×3のフィルターをh(i, j)としたら、畳み込み演算でえられる値g(i, j)は、以下のようになる。
g(i, j) = \sum_{u=-1}^{1} \sum_{v=-1}^{1} x(i + u, j + v) h(u + 1, v + 1)
フィルターの大きさは3×3だけでなく任意に決めることができるが、5×5、7×7など、中心を決められる奇数の幅が使いやすい。
実際に手書き数字に畳み込み演算をしてみる。
import numpy as np
import matplotlib.pyplot as plt
import time
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import Adam
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 28, 28, 1)
x_train = x_train.astype('float32')
x_train = x_train / 255
num_classes = 10
y_train = to_categorical(y_train, num_classes)
x_test = x_test.reshape(10000, 28, 28, 1)
x_test = x_test.astype('float32')
x_test = x_test / 255
y_test = to_categorical(y_test, num_classes)
id_img = 2
myfile1 = np.array([[1, 1, 1], [1, 1, 1], [-2, -2, -2]], dtype=float)
myfile2 = np.array([[-2, 1, 1], [-2, 1, 1], [-2, 1, 1]], dtype=float)
x_img = x_train[id_img, :, :, 0]
img_h = 28
img_w = 28
x_img = x_img.reshape(img_h, img_w)
out_img1 = np.zeros_like(x_img)
out_img2 = np.zeros_like(x_img)
# フィルター処理
for ih in range(img_h - 3):
for iw in range(img_w - 3):
img_part = x_img[ih:ih + 3, iw:iw + 3]
out_img1[ih + 1, iw + 1] = np.dot(img_part.reshape(-1), myfile1.reshape(-1))
out_img2[ih + 1, iw + 1] = np.dot(img_part.reshape(-1), myfile2.reshape(-1))
# 表示
plt.figure(1, figsize=(12, 3.2))
plt.subplots_adjust(wspace=0.5)
plt.gray()
plt.subplot(1, 3, 1)
plt.pcolor(1 - x_img)
plt.xlim(-1, 29)
plt.ylim(29, -1)
plt.subplot(1, 3, 2)
plt.pcolor(-out_img1)
plt.xlim(-1, 29)
plt.ylim(29, -1)
plt.subplot(1, 3, 3)
plt.pcolor(-out_img2)
plt.xlim(-1, 29)
plt.ylim(29, -1)
plt.show()
左画像が元の画像であり、真ん中は横ラインにエッジを効かせた画像。右は縦ラインにエッジを効かせた画像である。
フィルターを適用すると出力画像のサイズは一回り小さくなる。この対応策としてパディングという方法がある。
パディングはフィルターを適用する前に、0などの固定した要素で周囲を水増しする方法である。
3×3のフィルターを適用する場合には、幅1のパディングを施、5×5の場合には、幅2のパディングをすればいい。
パディングに加えてフィルター処理に関するパラメータがもう1つある。フィルターは1つ間隔をずらすが、2でも3でも、任意の間隔でずらすことができる。この間隔をストライド呼ぶ。
ストライドを大きくすると出力画像は小さくなる。パディングやストライドの値はライブラリで畳み込みネットワークを使う際に、引数として渡すことになる。