昨日のガボールフィルタに続き、
今日はガウシアンフィルタを実装してみます。
ガウシアンフィルタは、画像をぼかしたり、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()  | 
					
結果はこんな感じ。

綺麗にぼやけました!
以上!