バナナでもわかる話

計量経済学・統計学が専門の大学院生です。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

画像認識始めました~ガウシアンフィルタをRで実装してみた

最近画像認識について勉強中です。
画像認識始めました~手始めにRでスクラッチでフィルタリングしてみた~ - バナナでもわかる話


とりあえず、数式で理解した後スクラッチで書いてみるのが一番早いかなと思ったので、読んだ傍からRで書いています。
参考本はこれ。

前回は平均化フィルタを使って前に撮ったイグアナちゃんをフィルタリングしたわけなんですけど、
今回はガウシアンフィルタでやってみます。

スポンサーリンク



ガウシアンフィルタとは

二変量(画像には縦と横があるので)標準正規分布の中心の点(0,0)を平滑化したい点に合わせて、そこから離れるほど重みが小さくなるようなウエイトを用意してやろうという方法で、離散個のピクセルにウエイトを与えてウエイトの和が1にならねばならないので、その調整のために確率の総和 Wで割ります。条件付き分布と発想は同じですね。


というわけでコードを書いてみました。正直自分コーディング技術がないので、半ばゴリ押しのようになってしまいましたが....

#k個周りのガウシアンフィルタ
#パラメータの設定(sigmaは標準正規分布の標準偏差)
k=5
sigma=3
#imageに処理したい画像を入れてる
image4=array(0,dim=c(dim(image)[1],dim(image)[2],3))
#matに処理したい画像を入れる
Gaussian=function(mat=matrix(),ii,jj,kk,sigma){
	zzz=mat[max(1,(ii-kk)):min(dim(image)[1],(ii+kk)),max(1,(jj-kk)):min(dim(image)[2],(jj+kk)),]
#取り出した行列のスポットしたい点の座標を見つける
	hajix=max(1,(ii-kk))
	hajiy=max(1,(jj-kk))
	idox=1-hajix
	idoy=1-hajiy
#座標の特定
	midPointx=ii+idox
	midPointy=jj+idoy
	Dim_matx=matrix(1:dim(zzz)[1],dim(zzz)[1],dim(zzz)[2])-midPointx
	Dim_maty=t(matrix(1:dim(zzz)[2],dim(zzz)[2],dim(zzz)[1]))-midPointy
#gggにガウシアンフィルタを作る
	ggg=matrix(0,dim(zzz)[1],dim(zzz)[2])
	for(iii in 1:dim(zzz)[1]){
		for(jjj in 1:dim(zzz)[2]){
			ggg[iii,jjj]=(1/(2*pi*sigma^2))*exp(-(Dim_matx[iii,jjj]^2+Dim_maty[iii,jjj]^2)/(2*sigma^2))
		}
	}
	ggg
}
for(i in 1:(dim(image)[1])){
	for(j in 1:(dim(image)[2])){
		GG0=Gaussian(mat=image,ii=i,jj=j,kk=k,sigma=sigma)
		GG=array(GG0,dim=c(dim(GG0)[1],dim(GG0)[2],3))
		zzz=image[max(1,(i-k)):min(dim(image)[1],(i+k)),max(1,(j-k)):min(dim(image)[2],(j+k)),]
#Wはウエイトの和
		W=sum(GG0)
		image4[i,j,]=(1/W)*apply((GG*zzz),3,sum)
	}
}

こんな感じで作ってみました。コーディング技術欲しい.....

というわけで処理結果
f:id:bananarian:20181120122403p:plain

ちなみに処理前
f:id:bananarian:20181120002450p:plain

口の周りとか足のあたりとか見てもらうとわかりやすいかと思うんですけど、ザラザラ感がちょっと消えてます。
もう少しkを大きくしたりsigmaを大きく取ったりするともう少し分かりやすく変化するとは思いますが、


要はフィルタリングって前回も言ったと思うんですけど、ノイズを取ることが目的です。
だからザラザラした部分とかが均されてるわけです。

ただこのガウシアンフィルタの問題点は何か特徴に従って区別して均しているわけではなく、全ての点で同じような均し方をしているため、物体間の境界が不鮮明になる可能性があります。それを解決するためのフィルタがあるようなので、次回はそれを実装しようと思います。