Как определить исходный размер матрицы из результата, сгенерированного из `fftw_dft_r2c`? - PullRequest
0 голосов
/ 13 января 2019

Для fftw3, если вы выполните Reals 2D FFT для матрицы A с размером [m x n], вы получите комплексную матрицу B с размером [m x (n / 2 + 1)]. Если у нас есть только B, как определить форму A, то есть строки и столбцы A?

Для задач 1D БПФ я узнаю, что выполнение fft на vector с нечетным размером приводит к сложному вектору, который заканчивается действительным числом, то есть vector_fft[-1].imag() == 0. И это может быть ключом для определения оригинального vector размера.

Тем не менее, для 2D FFT проблема кажется более сложной, такой явной особенности для 2D FFT-ed-матрицы нет. Я прочитал руководство по 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, как определить форму исходной матрицы?

...