FrontPage  ページ一覧  検索  更新履歴  RSS  ログイン

FFT

手軽に使う方法

FFTを実行するにはFFT2クラスを使用します。まず手軽にFFTを使用するためには、

  1. 解析・フィルタしたい原画
  2. 結果保存用Imageを用意すれば、
  3. 関数1つでスペクトル画像やフィルタ済み画像を得ることができます。

これらの関数群では、スペクトル・フィルタともに振幅比例のデータとして扱います。

画像のスペクトルを得る

getSpectrum(Image/Matrix &source, Image &result, double gamma)
解析したい画像、解析結果の出力先、および解析結果のガンマ値を指定します。ガンマ値については、FFT解析を行うとピーク成分以外はかなりコントラストが落ちるため、Imageに解析結果を出力する場合は0.2程度の値を指定すると見やすく表示できます。
#include <psychlops.h>
using namespace Psychlops;

void psychlops_main() {
  Canvas cnvs(1024, 768, Canvas::window);

  Image source("test.png");
  Image result;
  FFT2::getSpectrum(source, result, 0.2);

  source.centering().shift(-300, 0).draw();
  result.centering().shift( 300, 0).draw();
  cnvs.flip();

  while(!Input::get(Keyboard::esc)) {
  }
}

画像にフィルタをかける

filterImage(Image/Matrix &source, Image &result, double lowCutOff_cpi, double highCutOff_cpi, double slope)
解析したい画像、解析結果の出力先、低い側のカットオフ周波数、高い側のカットオフ周波数、および対数軸上の傾きを指定します。カットオフの単位はCPIです。2なら画像2周期分です。(確認用サンプルコード
#include <psychlops.h>
using namespace Psychlops;

void psychlops_main() {
  Canvas cnvs(1024, 768, Canvas::window);

  Image source("test.png");
  Image result;
  FFT2::filterImage(source, result, 10, 10, 1.0);

  source.centering().shift(-300, 0).draw();
  result.centering().shift( 300, 0).draw();
  cnvs.flip();

  while(!Input::get(Keyboard::esc)) {
  }
}

フィルタを自作する

奇数と偶数の場合でDC座標が異なりますが、これを一意に得るにはoriginFor関数を使用します。

詳細な構造

上記の関数は内部にいくつかのステップがあります。たとえばフィルタリング関数の場合は、

  1. 画像データから複素数画像空間への変換
  2. FFT
  3. フィルタの作成
  4. 周波数空間でのフィルタの適用
  5. FFT
  6. FFT後の複素数画像空間から画像への変換

というステップを持ちます。FFTW2Dクラスではこれらのステップを逐次実行できる関数があります。たとえば、上記フィルタリング関数をステップごとに分解すると以下のようなコードになります。

#include <psychlops.h>
using namespace Psychlops;

void psychlops_main() {
  Canvas cnvs(1024, 768, Canvas::window);

  Image source("test.png");
  Image result;
  FFT2 tmp(source);
  Matrix carnel = FFT2::makeFilter(source.getHeight(), source.getWidth(), 10, 10, 1.0);
  tmp.fft();
  tmp.filtering(carnel);
  tmp.ifft();
  tmp.getImage(result);

  source.centering().shift(-300, 0).draw();
  result.centering().shift( 300, 0).draw();
  cnvs.flip();

  while(!Input::get(Keyboard::esc)) {
  }
}

これ以降は、個々のステップの関数について説明します。

初期化(複素数データ構造への変換)

幅と高さを指定して作るか、元画像をImageMatrixで入力することができます。

FFT2(int width, int height);
FFT2(const Image &source);
FFT2(const Matrix &source);
FFT2(const Matrix &real, const Matrix &imag);
void set(int wid, int hei);
void set(const Image &source);
void set(const Matrix &source);
void set(const Matrix &real, const Matrix &imag);

要素改変

画像空間に対しては、Imageに対して行うのと同じようにアクセスすることができます。

double pix(int x, int y, double l);
double pix(int x, int y, const Color &c);
double getPix(int x, int y);

周波数空間側に対しては、現状DC成分のみアクセスできます。

double getDC();
double setDC(double l);

FFT/iFFTの実行

FFT2クラスの保持データを使ってFFT/IFFTを実行します。

void fft();
void ifft();

フィルタリング関数

filtering
フィルタを具体的に記述したMatrixか標準フィルタ関数の引数を指定し、周波数空間でフィルタリングを行います。単に周波数空間でフィルタを乗算するだけなので、フィルタ前にfft()する必要があり、フィルタ後の画像を得るにはこのあとifft()する必要があります。
void filtering(const Matrix &filter);
void filtering(double cutoff_lambda1, double cutoff_lambda2, double slope);

読み出し専用可視化ツール

複素数画像空間のデータをImageMatrixに落として可視化するには以下の関数を用います。

void getImage(Image &target);
void getImage(Matrix &real);
void getImage(Matrix &real, Matrix &imag);

周波数空間のデータを得るには以下の関数を用います。

void getSpectrum(Image &target, double gamma);
void getSpectrum(Matrix &absolute, double gamma = 1.0);
void getSpectrum(Matrix &real, Matrix &imag);

保持データ

FFT2クラスは、FFTWが生で扱うことのできる複素数データ配列を保持すします。この方法では要素への直接アクセスにアルゴリズムへの理解が必要となる欠点がありますが、ひきかえ速度的な利点などが望めます。

更新日時:2012/02/03 15:18:49
キーワード:[FFT]
参照:[(逆引き) なんでも]