目次
今回は前回に引き続き、空間フィルタリングを行いました。ノイズ処理に多く用いられる、周波数領域でのフィルタリングは、ローパスフィルタ・ハイパスフィルタ・バンドパスフィルタなどで知られていますが、これらは特定の周波数をカットして画像内の情報を判別しやすくしてくれます。pythonで実装していきます。
画像のフーリエ変換
フーリエ変換とは、数学的操作によって距離をもつ空間である空間領域から信号がどのような周波数成分を持っているか表現する空間周波数領域へのシフトのことです。空間領域から空間周波数領域に画像情報をシフトすることで、画像内の特定の周波数を扱えるようになります。次の画像をフーリエ変換してみます。
フーリエ変換前の画像(img01.png)
まず画像を白黒表示で得ます。
gray = cv2.imread("img01.png",0) plt.imshow(gray) plt.gray()
img01.png(白黒画像)
白黒画像が得られたので、早速フーリエ変換していきます。
mg_fft = np.fft.fft2(gray) img_fft2 = np.fft.fftshift(img_fft)
plt.gray() plt.imshow(np.abs(img_fft2))
フーリエ変換後の画像(img01.png)
上絵のようにフーリエ変換ができました。これで画像が空間領域から空間周波数領域へとシフトしたので、画像の周波数を取り扱えるようになります。
様々な空間周波数フィルタの紹介
1. ハイパスフィルタ
ハイパスフィルタとは、遮断周波数より高い周波数を減衰させることなく低い周波数のみをカットするフィルタです。高周波成分のみが残ることで、画像のエッジ部分が強調されより画像がシャープになります。
2. ローパスフィルタ
ハイパスフィルタとは真逆に、ローパスフィルタは遮断周波数より低い周波数は減衰させることなく高い周波数のみをカットします。これをかけてみると平滑化されぼんやりした画像を得ることができます。前回説明した平均化フィルタは、フーリエ変換するとローアスフィルタの性質を持つことがわかります。
3. バンドパスフィルタ
画像に含まれる周波数のうち、中間の周波数のみ残すフィルタをバンドパスフィルタと呼びます。実際にこれをかけてみると、ハイパスフィルタをかけたようにエッジが強調され、ローパスフィルタをかけたようにエッジの周りがぼんやりするような画像を得ることができます。
pythonによるフィルタリングの実装
1. ローパスフィルタ
先ほどの画像(img01.png)にローパスフィルタをかけていきます。 もう一度画像を白黒表示させます。
gray = cv2.imread("img01.png",0) plt.imshow(gray) plt.gray()
img01.png(白黒表示)
上絵のように白黒表示ができました。ローパスフィルタをかけれるように、フーリエ変換を行い画像を空間領域から空間周波数領域へとシフトさせます。
img_fft = np.fft.fft2(gray) img_fft2 = np.fft.fftshift(img_fft)
先程と同様、画像をフーリエ変換させました。 次はローパスフィルタを設計していきます。今回は半径10の円の内部のみ1、そのほかは0となるようなフィルタをかけていきます。
size = gray.shape mask = np.zeros(size) length = size[0] centery = size[0]/2 R = 10 for x in range(0,length): for y in range(0,length): if (x- centery)**2 +(y- centery)**2 <R**2: mask[x,y]=1
それでは、このフィルタを画像にかけていきます。
img_fft2_mask = img_fft2*mask img_fft2_mask= np.fft.fftshift(img_fft2_mask) ifimage = np.fft.ifft2(img_fft2_mask) ifimage = ifimage.real Image.fromarray(np.uint8(ifimage)).show()
ローパスフィルタをかけたimg01.png
上絵のようにローパスフィルタをかけた画像を得ることができました。先述通り、平滑化されてぼんやりとした画像が得られます。これらのコードを図式化すると下絵のようになります。
2. ハイパスフィルタ
次にハイパスフィルタをかけていきます。ローパスフィルタと同様にフーリエ変換した画像にデザインしたフィルタをかけます。フーリエ変換までの過程は省略して、フィルタの設計から書きます。
size = gray.shape mask = np.zeros(size) length = size[0] centery = size[0]/2 R = 10 for x in range(0,length): for y in range(0,length): if (x- centery)**2 +(y- centery)**2 >R**2: mask[x,y]=1
これをフーリエ変換した先ほどの画像にかけていきます。
img_fft2_mask = img_fft2*mask img_fft2_mask= np.fft.fftshift(img_fft2_mask) ifimage = np.fft.ifft2(img_fft2_mask) ifimage = ifimage.real Image.fromarray(np.uint8(ifimage)).show()
これによって、ハイパスフィルタをかけた画像を得ることができます。
ハイパスフィルタをかけたimg01.png
先述通り、エッジを抽出したような画像を得ることができました。この流れを図式化すると下絵のようになります。
ハイパスフィルタをかける流れ
円の直径を変えたり、円の内部、外部でかける数字を変えたりすることで様々なフィルタを作り出すことができます。皆さんもぜひ、周波数領域のフィルタリングで遊んでみてください。