Eigen FFT library
Asked Answered
G

1

0

I am trying to use Eigen unsupported FFT library using FFTW backend. Specifically I am want to do a 2D FFT. Here's my code :

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

}

I have 2 problems :

  • First, I get a segmentation fault when using this code on some matrix. This error doesn't happen for all matrixes. I guess it's related to an alignment error. I use the functions in the following way :

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

where mat can be any matrix. Funnily, the code plants only when I compute the FFT over the 2nd dimension, never on the first one. This doesn't happen with kissFFT backend.

  • Second I don't get the same result as Matlab (that uses FFTW), when the function works. Eg :

Input Matrix :

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

Eigen gives :

[           (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 gives :

   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 

Only the central part is the same.

Any help would be welcome.

Gawlas answered 5/4, 2018 at 16:5 Comment(4)
Please provide a complete minimal reproducible example (how do you set up matFloat?) Also, is there a reason to pass matIn and matOut by pointer and not by reference?Melodymeloid
There is no specific reason that I chose to use pointer instead of reference.Gawlas
The reason I did not provide the initialization of matFloat is that I use an external library to set it up. I set it up to the Lena image with float RGB to Gray conversion. I believe this library is not a reason for failure as it worked well with kissFFT backend.Gawlas
I filed a bug for that: eigen.tuxfamily.org/bz/show_bug.cgi?id=1537 -- this might actually also be the reason of your occasional crashes. But this is hard to say without an MCVE.Melodymeloid
M
0

I failed to activate EIGEN_FFTW_DEFAULT in my first solution, activating it reveals an error in the fftw-support implementation of Eigen. The following works:

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

I get this output:

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)

Which is the same as your Matlab result.

N.B.: FFTW seems to support 2D real->complex FFT natively (without using individual FFTs). This is likely more efficient.

fftwf_plan fftwf_plan_dft_r2c_2d(int n0, int n1,               
                                 float *in, fftwf_complex *out, unsigned flags);
Melodymeloid answered 6/4, 2018 at 13:22 Comment(1)
Thanks for this solution. In the end I decided to use fftw's native 2D FFT.Gawlas

© 2022 - 2024 — McMap. All rights reserved.