画像フィルター(演習5)
~/image/e5 で演習
FFT によるフィルター
- サンプル画像(1) をダウンロード
- 次のプログラム(e501.py) で FFT による LPF (Low-Pass Filter) を試してみる
- できたら、プログラムを修正して、結果の画像を s501.pgm に保存
e501.py
# -*- coding: utf-8 -*- import Image import Numeric import FFT # 画像の読み込みと FFT im = Image.open('e5sample1.pgm') f = Numeric.array(im.getdata()) L = im.size[0] f.shape = (L,L) F = FFT.fft2d(f) # 波数空間でのフィルターの作成 U = 1./4 UL = int(L*U) G = Numeric.array([1.0]*(UL/2)+[0.0]*(L-UL+1)+[1.0]*(UL/2-1)) G = Numeric.outerproduct(G,G) # フィルターの適用と逆FFT F = F * G f = FFT.inverse_fft2d(F) # 画像データに変換 fimg = Image.new('L', (L,L)) d = [int(f[x][y].real) for x in range(L) for y in range(L)] fimg.putdata(d) fimg.show()
カットオフをゆるく
- 前回の1次元 FFT プログラム で、コメントアウトされている、「ゆるやかなカットオフを持つフィルター関数」を参考に e501.py を修正し、e502.py に保存
- できたら、結果の画像も s502.pgm に保存
畳み込みフィルター
- Python Image Library には、ImageFilter モジュールに(限定的ではあるが)畳み込みフィルターを作成して適用する機能が提供されている
- 詳しくは ImageFilter のマニュアル を参照
畳み込みフィルターによる LPF
- 次のプログラム(e503.py) では 5x5 の行列に全て 1 が入っている。つまり、5x5 の窓を使った走行平均の計算を行う
- 試してできたら、結果の画像を s503.pgm に保存
e503.py
import Image import ImageFilter img = Image.open('e5sample1.pgm') # 5x5, all 1 flt = ImageFilter.Kernel((5,5), [1]*25) imgx = img.filter(flt) imgx.show()
畳み込みフィルターによる HPF
- HPF (High-Pass Filter) はピクセル値から LPF による結果を差し引くようにすればよい
- 次のプログラム(e504.py) のようなフィルターを使えばよい
- LPFの重みが 5x5=25 なので、中心の値は 25-1=24 となっている。また、HPF の計算結果は負になることもあることを考慮して 128 のオフセットを加えてある
e504.py
import Image import ImageFilter img = Image.open('e5sample1.pgm') # HPF (1-5x5LPF) flist = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] flt = ImageFilter.Kernel((5,5), flist, offset=128) imgx = img.filter(flt) imgx.show()
LPF/HPF 以外のフィルター
- たとえば縦の線構造を調べたいときなど、
|-1 0 1| |-2 0 2| |-1 0 1|
- の 3x3 の畳み込みフィルターを適用する
- これは「微分」を行っていることにも注目
- filter() 関数の自動スケールを抑制するため scale=1 とし、またオフセットも与えるとよい
- 次のプログラム例(e505.py) では
- 別のサンプル画像 を使用する
- これは Sobel のエッジ検出 に使われている
e505.py
import Image import ImageFilter img = Image.open('e5sample2.pgm') # differrentiate flist = [-1, 0, 1, -2, 0, 2, -1, 0, 1] flt = ImageFilter.Kernel((3,3), flist, scale=1, offset=128) imgx = img.filter(flt) imgx.show()
その他の(非線形)フィルター
- ImageFilter にはその他にも、よく使われるフィルターが用意してある
- オンラインマニュアル を参考に、いくつか試してみよう
- 次の例はエッジ検出フィルター (FIND_EDGES) を利用するものである
e506.py
import Image import ImageFilter img = Image.open('e5sample2.pgm') imgx = img.filter(ImageFilter.FIND_EDGES) imgx.show()
発展課題
- e503.py と同じ結果を得るのに、ImageFilter を使わずに getpixel(), putpixel() を使ったプログラムを作成してみよう。どのくらいの実行時間が必要か試して見なさい。(e507.py)
出席確認
- 本日作成した 最後のプログラム をメールの本文に記入して、菊地・画像処理論用 に送信。本文の最初に感想等入れるも可。