具有特征和FFTW的二维傅里叶变换

时间:2017-03-23 04:54:38

标签: c++ fft eigen fftw

我正在尝试用FFTW进行实值二维傅里叶变换。我的数据存储在动态大小的特征矩阵中。这是我写的包装类:

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()中遇到了一个段错误。我知道我在构造函数中设置了一些错误,我尝试了许多不同的方法,但我似乎无法在此方面取得任何进展。

我尝试过的内容包括:将EMatrix typedef更改为Eigen::ColMajor,将(fftw_complex *) input.data()传递给fftw_plan_dft_2d,使用不同的fftw计划(fftw_plan_dft_r2c_2d)。< / p>

我的C ++(显然)生锈,但在一天结束时,我需要的是在真实值的二维特征矩阵上进行2D FT。提前谢谢。

1 个答案:

答案 0 :(得分:0)

这里的主要问题是没有“实值傅立叶变换”这样的东西。它只是虚构零的一个傅里叶变换,但是零仍然必须存在,正如你从fftw_complex定义所看到的那样:

typedef double fftw_complex[2];

这是有道理的,因为输出可以(并且可能会)具有非零的虚部 输出将具有一些对称属性,即在1D变换的情况下,它将是偶数函数。

因此(fftw_complex *) &input(0)强制转换无效--FFTW预计会传递两倍double个值。

解决方案是将矩阵原始数据与零交错,有很多方法可以做到这一点。几个例子:

  • 您可以将整个矩阵复制到新阵列中,然后再将其传递给FFTW,并在过程中添加零。
  • 您可以在矩阵本身中为零保留空间 - 这样您就可以避免复制,但可能需要进行大量重构:)
  • 我能想到的最好的方法是使用std::complex<double>作为标量。这会有点伤害你对“实值FFT”的注意,但同样首先几乎没有这样的事情。相反,您将能够按原样保留所有实际值操作,并且std::complex的布局将完全符合fftw_complex

这里可能还有其他一些需要考虑的事情,比如存储顺序(FFTW以行 - 主顺序运行,因此特征矩阵应该符合)和线性访问特征矩阵数据的有效性(对我来说似乎没问题)。