如何理解 DFT 结果

Posted

技术标签:

【中文标题】如何理解 DFT 结果【英文标题】:How to understand DFT results 【发布时间】:2015-10-08 10:44:43 【问题描述】:

我使用这种 DFT 实现:

/*
Direct fourier transform
*/
int DFT(int dir,int m,double *x1,double *y1)

    long i,k;
    double arg;
    double cosarg,sinarg;
    double *x2=NULL,*y2=NULL;

    x2 = malloc(m*sizeof(double));
    y2 = malloc(m*sizeof(double));
    if (x2 == NULL || y2 == NULL)
       return(FALSE);

    for (i=0;i<m;i++) 
       x2[i] = 0;
       y2[i] = 0;
       arg = - dir * 2.0 * 3.141592654 * (double)i / (double)m;
       for (k=0;k<m;k++) 
          cosarg = cos(k * arg);
          sinarg = sin(k * arg);
          x2[i] += (x1[k] * cosarg - y1[k] * sinarg);
          y2[i] += (x1[k] * sinarg + y1[k] * cosarg);
       
    

    /* Copy the data back */
    if (dir == 1) 
      for (i=0;i<m;i++) 
         x1[i] = x2[i] / (double)m;
         y1[i] = y2[i] / (double)m;
      
    else 
      for (i=0;i<m;i++) 
         x1[i] = x2[i];
         y1[i] = y2[i];
      
   

   free(x2);
   free(y2);
   return(TRUE);

这里放的是http://paulbourke.net/miscellaneous/dft/

第一个问题是为什么在应用直接变换后(dir=1)我们应该缩放值?我阅读了一些关于 DFT 实现的想法,但没有找到任何相关信息。

作为输入,我使用 1024 采样频率的 cos

#define SAMPLES 2048
#define ZEROES_NUMBER 512

double step = PI_2/(SAMPLES-2*ZEROES_NUMBER);
for(int i=0; i<SAMPLES; i++)

    /*
     * Fill in the beginning and end with zeroes 
     */
    if(i<ZEROES_NUMBER || i > SAMPLES-ZEROES_NUMBER)
    
        samplesReal[i] = 0;
        samplesImag[i] = 0;
    
    /*
     *  Generate one period cos with 1024 samples
     */
    else
    
        samplesReal[i] = cos(step*(double)(i-ZEROES_NUMBER));
        samplesImag[i] = 0;
    

对于绘图,我删除了我上面询问的缩放比例,因为输出值变得非常小并且无法绘制图形。

我得到了这样的幅度和相位图:

如您所见,相位始终为 0,幅度谱反转。为什么?

下面是我的更易读的版本,没有缩放,产生相同的结果:

void DFT_transform(double complex* samples, int num, double complex*   res)

    for(int k=0; k<num; k++)
    
        res[k] = 0;
        for(int n=0; n<num; n++)
        
            double complex Wkn = cos(PI_2*(double)k*(double)n/(double)num) -
            I*sin(PI_2*(double)k*(double)n/(double)num);

            res[k] += samples[n]*Wkn;
        
    

【问题讨论】:

@LightnessRacesinOrbit 我的实现使用了用 c++ 编写的复杂库。 每个问题一个问题。缩放只是一个约定,并且有不同的约定 - 通常它是正向的 1/N,而反向则没有缩放。要查看您的 DFT 是否正常工作,请从纯正弦波开始,然后查看输出箱的 幅度 (sqrt(re^2 + im^2))。 @LongSmith:但你问的是 C 代码,是吗? @PaulR 谢谢。我尝试输入cos(i)。这就是我为amplitude 和phase 得到的。幅度只是有点不同,但在相位上出现了一些新的东西。那是在开头和结尾填充零。 @LongSmith:幅度是指幅度,即sqrt(re^2 + im^2)?请注意,输入应具有例如x1 中的正弦波和 y1 中的零 - 不要像问题中的代码那样用零填充开头和结尾。您可以根据已知良好的 DFT 或 FFT 实施检查结果,例如Octave(免费的 MATLAB 克隆)。 【参考方案1】:

好的,伙计们。我很高兴地说这个实现是有效的。 问题是绘制图表的方式错误以及缺乏对公式的理解。

工作原理

如您所见,k 变量用于改变频率。 所以频率是 ν = k / T,其中 T 是获取样本所需的时间段。 T = N/S 其中 S 是您的采样频率。然后你可以找到你的频率 v = S*k/N

因此,当您获得结果时,您应该计算每个点的频率并删除 S/2 以上的所有内容,然后才绘制图表 Magnitude = Magnitude(Frequency)。这是我之前不明白的。希望对某人有所帮助。

我得到了一些图表。

仙100HZ。

Sin 100HZ + Cos 200HZ。

Sin 100HZ + (Cos 200HZ)/2

如您所见,图中显示了频率和相关幅度。缩放存在问题,但如果我们想确定信号中出现的频率并不重要。

感谢@PaulR

【讨论】:

以上是关于如何理解 DFT 结果的主要内容,如果未能解决你的问题,请参考以下文章

对于DFT频谱泄漏问题的研究

DFT

计算下列数字两个图像块的二维DFT和二维DCT,并用Matlab编程验证计算结果

计算下列数字两个图像块的二维DFT和二维DCT,并用Matlab编程验证计算结果

DFT与IDFT

Discrete Cosine Transform