画像フィルター(演習5)

~/image/e5 で演習

FFT によるフィルター

  • サンプル画像(1) をダウンロード
  • 次のプログラム(e501.py) で FFT による LPF (Low-Pass Filter) を試してみる
  • できたら、プログラムを修正して、結果の画像を s501.pgm に保存

e501.py

# -*- coding: utf-8 -*-
import Image
import scipy
import scipy.fftpack as fft
 
# 画像の読み込みと FFT
im = Image.open('e5sample1.pgm')
f  = scipy.array(im.getdata())
L = im.size[0]
f.shape = (L,L)
F = fft.fft2(f)
 
# 波数空間でのフィルターの作成
U = 1./4
UL = int(L*U)
G = scipy.array([1.0]*(UL/2)+[0.0]*(L-UL+1)+[1.0]*(UL/2-1))
G = scipy.outer(G,G)
 
# フィルターの適用と逆FFT
F = F * G
f = fft.ifft2(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)

出席確認

  • 本日作成した 最後のプログラム をメールの本文に記入して、菊地・画像処理論用 に送信。本文の最初に感想等入れるも可。