ガウシアンフィルタ
作業の流れ
ハフ変換を行う前にCanny法というものを使ってエッジ検出を行います。 Canny法ではまずガウシアンフィルタによるぼかしの処理を行います。
よってPythonの練習もかねて、まずガウシアンフィルタを実装しようと思います。
ガウシアンフィルタを使う例
ガウシアンフィルタは趣味のお絵描きでもよく使用している便利な処理です。 以下にガウシアンフィルタがイラスト制作に使われる例を示します。 (プログラム書く前に絵の制作で時間を溶かしたのは内緒...)
このように、イラストの背景にガウスぼかしをかけることによって主役の人物が見やすくなります。 この処理はお絵かきソフトClipStudioで行いました。
このガウスぼかしに使用するガウシアンフィルタを実装していきます。
ガウシアンフィルタの原理
ガウシアンフィルタではガウス分布というものを利用して、注目画素からの距離に応じて近傍の画素値に重みをかける処理を行っています。以下にガウス分布の式を載せます。
ガウス分布は確率統計とかでよく出てくる正規分布と同じものみたいです。偏差値の計算など、色々なところで使われるみたいです。 このガウス分布によって注目画素の周りの画素の画素値に重みを付けることでぼかしていきます。
プログラム
実際にガウシアンフィルタを行うプログラムです。 グレースケール化は無くても良いのですが勉強の過程で書いてみて、今後も必要なので載せました。
import cv2 import numpy as np #グレースケール化 def BGR2GRAY(img): b = img[:,:,0].copy() g = img[:,:,1].copy() r = img[:,:,2].copy() print(b) out = 0.2126*r + 0.7152*g + 0.0722*b #整数に変換 out = out.astype(np.uint8) return out #ガウシアンフィルタ def gaussian_filter(img,k_range=7,sigma=1.3): #入力画像がカラーかグレー化を判定し、グレーなら要素を増やす if len(img.shape) == 3: H,W,C = img.shape else: img = np.expand_dims(img,axis=-1) H,W,C = img.shape #//は切り捨て除算 pad = k_range//2 #隅の画素でも重み付けができるように0パディング out = np.zeros((H + pad *2,W + pad * 2,C),dtype=np.float) #入力画像を0パディング付きで複製 out[pad: pad + H,pad: pad + W] = img.copy().astype(np.float) #カーネルの準備 K = np.zeros((k_range,k_range),dtype=np.float) for x in range(-pad,-pad + k_range): for y in range(-pad, -pad + k_range): #ここで肝のガウス分布の式が登場 K[y + pad,x + pad] = np.exp(-(x ** 2 + y ** 2)/(2 * (sigma ** 2))) K /= (2*np.pi * sigma * sigma) #最後にカーネルの合計で割る K /= K.sum() tmp = out.copy() for y in range(H): for x in range(W): for c in range(C): out[pad + y,pad + x,c] = np.sum(K * tmp[y: y + k_range,x:x + k_range,c]) #0から255の範囲に収める out = np.clip(out,0,255) out = out[pad: pad + H,pad:pad + W].astype(np.uint8) return out img = cv2.imread("hough.png").astype(np.float) out = gaussian_filter(img) cv2.imshow("result",out) cv2.waitKey(0)
gaussian_filter内の画像はこのような感じになっているはずです。
このサイトのコードをガッツリ参考にしました github.com
結果はこんな感じです。
このガウシアンフィルタ、実はOpenCVのメソッドを使うと10行で実装できてしまいます。
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('hough.png') #kernel = np.ones((5,5),np.float32)/25 out = cv2.GaussianBlur(img,(7,7),1.3) cv2.imshow("result",out) cv2.waitKey(0)
次はこのガウシアンフィルタを使ってCanny法を実装しようと思います。