ガウシアンフィルタ
ガウシアンフィルタとはなにか
画像処理におけるガウシアンフィルタ(Gaussian filter)とは、平滑化フィルタ(smoothing filter)の一つであり、画像に含まれるノイズを軽減するのに使われる。
ガウス分布を近似したカーネル(kernel)を利用して畳み込み演算をすることで、フィルタリングを行う。
2次元ガウス分布
画像のガウシアンフィルタでは、2次元ガウス分布を利用するが、特別考慮することがなければ、x方向とy方向は独立で、同じ分散に従っているようなガウス分布を考える。
つまり、xとyに相関があったり分散が異なるような一般的なガウス分布を考える必要はない。
まずそういった2次元ガウス分布の確率密度関数を表示してみよう。
x方向の周辺分布が、標準偏差σの1次元ガウス分布
y方向の周辺分布も、標準偏差σの1次元ガウス分布
である。 これらが独立なので、求める確率密度関数は、
である。
2次元ガウス分布の近似
この分布
無限に連続的に広がっているものを有限で離散的なピクセルの集合である画像と畳み込み計算するのを考えるのは難しいので、
この
カーネルの具体例としては、よく次のようなものが使われる。
これらのカーネルはどのように
実は、各格子に対して
たとえば、左の3x3の格子の場合、
となり、これらの和は
となる。そこでカーネルの各格子の値は
と計算される。
各
乗じない場合を
また、
とおくと、
と非常に簡潔になる。
つまり、カーネルを計算するうえでは、まず
これを正規化すると、カーネルが得られる。
逆にカーネルが与えられたとき、そのベースとなるガウス分布の
によって求めれば良い。
たとえば、上に示した5x5の格子の場合、
であるから、
となる。
以上の議論を踏まえて、numpyを使用してガウシアンフィルタのカーネルを計算するコード例は次のようなものである。
import numpy as np
def make_gaussian_kernel(width: int, height: int, sigma: float) -> np.ndarray
# kernelの中心と1個横のセルの値の比
r = np.exp(-1 / (2 * sigma**2))
# kernelの中心index
mw = width // 2
mh = height // 2
# kernelの中心を原点とした座標が入った配列
xs = np.arange(-mw, mw + 1)
ys = np.arange(-mh, mh + 1)
x, y = np.meshgrid(xs, ys)
# rを絶対値の2乗分累乗すると、ベースとなる配列が求まる
g = r**(x**2 + y**2)
# 正規化
return g / np.sum(g)
畳み込み
こうしてできたカーネルを、元の画像に畳み込むことでガウシアンフィルタとなる。
畳み込み演算(convolution)は、「カーネルに従って周りの画素値を取り込むこと」、と考えればよい。
元の画像の画素値を
ここで、
畳み込みを行う際は、元の画像の端っこの処理についていくつかのバリエーションが考えられる。
たとえば、scipyのconvolve2dには、いくつかのモードが用意されている。
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html
フィルタ例
以下は、実際に3x3、
元の画像が平滑化されていることがわかる。
エッジ部分もぼやけてしまうため、ノイズの性質によって適切なフィルタを選択する必要はある。