2017-03-23 29 views
2

私はFFTWで実数2次元フーリエ変換をしようとしています。私のデータは動的サイズの固有ベクトルに保存されます。EigenとFFTWを使った2次元フーリエ変換

FFT2D.h:

#include <Eigen> 

class FFT2D { 
public: 

    enum FFT_TYPE {FORWARD=0, REVERSE=1}; 
    FFT2D(EMatrix &input, EMatrix &output, FFT_TYPE type_ = FORWARD); 
    ~FFT2D(); 

    void execute(); 

private: 
    EMatrix& input; 
    EMatrix& output; 
    fftw_plan plan; 
    FFT_TYPE type; 
}; 

FFT2D.cpp:

#include "FFT2D.h" 
#include <fftw3.h> 
#include "Defs.h" 


FFT2D::FFT2D(EMatrix &input_, EMatrix &output_, FFT_TYPE type_) 
     : type(type_), input(input_), output(output_) { 

    if (type == FORWARD) 
     plan = fftw_plan_dft_2d((int) input.rows(), (int) input.cols(), 
       (fftw_complex *) &input(0), (fftw_complex *) &output(0), 
       FFTW_FORWARD, FFTW_ESTIMATE); 
    else 
     // placeholder for ifft-2d code, unwritten 
} 


FFT2D::~FFT2D() { 
    fftw_destroy_plan(plan); 
} 

void FFT2D::execute() { 
    fftw_execute(plan); // seg-fault here 
} 

そしてEMatrixの定義:

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> EMatrix; 

問題は、あるここに私が書いたラッパークラスですFFT2D::execute()にsegフォルトが発生していますか?私はコンストラクタで何か間違った設定をしていることを知っています。私はいくつかの方法を試しましたが、これを進めることはできません。私が試した

物事は、次のとおり、Eigen::ColMajorEMatrixのtypedefを変更fftw_plan_dft_2d(fftw_complex *) input.data()を渡し、異なるFFTW計画(fftw_plan_dft_r2c_2d)を使用します。

私のC++は(明らかに)錆びていますが、終わりには二重の実数値2D固有行列で2D FTを実行する必要があります。前もって感謝します。

答えて

0

ここでの大きな問題は、「実数値フーリエ変換」のようなものは存在しないということです。出力ができます(おそらく意志)として

typedef double fftw_complex[2];

これは理にかなっている:それはちょうどフーリエ変換がゼロ虚部で何かの変換ですが、あなたはfftw_complex定義から見ることができるようにゼロはまだ、そこに持っています虚数部がゼロでない。
出力にはいくつかの対称的な特性があります。つまり、1D変換の場合は偶数関数になります。

結果として、(fftw_complex *) &input(0)キャストは実際には機能しません.FFTWは、渡した値の2倍の数のdoubleを期待しています。

解決策は、行列の生データをゼロでインターリーブすることです。これを行うにはいくつかの方法があります。いくつかの例:

  • 行列全体を新しい配列にコピーしてからFFTWに渡し、ゼロを追加することができます。
  • マトリックス自体にゼロのためのスペースを確保することができます。この方法でコピーを避けることができますが、多くのリファクタリングが必要になります:)
  • 私が考えることができる最良の方法は、 std::complex<double>をスカラーとして使用します。これは「実数型FFT」の通知をいくらか傷つけるでしょうが、最初はそのようなことはほとんどありません。代わりに、すべての現実価値操作をそのまま保つことができ、std::complexのレイアウトはfftw_complexに完全に収まります。格納順序(FFTW行優先順に配列上で動作し、その固有値行列は従わなければならない)と固有行列データへのリニアアクセスの妥当性は、(にOKと思われるように、ここで考慮すべきいくつかの他のものがあるかもしれません

私)。

+0

有益な投稿ありがとうございます。私の言葉は駄目だと思うが、FFTへの入力は「実数」、すなわちあなたの言ったような虚数部のすべての零点を持つという意味だった。私の追随する質問は、3番目の箇条書きです。「std :: complex をスカラーとして使う」とはどういう意味ですか?上記のように私が使用している 'EMatrix'型定義にこれをドロップすることはできますか? –

+0

@halp_meええ、typedefで 'double'を' std :: complex 'に置き換えることができます。しかし、すでにゼロをインターリーブしている場合は、そのままこのままにしておく方が簡単です。私があなたが想像上の部分を持っていないと思ったのは、 'input.rows()'と 'input.cols()'をFFTWに渡すことです - これを動作させるには、 – Ap31

関連する問題