2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonによる画像処理100本ノック#9 ガウシアンフィルタ

Last updated at Posted at 2020-09-29

はじめに

どうも、らむです。
今回は画像中のノイズを除去するガウシアンフィルタを実装します。

9本目:ガウシアンフィルタ

ガウシアンフィルタとは画像の平滑化を行うフィルタです。このフィルタを適用することによって画像全体をぼやかしたような加工ができます。

このフィルタでは注目画素の周辺画素をガウス分布によって重み付けし、フィルタの中心画素に近いほど大きな重みを付けます。ガウス分布による重み付けは以下のように定義されます。

g(x,y) = \frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}

例えば、3×3や5×5のガウシアンフィルタは以下のフィルタがよく用いられます。おそらく引数のsに$σ=0.85$あたりを指定するとこの値になるかと思います。

$\frac{1}{16}$ $\frac{2}{16}$ $\frac{1}{16}$
$\frac{2}{16}$ $\frac{4}{16}$ $\frac{2}{16}$
$\frac{1}{16}$ $\frac{2}{16}$ $\frac{1}{16}$
$\frac{1}{256}$ $\frac{4}{256}$ $\frac{6}{256}$ $\frac{4}{256}$ $\frac{1}{256}$
$\frac{4}{256}$ $\frac{16}{256}$ $\frac{24}{256}$ $\frac{16}{256}$ $\frac{4}{256}$
$\frac{6}{256}$ $\frac{24}{256}$ $\frac{36}{256}$ $\frac{24}{256}$ $\frac{6}{256}$
$\frac{4}{256}$ $\frac{16}{256}$ $\frac{24}{256}$ $\frac{16}{256}$ $\frac{4}{256}$
$\frac{1}{256}$ $\frac{4}{256}$ $\frac{6}{256}$ $\frac{4}{256}$ $\frac{1}{256}$

注目画素が中心だとすると、周辺画素と対応するフィルタ値の積の総和を注目画素に代入すれば良いですね。
3×3フィルタであれば$I(x_0,y_0)×\frac{1}{16} + I(x_0,y_1)×\frac{2}{16} + ... I(x_2,y_2)×\frac{1}{16}$の値を注目画素に代入します。

また、画像の端部分はフィルタリング処理が行えないので存在しない画素は0を用います。これを0パディングといいます。

ソースコード

gaussianFilter.py
import numpy as np
import cv2
import matplotlib.pyplot as plt


def gaussianFilter(img,k,s):
  w,h,c = img.shape
  size = k // 2

  # 0パディング処理
  _img = np.zeros((w+2*size,h+2*size,c), dtype=np.uint8)
  _img[size:size+w,size:size+h] = img.copy().astype(np.uint8)
  dst = _img.copy()

  # フィルタ作成
  ker = np.zeros((k,k), dtype=np.float)
  for x in range(-1*size,k-size):
    for y in range(-1*size,k-size):
      ker[x+size,y+size] = (1/(2*np.pi*(s**2)))*np.exp(-1*(x**2+y**2)/(2*(s**2)))

  ker /= ker.sum()

  # フィルタリング処理
  for x in range(w):
    for y in range(h):
      for z in range(c):
        dst[x+size,y+size,z] = np.sum(ker*_img[x:x+k,y:y+k,z])

  dst = dst[size:size+w,size:size+h].astype(np.uint8)

  return dst


# 画像読込
img = cv2.imread('image.jpg')

# ガウシアンフィルタ
# 第2引数:フィルタサイズ、第3引数:標準偏差(σ)
img = gaussianFilter(img,21,2)

# 画像保存
cv2.imwrite('result.jpg', img)
# 画像表示
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()

ファイル名 ファイル名

画像左は入力画像、画像右は出力画像です。
点状のノイズが低減されていることが分かります。

おわりに

もし、質問がある方がいらっしゃれば気軽にどうぞ。
imori_imoriさんのGithubに公式の解答が載っているので是非そちらも確認してみてください。
それから、pythonは初心者なので間違っているところがあっても優しく指摘してあげてください。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?