我对FFTW中的FFT实现有一个问题。或者问题可能是我对FFT的了解。关键是,据我所知, 如果我向前变换一个对称和真实的信号,我也应该得到一个对称和真实的信号。但是,这不是我所发现的 在FFTW中。我正在使用fftwf_plan_dft_r2c_2d例程在2d工作。
我在这里留下一段简单的代码,创建一个存储在每个像素中的矩阵 (x,y)计算1 /(sqrt(x ^ 2 + y ^ 2))的结果,其是对称信号。还有一个循环打印出这些值,只是为了检查 我正确地构建了矩阵。
#include <fftw3.h>
int main(int argc, char* argv[]){
width=5;height=5;
float *omega;
omega = (float *) malloc(sizeof(float)*width*height);
float *omegasym = (float *) malloc(sizeof(float)*2*width*2*height);
int y, x;
//Build a symmetric real signal
for(y = 0, i = 0; y < height; y++) /* omega = 1/sqrt(x^2 + y^2) */
for(x = 0; x < width; x++, i++)
omega[i] = (x == 0 && y == 0) ? 0 : 1.0f/(float) std::sqrt((float) x*x + y*y);
//Just check if we did well
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
std::cout<<" " << omega[j+5*i] << " ";
}
std::cout<<endl;
}
fftwf_complex *omega_trans_complexx;
omega_trans_complexx = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex)*2*height*(2*width/2+1));
fftwf_plan plan;
plan=fftwf_plan_dft_r2c_2d(height, width, omega, omega_trans_complexx, FFTW_ESTIMATE);
//Should not this has imaginary part = 0??? :S
for(int i=0; i<25; i++){
std::cout<<"Real part of omega_trans is :" << omega_trans_complexx[i][0] << endl;
std::cout<<"Imaginary part of omega_trans is :" << omega_trans_complexx[i][1] << endl;
}
return 0;
}
用FFTW计算正向变换后,我得到一个非零的虚部。起初我认为可能是信号不是这样的事实 对称,但对于它的对称版本,它也不起作用。我想知道我做错了什么,或者FFTW需要某种零填充, 或者我错过了其他的东西..
答案 0 :(得分:2)
这个问题似乎部分是关于fft的属性
的x,y轴&GT; 1 /(sqrt(x ^ 2 + y ^ 2))既不是偶数也不是奇数。你得到一个非零的虚部是正常的。如果您尝试:
,您可能会想到零虚部 omega[i]=sin(2.0*M_PI/height*y)*sin(2.0*M_PI/width*x);
或:
omega[i]=cos(2.0*M_PI/height*y)*cos(2.0*M_PI/width*x);
如果你尝试的话,还有一些纯粹想象的东西:
omega[i]=cos(2.0*M_PI/height*y)*sin(2.0*M_PI/width*x);
使用real作为输入的效果是你不必为负频率计算fft,因为它是相应正频率的共轭:\hat{f}(-k)=(\hat{f}(k))*
关于代码本身:
fftwf_execute(plan);
,你就不会得到任何有用的东西!sizeof(fftwf_complex)*2*height*(2*width/2+1)
太大了。您可以使用sizeof(fftwf_complex)*2*height*(width/2+1)
来保存一些内存。x
方向存储“额外”频率。这就是为什么你应该在width/2+1
方向分配x
个复数。一旦您更正了打印操作,您将获得x
和y
之间的对称值结果如下:
#include <fftw3.h>
#include <iostream>
#include <cmath>
#include <stdlib.h>
int main(int argc, char* argv[]){
int width=5;int height=5;
float *omega;
omega = (float *) fftwf_malloc(sizeof(float)*width*height);
float *omegasym = (float *) malloc(sizeof(float)*2*width*2*height);
int y, x;
//Build a symmetric real signal
int i;
for(y = 0, i = 0; y < height; y++) /* omega = 1/sqrt(x^2 + y^2) */
for(x = 0; x < width; x++, i++)
//omega[i]=sin(2.0*M_PI/height*y)*cos(2.0*M_PI/width*x);
omega[i] = (x == 0 && y == 0) ? 0 : 1.0f/(float) std::sqrt((float) x*x + y*y);
//Just check if we did well
for(i=0; i<5; i++){
for(int j=0; j<5; j++){
std::cout<<" " << omega[j+5*i] << " ";
}
std::cout<<std::endl;
}
fftwf_complex *omega_trans_complexx;
omega_trans_complexx = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex)*2*height*(width/2+1));
fftwf_plan plan;
plan=fftwf_plan_dft_r2c_2d(height, width, omega, omega_trans_complexx, FFTW_ESTIMATE);
fftwf_execute(plan);
//Should not this has imaginary part = 0??? :S : imaginary part is ok :)
for(y = 0, i = 0; y < height; y++) /* omega = 1/sqrt(x^2 + y^2) */
for(x = 0; x < width/2+1; x++, i++)
std::cout<<"freqx "<<x<<" freqy "<<y<<" real "<<omega_trans_complexx[i][0]<< " imag "<<omega_trans_complexx[i][1]<<std::endl;
return 0;
}
再见,
弗朗西斯