ディジタル画像処理~pythonによる空間フィルタリングpart2~ 

今回はフーリエ変換を用いた周波数領域でのフィルタリングをpythonで行ってみました。

目次

今回は前回に引き続き、空間フィルタリングを行いました。ノイズ処理に多く用いられる、周波数領域でのフィルタリングは、ローパスフィルタ・ハイパスフィルタ・バンドパスフィルタなどで知られていますが、これらは特定の周波数をカットして画像内の情報を判別しやすくしてくれます。pythonで実装していきます。

画像のフーリエ変換

フーリエ変換とは、数学的操作によって距離をもつ空間である空間領域から信号がどのような周波数成分を持っているか表現する空間周波数領域へのシフトのことです。空間領域から空間周波数領域に画像情報をシフトすることで、画像内の特定の周波数を扱えるようになります。次の画像をフーリエ変換してみます。

フーリエ変換前の画像(img01.png)

まず画像を白黒表示で得ます。

gray = cv2.imread("img01.png",0) 
plt.imshow(gray)           
plt.gray()
show.picture(white&black).py

img01.png(白黒画像)

白黒画像が得られたので、早速フーリエ変換していきます。

mg_fft = np.fft.fft2(gray)
img_fft2 = np.fft.fftshift(img_fft)
Fourier transform.py
plt.gray()
plt.imshow(np.abs(img_fft2))
Show picture Fourier transformed.py

フーリエ変換後の画像(img01.png)

上絵のようにフーリエ変換ができました。これで画像が空間領域から空間周波数領域へとシフトしたので、画像の周波数を取り扱えるようになります。

様々な空間周波数フィルタの紹介

1. ハイパスフィルタ

ハイパスフィルタとは、遮断周波数より高い周波数を減衰させることなく低い周波数のみをカットするフィルタです。高周波成分のみが残ることで、画像のエッジ部分が強調されより画像がシャープになります。

2. ローパスフィルタ

ハイパスフィルタとは真逆に、ローパスフィルタは遮断周波数より低い周波数は減衰させることなく高い周波数のみをカットします。これをかけてみると平滑化されぼんやりした画像を得ることができます。前回説明した平均化フィルタは、フーリエ変換するとローアスフィルタの性質を持つことがわかります。

3. バンドパスフィルタ

画像に含まれる周波数のうち、中間の周波数のみ残すフィルタをバンドパスフィルタと呼びます。実際にこれをかけてみると、ハイパスフィルタをかけたようにエッジが強調され、ローパスフィルタをかけたようにエッジの周りがぼんやりするような画像を得ることができます。

pythonによるフィルタリングの実装

1. ローパスフィルタ

先ほどの画像(img01.png)にローパスフィルタをかけていきます。 もう一度画像を白黒表示させます。

gray = cv2.imread("img01.png",0)  
plt.imshow(gray)              
plt.gray()
Show.picture(black&white).py

img01.png(白黒表示)

上絵のように白黒表示ができました。ローパスフィルタをかけれるように、フーリエ変換を行い画像を空間領域から空間周波数領域へとシフトさせます。

img_fft = np.fft.fft2(gray)
img_fft2 = np.fft.fftshift(img_fft)
Fourier transform.py

先程と同様、画像をフーリエ変換させました。 次はローパスフィルタを設計していきます。今回は半径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
Design filter.py

それでは、このフィルタを画像にかけていきます。

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()
Apply filter.py

ローパスフィルタをかけた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
Design filter.py

これをフーリエ変換した先ほどの画像にかけていきます。

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()
Apply filter.py

これによって、ハイパスフィルタをかけた画像を得ることができます。

ハイパスフィルタをかけたimg01.png

先述通り、エッジを抽出したような画像を得ることができました。この流れを図式化すると下絵のようになります。

ハイパスフィルタをかける流れ

円の直径を変えたり、円の内部、外部でかける数字を変えたりすることで様々なフィルタを作り出すことができます。皆さんもぜひ、周波数領域のフィルタリングで遊んでみてください。