2

我一直在我的一个项目中使用 2D FFT,并且无法使用两个不同的 FFT 库获得正确的结果。起初我以为我用错了,但在与 MATLAB 和 Linux GCC 参考实现进行比较后,现在我的编译器(MSVC 2013 express)似乎发生了一些险恶的事情。

我的测试用例如下:256x256 复杂到真正的 IFFT,单个 bin 为 255(X,Y 表示法为 0,255)设置为 10000。

使用 AMFFFT,我得到以下 2D 变换:

损坏的 AMFFFT 示例

使用 FFTW,我得到以下 2D 变换:

损坏的 FFTW 示例

如您所见,AMPFFT 版本有点“几乎”正确,但有一点很奇怪,每个样本都有条带,而 FFTW 版本到处都是,出去吃午饭了。

我获取了两个不同测试版本的输出并将它们与 MATLAB(技术上是 octave,它在引擎盖下使用 FFTW)进行了比较。我还在 Linux 下使用 GCC 为 FFTW 运行了相同的测试用例。这是第 127 行的一组测试中的一个片段(行号在技术上并不重要,因为我选择的 bin 所有行都应该是相同的):

FFT 比较

在这个例子中,octave 和 Linux 实现代表正确的结果并遵循红线(octave 绘制为黑色,Linux 绘制为红色,它与 octave 完全一致)。MSVC 下的 FFTW 绘制为蓝色,AMP FFT 输出绘制为洋红色。正如你所看到的,AMPFFT 版本似乎几乎接近了,但其中有这种奇怪的高频纹波,而 MSVC 下的 FFTW 只是一团糟,有这种奇怪的“打包”外观。

在这个阶段,我只能将矛头指向 Visual Studio,但我不知道发生了什么或如何修复它。

这是我的两个测试程序:

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;
    }
}

这两个都是在 MSVC 2013 上为 win32 控制台应用程序使用股票设置编译的,FFTW 测试也在 Centos 6.4 和 GCC 4.4.7 下运行。两个 FFTW 测试都使用 FFTW 版本 3.3.4,并且同时测试了复杂到真实和复杂到复杂的计划(结果相同)。

有没有人对我可以尝试解决这个问题的 Visual Studio 编译器设置有丝毫线索?

4

1 回答 1

1

查看蓝色的 MSVC FFTW 输出,它似乎是多个正弦的乘积。也就是说,有一个周期为 64 左右的正弦,一个周期为 4 的正弦,并且可能还有另一个具有相似频率的正弦来产生节拍。

这基本上意味着 MSVC 版本至少有两个非零输入。我怀疑原因是类型转换,因为您fftw_complex通过类型编写对象std::complex<double>

于 2014-06-12T08:14:17.857 回答