fftw3/gsl庫中傅里葉變換/反傅里葉變換函數和Matlab中的fft/ifft的對應關係

先分析一維度的

一、fftw_plan_dft_1d

正變換:

 fftw_complex *in = fftw_malloc ( sizeof ( fftw_complex ) * n );

 fftw_complex *out = fftw_malloc ( sizeof ( fftw_complex ) * n );

plan_forward = fftw_plan_dft_1d ( n, in, out, FFTW_FORWARD, FFTW_ESTIMATE );

fftw_execute ( plan_forward );

n就是總體個數,不是啥一半還是一半加一那種,in和out都是fftw_complex這種類型

反變換:

 fftw_complex *in2 = fftw_malloc ( sizeof ( fftw_complex ) * n );
plan_backward = fftw_plan_dft_1d ( n, out, in2, FFTW_BACKWARD, FFTW_ESTIMATE );

fftw_execute ( plan_backward );

這時候的in2並不是原來的in,要除以n纔可以完全回去和最初的align

plan_backward 的結果需要除以n纔可以和 matlab中的 ifft()對應上,而fft不用管,和matlab中的fft是一模一樣的

使用完之後,釋放內存:

  fftw_destroy_plan ( plan_forward );
  fftw_destroy_plan ( plan_backward );

  fftw_free ( in );
  fftw_free ( in2 );

  fftw_free ( out );

matlab code: fft(a) 和 ifft(a)

二、fftw_plan_dft_r2c_1d 和 fftw_plan_dft_c2r_1d

double *in = fftw_malloc ( sizeof ( double ) * n );

nc = ( n / 2 ) + 1;

fftw_complex* out = fftw_malloc ( sizeof ( fftw_complex ) * nc );

plan_forward = fftw_plan_dft_r2c_1d ( n, in, out, FFTW_ESTIMATE );

fftw_execute ( plan_forward );

c code

 0     55.000000      0.000000
 1     -5.000000     15.388418
 2     -5.000000      6.881910
 3     -5.000000      3.632713

 4     -5.000000      1.624598

5     -5.000000      0.000000

matlab code

fft([1:10]) =
55
-5 +      15.3884176858763i
-5 +      6.88190960235587i
-5 +       3.6327126400268i
-5 +      1.62459848116453i
-5
-5 -      1.62459848116453i
-5 -       3.6327126400268i
-5 -      6.88190960235587i
-5 -      15.3884176858763i

反變換

in2 = fftw_malloc ( sizeof ( double ) * n );

out = fftw_malloc ( sizeof ( fftw_complex ) * nc );

plan_backward = fftw_plan_dft_c2r_1d ( n, out, in2, FFTW_ESTIMATE );

fftw_execute ( plan_backward );

要完全回去還得除以n  

in2[i] / ( double ) ( n )

 

 

 

Gsl 庫中有下面幾種

這幾種是基2的

gsl_fft_real_radix2_transform
gsl_fft_real_float_radix2_transform
gsl_fft_complex_radix2_forward
gsl_fft_complex_float_radix2_forward

這幾種是任意尺寸的FFT變換
gsl_fft_real_transform
gsl_fft_real_float_transform
gsl_fft_complex_forward
gsl_fft_complex_float_forward

重點介紹 gsl_fft_complex_radix2_forward (double版本))gsl_fft_complex_float_radix2_forward (float版本)

GSL裏面正變換反變換逆變換的差別 具體內容見( 一般都只有正反變換,哪有逆變換,或者把逆變換和反變換默認一個東西)

https://blog.csdn.net/liyuanbhu/article/details/40925873

gsl_fft_complex_radix2_forward  FFT的長度是N的話,那麼數組要造2N這麼長,

所謂的造數據就是gls庫中的 fft的輸入輸出都是double或者float的數組,它不需要啥gsl_complex 或者gsl_complex_float 這種玩意

下面原型函數中的 gsl_complex_packed_array 和  gsl_complex_packed_array  對應如下:

/* 2N consecutive built-in types as N complex numbers */
typedef double *       gsl_complex_packed_array ;
typedef float *        gsl_complex_packed_array_float  ;

它的數據排列是

data0_real_part  data0_image_part data1_real_part  data2_image_part ....

你需要加的庫文件

對於double:gsl_fft_complex.h

對於float:gsl_fft_complex_float.h

原型函數:

GSL_FUN int gsl_fft_complex_radix2_forward (gsl_complex_packed_array data,
                                    const size_t stride,
                                    const size_t n);

GSL_FUN int gsl_fft_complex_float_radix2_forward (gsl_complex_packed_array_float data,
                                          const size_t stride,
                                          const size_t n);

