【问题标题】:Eigen FFT library特征 FFT 库
【发布时间】:2026-01-19 13:55:02
【问题描述】:

我正在尝试使用 FFTW 后端使用 Eigen 不受支持的 FFT 库。具体来说,我想做一个 2D FFT。这是我的代码:

void fft2(Eigen::MatrixXf * matIn,Eigen::MatrixXcf * matOut)
{
    const int nRows = matIn->rows();
    const int nCols = matIn->cols();

    Eigen::FFT< float > fft;

    for (int k = 0; k < nRows; ++k) {
        Eigen::VectorXcf tmpOut(nRows);
        fft.fwd(tmpOut, matIn->row(k));
        matOut->row(k) = tmpOut;
    }

    for (int k = 0; k < nCols; ++k) {
        Eigen::VectorXcf tmpOut(nCols);
        fft.fwd(tmpOut, matOut->col(k));
        matOut->col(k) = tmpOut;
    }

}

我有两个问题:

  • 首先,在某些矩阵上使用此代码时出现分段错误。并非所有矩阵都会发生此错误。我猜这与对齐错误有关。我通过以下方式使用这些功能:

    特征::MatrixXcf matFFT(mat.rows(),mat.cols()); fft2(&matFloat,&matFFT);

其中 mat 可以是任何矩阵。有趣的是,代码仅在我计算第二维上的 FFT 时才出现,而不是在第一维上。 KissFFT 后端不会发生这种情况。

  • 其次,当函数工作时,我没有得到与 Matlab(使用 FFTW)相同的结果。例如:

输入矩阵:

[2, 1, 2]
[3, 2, 1]
[1, 2, 3]

特征给出:

[           (0,5),    (0.5,0.86603),          (0,0.5)]
[  (-4.3301,-2.5),     (-1,-1.7321), (0.31699,-1.549)]
[ (-1.5,-0.86603),       (2,3.4641),       (2,3.4641)]

Matlab 给出:

   17 +          0i          0.5 +    0.86603i          0.5 -    0.86603i
   -1 +          0i           -1 -     1.7321i            2 -     3.4641i
   -1 +          0i            2 +     3.4641i           -1 +     1.7321i 

只有中间部分是一样的。

欢迎任何帮助。

【问题讨论】:

  • 请提供完整的minimal reproducible example(如何设置matFloat?)另外,是否有理由通过指针而不是引用传递matInmatOut?跨度>
  • 我没有特别的理由选择使用指针而不是引用。
  • 我没有提供matFloat初始化的原因是我使用了一个外部库来设置它。我将它设置为具有浮点 RGB 到灰色转换的 Lena 图像。我相信这个库不是失败的原因,因为它与 KissFFT 后端配合得很好。
  • 我为此提交了一个错误:eigen.tuxfamily.org/bz/show_bug.cgi?id=1537——这实际上也可能是您偶尔崩溃的原因。但如果没有 MCVE,这很难说。

标签: image-processing fft eigen fftw


【解决方案1】:

我未能在我的第一个解决方案中激活 EIGEN_FFTW_DEFAULT,激活它会显示 Eigen 的 fftw-support 实现中存在错误。以下作品:

#define EIGEN_FFTW_DEFAULT
#include <iostream>
#include <unsupported/Eigen/FFT>

int main(int argc, char *argv[])
{
    Eigen::MatrixXf A(3,3);
    A << 2,1,2,  3,2,1,  1,2,3;
    const int nRows = A.rows();
    const int nCols = A.cols();

    std::cout << A << "\n\n";

    Eigen::MatrixXcf B(3,3);

    Eigen::FFT< float > fft;

    for (int k = 0; k < nRows; ++k) {
        Eigen::VectorXcf tmpOut(nRows);
        fft.fwd(tmpOut, A.row(k));
        B.row(k) = tmpOut;
    }
    std::cout << B << "\n\n";
    Eigen::FFT< float > fft2;  // Workaround: Using the same FFT object for a real and a complex FFT seems not to work with FFTW
    for (int k = 0; k < nCols; ++k) {
        Eigen::VectorXcf tmpOut(nCols);
        fft2.fwd(tmpOut, B.col(k));
        B.col(k) = tmpOut;
    }
    std::cout << B << '\n';
}

我得到这个输出:

2 1 2
3 2 1
1 2 3

     (17,0)  (0.5,0.866025) (0.5,-0.866025)
     (-1,0)   (-1,-1.73205)     (2,-3.4641)
     (-1,0)      (2,3.4641)    (-1,1.73205)

这与您的 Matlab 结果相同。

注意:FFTW 似乎本机支持 2D 实数->复数 FFT(不使用单独的 FFT)。这可能更有效。

fftwf_plan fftwf_plan_dft_r2c_2d(int n0, int n1,               
                                 float *in, fftwf_complex *out, unsigned flags);

【讨论】:

  • 感谢您的解决方案。最后我决定使用 fftw 原生的 2D FFT。