画像処理分野においてフィルタ処理と呼ばれる技術があります。
何をするのかを端的に言うと、ノイズが含まれる画像にフィルタ処理を行うことで、ノイズを除去しようと言う技術です。
やる理由としては、画像認識、近年では自動運転などAIを用いた技術が発達していて、画像認識を行うための画像が汚れていては画像を誤認識してしまうため、フィルタ処理を行うのです。
ノイズを含ませる方法は以前のブログにて紹介しています。
ガウシアンフィルタとは
ガウシアンフィルタは次のようなガウス分布を用いて近傍画素値に重みをつけて行います。
$$ g(x, y, \sigma) = \frac{1}{\sqrt{2\pi}\\ \sigma}exp(-\frac{x^2+y^2}{2\sigma^2}) $$
画像フィルタとして用いられる時、標準偏差をσ=1.3で8近傍ガウシアンフィルタ すなわち 3x3フィルタの場合以下のようになります
$$ K = \frac{1}{16}\begin{bmatrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \\ \end{bmatrix} $$
以前紹介した移動平均フィルタと同様に正方行列で形成され、数値が違うと言うことになります。
フィルタ処理方法
フィルタ処理方法も移動平均と同じです。
1.ガウシアンフィルタを用意する

2.入力画像から注目画素をガウシアンフィルタと同じ近傍分取得する

3.取得した注目画素およびその周辺画素とガウシアンフィルタとで畳み込む

3.1.畳み込みの仕方
色が同じもので掛け算を行い、その合計値を算出する。

3.2.アニメーションによる処理の可視化
以下のように計算します。

4.出力
上記の計算結果を出力画像用の正規行列に代入する。代入場所は注目画素を取り出した場所である。

ガウシアンフィルタ処理結果
左から順に、ノイズを含まない画像, ノイズを含む画像, フィルタ処理結果となります。



全てのノイズを除去しているとは言い切れないですね..
実は、ガウシアンフィルタは、フィルタ処理性能としてはノイズ除去率が悪くボケてしまっていてあまり実用的とはいえません。とはいえ画像用フィルタの基本であり基盤となるフィルタなので画像フィルタを学ぶものとして知っておくべきフィルタです。
現在はいろんな研究が進み、性能の良いフィルタも開発されています。
Pythonコード
# ライブラリのインポート
import cv2
import numpy as np
# ガウシアンフィルタ
class GaussianFilter:
def __init__(self, img):
self.img = img
self.denoise_img = None
def filtering(self, kernel):
self.createGaussian(kernel)
self.mainGaus()
return self.denoise_img
# ガウシアンフィルタ作成
def createGaussian(self, kernel):
filter_tmp = np.ones([kernel, kernel])
filter = np.ones([kernel, kernel])
# パスカルの三角形より作成
for i in range(1, kernel):
for j in range(kernel):
if j == 0:
filter_tmp[i][j] = 1
elif j == i:
filter_tmp[i][j] = 1
else:
filter_tmp[i][j] = filter_tmp[i-1][j-1] + filter_tmp[i-1][j]
for i in range(kernel):
for j in range(kernel):
filter[i][j] = filter_tmp[-1][j] * filter_tmp[-1][i]
# 正規化
self.filter = filter / np.sum(filter)
return 0
# ガウシアンフィルタメイン処理 畳み込み処理
def mainGaus(self):
x = self.img.shape[0]
y = self.img.shape[1]
kx = self.filter.shape[0]
k1 = int(kx / 2)
calc_sum = 0
quantity = 0
filtering_img = np.zeros([x, y])
for i in range(x):
for j in range(y):
for p in range(-k1, k1+1):
for q in range(-k1, k1+1):
if ((i + p) >= 0) and ((i + p) < x):
if ((j + q) >= 0) and ((j + q) < y):
calc_sum = calc_sum + self.img[i+p][j+q] + self.filter[p+k1][q+k1]
quantity += 1
filtering_img[i][j] = calc_sum / quantity
calc_sum = 0
quantity = 0
self.denoise_img = np.array(filtering_img, dtype=int)
return 0
if __name__ == '__main__':
origin_name = "ノイズなし画像" # 今回の処理で使用しない 比較用
noise_name = "フィルタ処理をかけたい画像"
img = cv2.imread(origin_name, cv2.IMREAD_GRAYSCALE) # 今回の処理で使用しない 比較用
noise_img = cv2.imread(noise_name, cv2.IMREAD_GRAYSCALE)
kernel = 3
Gaus = GaussianFilter(noise_img)
result_img = Gaus.filtering(kernel)
# 書き込み
cv2.imwrite("denoise_img.png", result_img)
コメント