私は私のプロジェクトで 2D FFT を使用してきましたが、2 つの異なる FFT ライブラリを使用して正しい結果を得ることができませんでした。最初は間違った使い方をしていると思っていましたが、MATLAB や Linux の GCC 参照実装と比較すると、私のコンパイラ (MSVC 2013 Express) で何か不吉なことが起こっているようです。
私のテスト ケースは次のとおりです: 256x256 複素数から実際の IFFT へ、10000 に設定された 255 (X、Y 表記では 0,255) の単一ビン。
AMPFFT を使用して、次の 2D 変換を取得します。
FFTW を使用すると、次の 2D 変換が得られます。
ご覧のとおり、AMPFFT バージョンは「ほぼ」正しいですが、この奇妙なサンプルのバンディングがすべて含まれており、FFTW バージョンはいたるところにあり、ランチに出かけています。
2 つの異なるテスト バージョンの出力を取得し、それらを MATLAB (技術的には FFTW を内部で使用するオクターブ) と比較しました。また、GCC を使用する Linux で FFTW に対して同じテスト ケースを実行しました。これは、127 番目の行の一連のテストからのスライスです (ビンの選択では、すべての行が同一である必要があるため、行番号は技術的には問題ではありません)。
この例では、オクターブと Linux の実装は正しい結果を表し、赤い線に従っています (オクターブは黒でプロットされ、Linux は赤でプロットされ、オクターブと完全に一致しました)。MSVC の下の FFTW は青色でプロットされ、AMP FFT 出力はマゼンタでプロットされます。ご覧のとおり、やはり AMPFFT バージョンはほぼ近いように見えますが、この奇妙な高周波リップルが含まれており、MSVC での FFTW は、この奇妙な「パケット化された」外観で混乱しています。
この段階では、Visual Studio に指を向けることしかできませんが、何が起こっているのか、それを修正する方法はわかりません。
ここに私の2つのテストプログラムがあります:
FFTW テスト:
//fftwtest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <fstream>
#include <iostream>
#include <complex>
#include <fftw3.h>
int main(int argc, char** argv)
{
int FFTSIZE = 256;
std::complex<double>* cpxArray;
std::complex<double>* fftOut;
// cpxArray = new std::complex<double>[FFTSIZE * FFTSIZE];
//fftOut = new double[FFTSIZE * FFTSIZE];
fftOut = (std::complex<double>*)fftw_alloc_complex(FFTSIZE*FFTSIZE);
cpxArray = (std::complex<double>*)fftw_alloc_complex(FFTSIZE * FFTSIZE);
for(int i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
cpxArray[255] = std::complex<double>(10000, 0);
fftw_plan p = fftw_plan_dft_2d(FFTSIZE, FFTSIZE, (fftw_complex*)cpxArray, (fftw_complex*)fftOut, FFTW_BACKWARD, FFTW_DESTROY_INPUT | FFTW_ESTIMATE);
fftw_execute(p);
std::ofstream debugDump("debugdumpFFTW.txt");
for(int j = 0; j < FFTSIZE; j++)
{
for(int i = 0; i < FFTSIZE; i++)
{
debugDump << " " << fftOut[j * FFTSIZE + i].real();
}
debugDump << std::endl;
}
debugDump.close();
}
AMPFFT テスト:
//ampffttest.cpp
//2 dimensional complex-to-real inverse FFT test.
//Produces a 256 x 256 real-valued matrix that is loadable by octave/MATLAB
#include <amp_fft.h>
#include <fstream>
#include <iostream>
int main(int argc, char** argv)
{
int FFTSIZE = 256;
std::complex<float>* cpxArray;
float* fftOut;
cpxArray = new std::complex<float>[FFTSIZE * FFTSIZE];
fftOut = new float[FFTSIZE * FFTSIZE];
for(size_t i = 0; i < FFTSIZE * FFTSIZE; i++) cpxArray[i] = 0;
cpxArray[255] = std::complex<float>(10000, 0);
concurrency::extent<2> e(FFTSIZE, FFTSIZE);
std::cout << "E[0]: " << e[0] << " E[1]: " << e[1] << std::endl;
fft<float, 2> m_fft(e);
concurrency::array<float, 2> outpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE));
concurrency::array<std::complex<float>, 2> inpArray(concurrency::extent<2>(FFTSIZE, FFTSIZE), cpxArray);
m_fft.inverse_transform(inpArray, outpArray);
std::vector<float> outVec = outpArray;
std::copy(outVec.begin(), outVec.end(), fftOut);
std::ofstream debugDump("debugdump.txt");
for(int j = 0; j < FFTSIZE; j++)
{
for(int i = 0; i < FFTSIZE; i++)
{
debugDump << " " << fftOut[j * FFTSIZE + i];
}
debugDump << std::endl;
}
}
これらは両方とも、win32 コンソール アプリ用に MSVC 2013 のストック設定でコンパイルされ、FFTW テストも GCC 4.4.7 を使用する Centos 6.4 で実行されました。どちらの FFTW テストも FFTW バージョン 3.3.4 を使用します。
この問題を解決しようとする Visual Studio コンパイラの設定について、少しでも手がかりを持っている人はいますか?