需要解释 specgram 函数如何在 python 中工作(matplotlib - MATLAB 兼容函数)

Need explanation how specgram function work in python (matplotlib - MATLAB compatible functions)

我正在努力将我的代码从 python 转换为 objective c。 在 matplotlib.mlab.specgram 函数中,我在 fft 之前看到了 3 个重要函数:

 result = stride_windows(x, NFFT, noverlap, axis=0)
 result = detrend(result, detrend_func, axis=0)
 result, windowVals = apply_window(result, window, axis=0,
                                      return_window=True)
 result = np.fft.fft(result, n=pad_to, axis=0)[:numFreqs, :]

我尝试调试以了解每个的用途。例如我有输入数组:

x = [1,2,3,4,5,6,7,8,9,10,11,12]

在第一个函数stride_windows之后(这个是为了防止泄露?),如果NFFT = 4, noverlap = 2 then:

x = [ [1,3,5,7,9],
      [2,4,6,8,10],
      [3,5,7,9,11],
      [4,6,8,10,12] 
    ]

去除趋势后没有任何变化(我了解 fft 之前的去除趋势)

里面apply_window(这一步没看懂):

    xshape = list(x.shape) 
    xshapetarg = xshape.pop(axis) // =4
    windowVals = window(np.ones(xshapetarg, dtype=x.dtype))
    //result of 4 elements [0.0, 0.75, 0.75, 0.0]
    xshapeother = xshape.pop() // =5
    otheraxis = (axis+1) % 2  // =1
    windowValsRep = stride_repeat(windowVals, xshapeother, axis=otheraxis)
    // result windowValsRep = [
                                [ 0. ,0. ,0. ,0. ,0. ,],
                                [0.75, 0.75, 0.75, 0.75, 
                                [0.75, 0.75, 0.75, 0.75, 
                                [ 0. ,0. ,0. ,0. ,0. ,]
                              ]

然后乘以 x

windowValsRep * x

现在

 x =    [ 
          [ 0.  , 0.   , 0.   , 0.   , 0.   ],
          [ 1.5 , 3    , 4.5  , 6.   , 7.5  ],
          [ 2.25, 3.75 , 5.25 , 6.75 , 8.25 ],
          [ 0.  , 0.   , 0.   , 0.   , 0.   ] 
        ]

最后是fft,据我所知,fft只需要一个数组,但这里它处理二维数组。为什么?

result = np.fft.fft(x, n=pad_to, axis=0)[:numFreqs, :]

谁能一步步给我解释为什么数据在fft之前需要这样处理?

谢谢,

频谱图和 FFT 不是一回事。 spectogram 的目的是对小的、大小相等的时间块进行 FFT。这会产生二维傅里叶变换,其中 X 轴是时间块的开始时间,Y 轴是该时间块中每个频率的能量(或功率等)。这使您可以查看频率分量如何随时间变化。

specgram 函数的文档对此进行了解释:

Data are split into NFFT length segments and the spectrum of each section is computed. The windowing function window is applied to each segment, and the amount of overlap of each segment is specified with noverlap.

至于各个功能,reach 功能的文档中描述了很多您要问的内容,但我会尝试更详细地解释一下。

documentation 中所述,stride_windows 的目的是将一维数据数组转换为连续时间块的二维数组。这些是将在最终频谱图中计算其 FFT 的时间块。在您的情况下,它们是长度为 4 (NFFT=4) 的时间块(注意每列 4 个元素)。因为你设置了noverlap=2,每列的最后2个元素和下一列的前2个元素相同(就是重叠的意思)。它被称为 "stride" 是因为它使用了一个关于 numpy 数组内部存储的技巧来允许它创建一个具有重叠 windows 的数组而不占用任何额外的内存。

去趋势函数,顾名思义,如其 documentation, removes the trend from a signal. By default it uses the mean, which as the detrend_mean documentation describes, removes the mean (DC offset) 信号中所述。

apply_window 函数的作用与它的名字一样,documentation says: it applies a window function to each of the time chunks. This is needed because suddenly cutting of the signal at the beginning and end of the time chunks causes large bursts of broadband energy called transients that will mess up the spectrogram. Windowing the signal reduces those transients. By default the spectrogram function uses the hanning window 也是如此。这会衰减每个时间块的开始和结束。

FFT 并不是真正的二维。 numpy FFT function 允许您指定一个轴来接管 FFT。所以在这种情况下,我们有一个二维数组,我们对该数组的每一列进行 FFT。一步完成比手动遍历每一列要干净得多,速度也快一点。