離散フーリエ変換の直流成分を中心に持ってくる方法
普通の離散フーリエ変換は直流成分は角にくるようです。知らなかった。。。これのデバッグに8時間以上費やしたhoshimiですが、ここではフーリエ変換で中心に持ってくる方法について説明(自分用)したいと思います。
ちなみに今回はfftwというフーリエ変換ライブラリを使ってます。詳しくはhttp://d.hatena.ne.jp/hoshimi_etoile/20070802を参照ください。
画像をdouble matrix;の行列としたとき、直流成分を中心に持ってくるためにはsign = 1の時に複素成分を負をかけてフーリエ変換後もう一度sign = 1についてもう一度複素成分に負をかければOKです。
といってもわかりにくいと思うのでサンプル
#include<fftw3.h> #include<math.h> void fft2d(double* matrix){ //数値配列の宣言 fftw_complex *in,*out; //フーリエ変換設定の宣言 fftw_plan p; //数値配列用のメモリの確保 in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nx * ny); out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nx * ny); //入力に値を挿入 for(int i = 0; i < width;i++){ for(int j=0; j < height;j++){ in[i*height + j][0] = matrix[i*height + j]; in[i*height + j][1] = 0; //直流成分を中心にするなら if( (i+j) % 2 == 1){ in[i*height + j][0] *= -1; in[i*height + j][1] *= -1; } } } //フーリエ変換の設定 p = fftw_plan_dft_2d(nx,ny,in,out,FFTW_FORWARD,FFTW_ESTIMATE); //フーリエ変換の実行 fftw_execute(p); for(int i = 0; i < width;i++){ for(int j=0; j < height;j++){ //直流成分を中心にするなら。 if( (i+j) % 2 == 1){ out[i*height + j][0] *= -1; out[i*height + j][1] *= -1; } matrix = out[i*height + j][0] / ::sqrt(width*height); } } //メモリの解放 fftw_destroy_plan(p); fftw_free(in); fftw_free(out); }
こんな関数を作れば直流成分が中心に来るようです。
ちなみにこの証明は・・・勉強しておきます。
フーリエ変換そろそろ真面目に勉強しようかな。疎かにしてました。