OpenCVで画像の平滑化をしてみた
はじめに
画像処理では、必ずしもキレイな画像を用意できるとは限りません。
不鮮明だったり、ノイズが入っていたりといったことも多くあります。
ノイズが入っている場合には、平滑化という手法を用いてそれを取り除くことがあります。
あるいはわざと不鮮明な画像を作り、ダミーデータとして使用する、ということもあります。
今回は、Pythonを使ってOpenCVによる画像の平滑化を行います。
平滑化とは
平滑化(へいかつか)、あるいはスムージング処理とは、簡単に言うと画像をぼかすことです。
画像をぼかすということは、画素値の変化を滑らかにすることとも言えます。
ノイズやエッジは、画素値の急激な変化です。
平滑化により、ノイズやエッジを消したり、目立たなくすることができます。
準備
環境はGoogle Colaboratoryを使用します。
Pythonのバージョンは以下です。
import platform
print("python " + platform.python_version())
# python 3.6.9
画像を表示してみよう
では、早速コードを書いていきましょう。
まずは、OpenCVをインポートします。
import cv2
さらに、Colaboratoryで画像を表示するため、以下もインポートします。
from google.colab.patches import cv2_imshow
サンプルの画像も用意しておきましょう。
今回は、Pixabayのフリー画像を使用します。
それでは、用意したサンプル画像を表示してみましょう。
img = cv2.imread(path) # pathは画像を置いている場所を指定
cv2_imshow(img)
また、後で必要になるため、ノイズ入りの画像も用意しておきます。
ここでは、「salt-and-pepper noise(ごま塩ノイズとも呼ばれる)」というノイズを画像に付加してみましょう。
# salt-and-pepper noise
# コードは以下を参照
# https://lp-tech.net/articles/nCvfb?page=2
import numpy as np
row, col, ch = img.shape
img_sp = cv2.imread(path)
# salt
pts_x = np.random.randint(0, col-1 , 1000)
pts_y = np.random.randint(0, row-1 , 1000)
img_sp[(pts_y,pts_x)] = (255, 255, 255)
# pepper
pts_x = np.random.randint(0, col-1 , 1000)
pts_y = np.random.randint(0, row-1 , 1000)
img_sp[(pts_y, pts_x)] = (0, 0, 0)
cv2_imshow(img_sp)
平滑化
一般的な平滑化
平滑化とは、簡単に言うと画像をぼかすことです。
OpenCVで画像を平滑化する最も簡単な方法は、cv2.blurを使用する方法です。
ここで、blurとは「ぼかし」という意味です。
それでは、平滑化した画像を表示してみましょう。
元画像と並べて表示してみます。
img_blur = cv2.blur(img, (3, 3))
imgs = cv2.hconcat([img, img_blur])
cv2_imshow(imgs)
左が元画像、右が平滑化した画像です。
右のほうが少しボケているのがわかると思います。
cv2.blurの引数は2つあります。
1つ目は、インプットとなる画像です。
2つ目は、カーネルと呼ばれるものです。画像の1点を決めたとき、周囲のどれだけの領域を含むかを表します。「箱の大きさ」だと考えてみて下さい。
上の例では(3, 3)となっており、これは画像の1点を中心とする3×3の領域を対象とすることを表します。
一般的な平滑化であるcv2.blurでは、このカーネル内の画素の平均値でカーネル内を塗りつぶします。
カーネルのサイズが大きくなればなるほど、画像のぼけ具合が強くなっていきます。
カーネルサイズを色々と変更してみた画像を表示してみましょう。
img1 = cv2.blur(img, (1, 1))
img2 = cv2.blur(img, (2, 2))
img3 = cv2.blur(img, (3, 3))
img4 = cv2.blur(img, (4, 4))
img5 = cv2.blur(img, (5, 5))
img6 = cv2.blur(img, (6, 6))
imgs_1 = cv2.hconcat([img1, img2, img3])
imgs_2 = cv2.hconcat([img4, img5, img6])
imgs = cv2.vconcat([imgs_1, imgs_2])
cv2_imshow(imgs)
左上から順に、カーネルサイズを大きくしていった画像になります。
画像のぼけ具合がどんどん強くなっているのがわかりますね。
Gaussianフィルタ
一般的な平滑化の他にも、OpenCVではいくつかの平滑化処理が可能です。
次は、Gaussianフィルタというものを紹介します。
一般的な平滑化では、カーネル内の画素を平均値という一定値で塗りつぶしました。
Gaussianフィルタでは、カーネルの中心からの距離に応じて値が変わります。
中心での値が一番大きく、離れるにつれて値は小さくなります。
その様子がガウス関数(Gaussian)と呼ばれる関数に従うので、Gaussianフィルタと呼ばれます。
ガウス関数の式は以下です。
\frac{1}{\sqrt{2\pi\sigma^2}}\exp\Bigl(-\frac{x^2}{2\sigma^2}\Bigr) \\
また、ガウス関数のグラフは以下のようになります。
それでは、ガウシアンフィルタを用いて画像を平滑化してみましょう。
こちらも、元画像と並べて表示してみます。
img_gauss = cv2.GaussianBlur(img, (3, 3), 3)
imgs = cv2.hconcat([img, img_gauss])
cv2_imshow(imgs)
cv2.GaussianBlurの引数は3つです。
最初の2つは、cv2.blur同様、インプット画像とカーネルサイズです。
3つ目の引数は、ガウス関数の$\sigma$(シグマ)に相当します。
$\sigma$が小さいと、ピークは高くなる代わりに広がりは狭くなります。
逆に$\sigma$が大きくなると、広がりは大きくなりますが、ピークは低くなります。
medianフィルタ
次は、medianフィルタを紹介します。
medianとは「中央値」のことで、指定したカーネル内に含まれる画素から中央値を取り出し、その値でカーネル全体を塗りつぶします。
一般的な平滑化と異なるのは、平均化された画素値ではなく、必ず存在する画素値を使用するという点になります。
medianフィルタを使用した画像を元画像と比較してみましょう。
img_med = cv2.medianBlur(img, 3)
imgs = cv2.hconcat([img, img_med])
cv2_imshow(imgs)
cv2.medianBlurの引数は2つで、インプット画像とカーネルサイズです。
上記では、2つ目の引数を3としていますが、これは3×3のカーネルを表しています。
このmedianフィルタは、salt-and-pepper noiseの除去に威力を発揮します。
実際に、ノイズ入りの画像に対してmedianフィルタをかけた結果は以下になります。
きれいに除去できているのがわかりますね。
bilateralフィルタ
最後に、bilateral(バイラテラル)フィルタを紹介します。
bilateralとは、「両方ともある」といった意味ですが、このフィルタはエッジをうまく残すことができます。
今までの平滑化フィルタは、エッジなどのピークも含めてぼかしていました。
bilateralフィルタは、画像をぼかしつつ、エッジも残すことができる便利なフィルタです。
元画像とあわせて出力してみましょう。
img_bi = cv2.bilateralFilter(img, 9, 75, 75)
imgs = cv2.hconcat([img, img_bi])
cv2_imshow(imgs)
全体的に滑らかになっているにも関わらず、エッジ部分はしっかりと残しているのがわかりますね。
cv2.bilateralFilterの引数の詳細は省きます。OpenCVの公式ドキュメントなどを参照下さい。
まとめ
今回は、Pythonを使ってOpenCVにより画像の平滑化を行いました。
画像処理でノイズの除去が必要になった際には、平滑化を試してみて下さい。
平滑化に関するさらに詳しい内容は、以下が参考になります。
- 画像の平滑化
- 【Udemy】 【Pythonで学ぶ】OpenCVでの画像処理入門
Author And Source
この問題について(OpenCVで画像の平滑化をしてみた), 我々は、より多くの情報をここで見つけました https://qiita.com/shoku-pan/items/07ec25f1d50629fed698著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .