最近画像認識について勉強中です。
画像認識始めました~手始めにRでスクラッチでフィルタリングしてみた~ - バナナでもわかる話
とりあえず、数式で理解した後スクラッチで書いてみるのが一番早いかなと思ったので、読んだ傍からRで書いています。
参考本はこれ。
前回は平均化フィルタを使って前に撮ったイグアナちゃんをフィルタリングしたわけなんですけど、
今回はガウシアンフィルタでやってみます。
スポンサーリンク
ガウシアンフィルタとは
二変量(画像には縦と横があるので)標準正規分布の中心の点(0,0)を平滑化したい点に合わせて、そこから離れるほど重みが小さくなるようなウエイトを用意してやろうという方法で、離散個のピクセルにウエイトを与えてウエイトの和が1にならねばならないので、その調整のために確率の総和で割ります。条件付き分布と発想は同じですね。
というわけでコードを書いてみました。正直自分コーディング技術がないので、半ばゴリ押しのようになってしまいましたが....
#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) } }
こんな感じで作ってみました。コーディング技術欲しい.....
というわけで処理結果
ちなみに処理前
口の周りとか足のあたりとか見てもらうとわかりやすいかと思うんですけど、ザラザラ感がちょっと消えてます。
もう少しkを大きくしたりsigmaを大きく取ったりするともう少し分かりやすく変化するとは思いますが、
要はフィルタリングって前回も言ったと思うんですけど、ノイズを取ることが目的です。
だからザラザラした部分とかが均されてるわけです。
ただこのガウシアンフィルタの問題点は何か特徴に従って区別して均しているわけではなく、全ての点で同じような均し方をしているため、物体間の境界が不鮮明になる可能性があります。それを解決するためのフィルタがあるようなので、次回はそれを実装しようと思います。