昨日のガボールフィルタに続き、
今日はガウシアンフィルタを実装してみます。
ガウシアンフィルタは、画像をぼかしたり、SIFTと呼ばれる特徴量抽出の中でとても
大活躍のフィルタです。
C言語で書くとこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void gaussianCoefficients(double *gaussian_filter, double sigma_pow_2, int w) { double PI = 3.1415926535897932384626; int mask_size = w*2 +1; double sum=0; for(int yy=0; yy<mask_size; yy++){ for(int xx=0; xx<mask_size; xx++){ double x = xx -w; double y = yy -w; gaussian_filter[yy*mask_size+xx]=(1.0/(2.0*PI*sigma_pow_2))*(exp((-1.0)*(((x*x)+(y*y))/(2.0*sigma_pow_2)))); sum = sum +gaussian_filter[yy*mask_size +xx]; } } printf("sum:%lf\n", sum); sum=0; } |
ガボールフィルタと比べるととても可愛げがあります!
今日は、これをPythonでカーネル作るだけでなく、画像をボカすところまでやってしまいます。
コードは下記です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# -*- coding: utf-8 -*- import cv2 import numpy as np import pylab as plt import os def main(): # 入力画像をグレースケールで読み込み os.chdir("/Users/XXXXXXX/ZZZZZZ/XX_IMG") imgGScale = cv2.imread("lenna.bmp", 0) # ガウシアンカーネル gaussianK = cv2.getGaussianKernel(21,5) # 畳み込み dst1 = cv2.filter2D(imgGScale, -1, gaussianK) # 画像表示 cv2.imshow('input', imgGScale) cv2.imshow('conv1', dst1) # キー押下で終了 cv2.waitKey(0) cv2.destroyAllWindows() if __name__=='__main__': main() |
ガウシアンフィルタもやっぱりライブラリで用意されてるっ・・・!
ゆとり仕様万歳!
実行!
INPUT
OUTPUT
お。
ぼけてはいるけど思ってたのと少し違う結果が出てきました。
縦に伸びるようにぼけてますね。
こんな時は、私の場合、下記を疑います。
(1) 畳み込み結果の配列の型と、Outputの配列の型が異なる可能性
(2)畳み込みで誤ったFor文が使われている可能性
(3)カーネルの中身が違う可能性
今回は、Python + OpenCVってこともあって、
(1)と(2)の線はうすいので
(3)から調べて見ます。
カーネルの値をプロットしてみたら、
案の定、ガウシアンフィルタが想定していたものと違いました。
どうやら、OpenCVの
getGaussianKernelで用意されているのは、1次元のガウシアンフィルタのようです。
なので、2次元のガウシアンフィルタを作って再実行!
コードは下記です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# -*- coding: utf-8 -*- import cv2 import numpy as np import pylab as plt import os def get2DGaussianKernel(size=21, sigma=5.): ax = np.arange(-1 * size // 2 + 1., size // 2 + 1.) xx, yy = np.meshgrid(ax, ax) kernel = np.exp(-(xx**2 + yy**2) / (2. * sigma**2)) return kernel / np.sum(kernel) def main(): # 入力画像をグレースケールで読み込み os.chdir("/Users/XXXXXX/ZZZZ/XX_IMG") imgGScale = cv2.imread("lenna.bmp", 0) # ガウシアンカーネル1D gaussianK1D = cv2.getGaussianKernel(21,5) # ガウシアンカーネル2D gaussianK2D = get2DGaussianKernel() # 畳み込み dst1 = cv2.filter2D(imgGScale, -1, gaussianK1D) dst2 = cv2.filter2D(imgGScale, -1, gaussianK2D) # 画像表示 #plt.imshow(gaussianK2D, cmap="ocean") and plt.show() cv2.imshow('input', imgGScale) cv2.imshow('conv1', dst1) cv2.imshow('conv2', dst2) # キー押下で終了 cv2.waitKey(0) cv2.destroyAllWindows() if __name__=='__main__': main() |
結果はこんな感じ。
綺麗にぼやけました!
以上!