真实对称图像的FFTW变换是不是真实对称的?

时间:2014-02-03 16:40:31

标签: fftw

我对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需要某种零填充, 或者我错过了其他的东西..

1 个答案:

答案 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)来保存一些内存。
  • 你对填充是正确的。实际上,fftw在x方向存储“额外”频率。这就是为什么你应该在width/2+1方向分配x个复数。一旦您更正了打印操作,您将获得xy之间的对称值

结果如下:

#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;
}

再见,

弗朗西斯