问题描述
我有一个时域振动数据,想用 pi@raspBerrypi:/tmp $ cp /dev/null i
pi@raspBerrypi:/tmp $ ./a.out
pi@raspBerrypi:/tmp $
将其转换为频域。然而,FFT 的图只显示了零处的一个大尖峰,没有其他任何东西。
这是我的振动数据:https://pastebin.com/7RK57kJW
我的代码:
fft
我的 FFT 图:
我在这里做错了什么?我很确定我的数据是统一的,这在其他情况下会引发类似的 fft 问题。
解决方法
FFT 的 bin 对应于 0,df,2df,3df,...,F-2df,F-df
处的频率,其中 df
由 bin 的数量决定,F
是每个 bin 1 个周期。
注意开头的零频率。这称为直流偏移。这是你的数据的平均值。在您显示的数据中,平均值约为 1.32,而正弦波的幅度约为 0.04。看不到比 DC 项小 33 倍的峰值也就不足为奇了。
有一些常见的数据可视化方法可以帮助您解决这个问题。一种常见的方法是保持 DC 偏移但使用对数刻度,至少对于 y 轴:
plt.semilogy(freq,a1_fft)
或
plt.loglog(freq,a1_fft)
您可以做的另一件事是放大图的底部 1/33 左右。您可以手动执行此操作,也可以通过调整所显示 Y 轴的跨度来执行此操作:
p = np.abs(a1_fft[1:]).max() * [-1.1,1.1]
plt.ylim(p)
如果您已经在绘制绝对值,请使用
p = np.abs(a1_fft[1:]).max() * [-0.1,1.1]
另一种方法是去除直流偏移。一种比 @J. Schmidt 建议的更优雅的方法是简单地不显示 DC 项:
plt.plot(freq[1:],a1_fft[1:])
或者仅针对正频率:
n = freq.size
plt.plot(freq[1:n//2],a1_fft[1:n//2])
n // 2
处的截止值只是近似值。正确的截止取决于 FFT 的元素数是偶数还是奇数。对于偶数,中间的 bin 实际具有来自光谱两侧的能量,并且经常得到特殊处理。
0 处的峰值是 DC 增益,由于您没有对数据进行标准化,因此该值非常高。此外,傅立叶变换是一个复数,您应该分别绘制绝对值和相位。在这段代码中,我也只绘制了正频率:
import numpy as np
import matplotlib.pyplot as plt
#Import data
a1 = np.loadtxt('a1.txt')
plt.plot(a1)
#Normalize a1
a1 -= np.mean(a1)
#Your code
t = np.arange(3000)
a1_fft= np.fft.fft(a1,axis=0)
freq = np.fft.fftfreq(t.shape[-1])
#Only plot positive frequencies
plt.figure()
plt.plot(freq[freq>=0],np.abs(a1_fft)[freq>=0])