如何根据从fftw_dft_r2c生成的结果确定原始矩阵的大小?

时间:2019-01-13 13:17:23

标签: c++ fft fftw

对于fftw3,如果对大小为[m x n]的矩阵A执行Reals 2D FFT,则会得到大小为[m x(n / 2 + 1)]的复数矩阵B。如果我们只有B,如何确定A的形状,即A的行和列?

对于一维FFT问题,我知道在fft上以奇数大小执行vector会导致复数向量以实数结尾,即vector_fft[-1].imag() == 0。这可能是确定原始vector大小的关键。

但是,对于2D FFT,问题似乎更加复杂,对于2D FFT编码阵列没有这种明显的功能。我阅读了fftw3的手册,但仍然对fftw如何压缩结果矩阵中的共轭数据感到困惑。

#include <iostream>
#include <Eigen/Eigen>
#include <fftw3.h>
#include <complex>

#define EIGEN_DEFAULT_TO_ROW_MAJOR

using namespace Eigen;

using Cmpl  = std::complex<double>;

using Matd  = Matrix<double, Dynamic, Dynamic, RowMajor>;
using Vecd  = Matrix<double,       1, Dynamic, RowMajor>;
using Veccd = Matrix<  Cmpl,       1, Dynamic, RowMajor>;
using Matcd = Matrix<  Cmpl, Dynamic, Dynamic, RowMajor>;

Veccd fft_1d_r2c(const Vecd& in) {
  Veccd out(in.size() / 2 + 1);
  auto plan = fftw_plan_dft_r2c_1d(in.size(),
      (double*)in.data(), (fftw_complex*)out.data(), FFTW_ESTIMATE);
  fftw_execute(plan);
  fftw_destroy_plan(plan);
  return out;
}

Veccd fft_1d_c2c(const Veccd& in) {
  Veccd out(in.size());
  auto plan = fftw_plan_dft_1d(in.size(),
      (fftw_complex*)in.data(), (fftw_complex*)out.data(),
      FFTW_FORWARD, FFTW_ESTIMATE);
  fftw_execute(plan);
  fftw_destroy_plan(plan);
  return out;
}

Matcd fft_2d_r2c(const Matd& in) {
  Matcd out(in.rows(), in.cols() / 2 + 1);
  auto plan = fftw_plan_dft_r2c_2d(in.rows(), in.cols(),
      (double*)in.data(), (fftw_complex*)out.data(), FFTW_ESTIMATE);
  fftw_execute(plan);
  fftw_destroy_plan(plan);
  return out;
}

Matcd fft_2d_c2c(const Matcd& in) {
  Matcd out(in.rows(), in.cols());
  auto plan = fftw_plan_dft_2d(in.rows(), in.cols(),
      (fftw_complex*)in.data(), (fftw_complex*)out.data(),
      FFTW_FORWARD, FFTW_ESTIMATE);
  fftw_execute(plan);
  fftw_destroy_plan(plan);
  return out;
}

void test_1d(const int size) {
  Vecd vec{size};
  vec.setRandom();
  Veccd vec_fft = fft_1d_c2c(vec.cast<Cmpl>());
  Veccd vec_rfft = fft_1d_r2c(vec);
  std::cout << "Original Vector: \n" << vec << std::endl << std::endl
    << "fftw_r2c of vec: \n" << vec_rfft << std::endl << std::endl;
}

void test_2d(const int rows, const int cols) {
  Matd mat{rows, cols};
  mat.setRandom();

  Matcd mat_rfft = fft_2d_r2c(mat);
  Matcd mat_fft = fft_2d_c2c(mat.cast<Cmpl>());
  std::cout << "Original Matrix: \n" << mat << std::endl << std::endl
    << "fftw_r2c of mat: \n" << mat_rfft << std::endl << std::endl;

  std::cout << "fftw_c2c of mat: \n" << mat_fft << std::endl;
}

int main(int argc, char* argv[]) {
  std::cout << "For 1D fft problems" << std::endl;
  test_1d(9);
  test_1d(10);

  std::cout << "For 2D fft problems" << std::endl;
  test_2d(6, 5);
  test_2d(6, 4);
  return 0;
}

对于fftw_r2c返回的矩阵,如何确定原始矩阵的形状?

0 个答案:

没有答案