* octave で画像処理 - 2 次元 FFT [#sde7f80e]

octave での画像の読み書きができたところで,カッ飛ばしていきます.

** 2次元 FFT [#p1f8fda5]

ここで 2 次元 FFT について説明します.

#ref(2DFFT.png,center)

まず,元の画像を横方向に1ラインずつ抜きだし,(1次元の)FFT をかけます.
それらを寄せ集め,今度は縦方向に1ラインずつ抜きだし,FFT をかけ,寄せ集めます.
この結果が 2 次元 FFT となります.

なお,横→縦と1次元 FFT を実行しても縦→横と1次元 FFT を実行しても同じ結果になることが知られています.

2 次元逆 FFT も同様に定義されます.
こちらでも「横→縦」の逆変換でも「縦→横」の逆変換でも同じ結果になることが知られています.

** octave では [#g2c8ef27]

octave では fft2(), ifft2() という関数で2次元 FFT・2次元逆 FFT を行うことができます.

 octave:119> [ x, m, a ] = imread ( 'DSCF0135.JPG' );  # 画像ファイルを読み込み
 octave:120> y = fft2 ( x );                           # 2次元 FFT の実行
 octave:121> xx = ifft2 ( y );                         # 2次元逆 FFT の実行

** 実際に 2 次元 FFT をやってみる [#na5f6d02]

理屈をグダグダ言っててもつまらないので,実際にやってみます.
画像はこんなやつを使ってみました.
#ref(DSCF0135.JPG,center,50%)

まずは画像ファイルを読み込んで

 octave:26> [ x, m, a ] = imread ( 'DSCF0135.JPG' );

2 次元 FFT を実行します.

 octave:27> y = fft2(x);

FFT では複素数で波の位相を表していますが,そのままでは表示に無理があるので,絶対値 ( √(Re^2 + Im^2) ) で画像にして表示してみます.

 octave:28> imshow ( abs(y));

む,画像が真っ白だ.値が大きすぎてサチってるようです.
値を適当にスケーリングします.
いろいろ試行錯誤したら,100000 で割ると,何となくいい感じのようです.

 octave:29> imshow ( abs(y)/100000);

こんな感じの画像が表示されます.
#ref(fft2.jpg,center,50%)

左上 1/4 が周波数成分(の大きさ)で,右上,左下,右下には横方向・縦方向のエイリアジングが現れています.
1 次元の FFT のときのように,これらは負の周波数の成分,という見かたもできます.

というわけで,十文字に4等分して,上下左右を入れ替えてみます.
が,そういう関数が見つからなかったので,適当に作ってみました.
swap2.m という名前で保存すると,octave 上から swap2 (x) のように呼び出すことができます.

 function y = swap2 ( x )
   r = rows(x);
   c = columns(x);
   r2 = floor(r/2);
   c2 = floor(c/2);
 
   y = [x(r2+1:r, c2+1:c, : ) x(r2+1:r, 1:c2, : );
        x(1:r2,   c2+1:c, : ) x(1:r2,   1:c2, : ) ];
 endfunction

使ってみます.

 octave:33> imshow ( abs(swap2(y))/100000 );

こんな感じの画像が表示されます.
画像の中央が低い周波数成分で,端に行くほど高い周波数成分を表しています.

#ref(fft2_swap.jpg,center,50%)

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS