先分析一維度的
一、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; | |
} |