从FFT中求出信号的周期

2024-10-04 05:24:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个周期信号,我想找出周期。 Raw signal

由于存在边界效应,我首先去掉边界,通过观察第一个和最后一个极小值保持N个周期。在

Signal

然后,计算FFT。在

代码:

import numpy as np

from matplotlib import pyplot as plt

# The list of a periodic something
L = [2.762, 2.762, 1.508, 2.758, 2.765, 2.765, 2.761, 1.507, 2.757, 2.757, 2.764, 2.764, 1.512, 2.76, 2.766, 2.766, 2.763, 1.51, 2.759, 2.759, 2.765, 2.765, 1.514, 2.761, 2.758, 2.758, 2.764, 1.513, 2.76, 2.76, 2.757, 2.757, 1.508, 2.763, 2.759, 2.759, 2.766, 1.517, 4.012]
# Round because there is a slight variation around actually equals values: 2.762, 2.761 or 1.508, 1.507
L = [round(elt, 1) for elt in L]

minima = min(L)
min_id = L.index(minima)

start = L.index(minima)
stop = L[::-1].index(minima)

L = L[start:len(L)-stop]

fft = np.fft.fft(np.asarray(L))/len(L)
fft = fft[range(int(len(L)/2))]

plt.plot(abs(fft))

我知道在列表的2个点之间有多少时间(即采样频率,在本例中为190赫兹)。我认为fft应该给我一个峰值,对应于一个周期内的点数,从而得到点数和周期。 然而,这根本不是我观察到的结果:

FFT

我目前的猜测是0处的峰值对应于我信号的平均值,7左右的这个小峰值应该是我的周期(尽管,重复模式只包括5个点)。在

我做错什么了?谢谢!在


Tags: importfftindexlen信号asnpplt
3条回答

您的数据是正确的,只是您没有正确地预处理它:

  1. 第一个巨大的峰值是信号的直流电/平均值。如果你在做DFT之前减去它,它就会消失
  2. 在进行DFT之前不加窗会在DFT频谱中产生振铃,降低峰值并提高“非峰值”。在

如果包含这两个步骤,则结果应该与您预期的更接近:

import numpy as np
import scipy.signal

from matplotlib import pyplot as plt

L = np.array([2.762, 2.762, 1.508, 2.758, 2.765, 2.765, 2.761, 1.507, 2.757, 2.757, 2.764, 2.764, 1.512, 2.76, 2.766, 2.766, 2.763, 1.51, 2.759, 2.759, 2.765, 2.765, 1.514, 2.761, 2.758, 2.758, 2.764, 1.513, 2.76, 2.76, 2.757, 2.757, 1.508, 2.763, 2.759, 2.759, 2.766, 1.517, 4.012])
L = np.round(L, 1)
# Remove DC component
L -= np.mean(L)
# Window signal
L *= scipy.signal.windows.hann(len(L))

fft = np.fft.rfft(L, norm="ortho")

plt.plot(L)
plt.figure()
plt.plot(abs(fft))

您将注意到,您将在8左右看到一个峰值,另一个峰值在两倍16处。这也是意料之中的:周期信号在n*period采样之后总是周期性的,其中n是任何自然数。在你的例子中:n*8。在

一旦信号的直流部分被移除,函数就可以与其自身卷积以捕捉周期。实际上,卷积在周期的每一个倍数上都会出现峰值。FFT可以用来计算卷积。在

fft = np.fft.rfft(L, norm="ortho")

def abs2(x):
    return x.real**2 + x.imag**2

selfconvol=np.fft.irfft(abs2(fft), norm="ortho")

第一个输出不是很好,因为图像的大小不是周期的倍数。在

self convolution of periodic signal by fft

正如Nils-Werner所注意到的,一个窗口可以用来限制频谱泄漏的影响。另一种选择是,周期的第一个粗略估计可以用来传输信号,并且可以重复我在How do I scale an FFT-based cross-correlation such that its peak is equal to Pearson's rho中回答的过程。在

self convolution of periodic signal by fft(2)

从那里,得到周期可以归结为找到第一个最大值。有一种方法可以做到:

^{pr2}$

FFT幅值结果中的峰值表示频率,它是周期的倒数。将频率指数倒数乘以FFT窗口长度,得到窗口长度相同单位的周期结果。在

相关问题 更多 >