執行gsl_fft_complex_radix2_forward 之後,結果還保存在 data裏面(數據會被沖掉!)

下面是原型:

int gsl_fft_complex_radix2_forward (gsl_complex_packed_array data, size t stride, size t n)
int gsl_fft_complex_radix2_backward (gsl_complex_packed_array data, size t stride, size t n)
int gsl_fft_complex_radix2_inverse (gsl_complex_packed_array data, size t stride, size t n)

下面是使用方法:

gsl_fft_complex_radix2_forward(data, 1, 128);
gsl_fft_complex_radix2_backward(data, 1, 128);
gsl_fft_complex_radix2_inverse(data, 1, 128);

backward是不除以N

forward~fft 正變換

inverse~ifft 逆變換

他們和matlab的 fft ifft 等效

 

 

FFTW3中的二維變換的例子:【二維變換就是按行優先碼成一維向量

typedef struct _COMPLEX
{
    double real;
    double img;
}COMPLEX;

正變換

void FFT2(double **input, COMPLEX **output, int height, int width)
{
    fftw_plan planR;
    fftw_complex *inR, *outR;
    inR = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * height * width);
    outR = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * height * width);
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
        {
            inR[i * width + j][0] = input[i][j];
            inR[i * width + j][1] = 0;
        }
    planR = fftw_plan_dft_2d(height, width, inR, outR, FFTW_FORWARD, FFTW_ESTIMATE);
    fftw_execute(planR);
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
        {
            output[i][j]._COMPLEX::real = outR[i * width + j][0];
            output[i][j]._COMPLEX::img = outR[i * width + j][1];
        }
    fftw_destroy_plan(planR);
    fftw_free(inR);
    fftw_free(outR);
}

反變換

void IFFT2(COMPLEX **input, double **output, int height, int width)
{
    fftw_plan planR;
    fftw_complex *inR, *outR;
    inR = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * height * width);
    outR = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * height * width);
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
        {
            inR[i * width + j][0] = input[i][j]._COMPLEX::real;
            inR[i * width + j][1] = input[i][j]._COMPLEX::img;
        }
    planR = fftw_plan_dft_2d(height, width, inR, outR, FFTW_BACKWARD, FFTW_ESTIMATE);
    fftw_execute(planR);
    for (int i = 0; i < height; i++)
        for (int j = 0; j < width; j++)
        {
            output[i][j] = outR[i * width + j][0] / (height*width);
        }
    fftw_destroy_plan(planR);
    fftw_free(inR);
    fftw_free(outR);
}

gsl 貌似沒有2D的fft和ifft? (待確認。。。)

下面是一個使用fftw來搞定gsl 2D fft的一個例子

 

#include <fftw3.h>
  #include <gsl/gsl_matrix.h>
  #include <gsl/gsl_complex.h>
  #include <gsl/gsl_complex_math.h>
   
  int main()
  {
  //Create 2 GSL Complex matrices
  gsl_matrix_complex* mc = gsl_matrix_complex_alloc(3,3);
  gsl_matrix_complex* mc2 = gsl_matrix_complex_alloc(3,3);
  int i,j;
   
  /* FFTW requires data stored in row major order. Real and Imaginary parts of complex number stored as double[2]
  Fortunately, GSL implements gsl_matrix_complex in the required format. */
  fftw_complex* in = (fftw_complex*) mc->data;
  fftw_complex* out = (fftw_complex*) mc2->data;
   
  fftw_plan fp = fftw_plan_dft_2d(3,3, in, in, FFTW_FORWARD, FFTW_MEASURE);
  fftw_plan fp2 = fftw_plan_dft_2d(3,3, in, in, FFTW_BACKWARD, FFTW_MEASURE);
  for(i=0;i<3;i++)
  {
  for(j=0;j<3;j++)
  {
  gsl_matrix_complex_set(mc, i, j, gsl_complex_rect(i,j));
  }
  }
   
  //Calculate FFT
  fftw_execute(fp);
   
  for(i=0;i<3;i++)
  {
  for(j=0;j<3;j++)
  {
  printf("%f %f\n",GSL_REAL(gsl_matrix_complex_get(mc,i,j)),GSL_IMAG(gsl_matrix_complex_get(mc,i,j)));
  }
  }
   
  printf("\n");
   
  gsl_matrix_complex_scale(mc, gsl_complex_rect((1/9.0),0));
  fftw_execute(fp2);
   
  for(i=0;i<3;i++)
  {
  for(j=0;j<3;j++)
  {
  printf("%f %f\n",GSL_REAL(gsl_matrix_complex_get(mc,i,j)),GSL_IMAG(gsl_matrix_complex_get(mc,i,j)));
  }
  }
   
  return 0;
  }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章