Python中的快速傅立叶图

问题描述

我有一个时域振动数据,想用 pi@raspBerrypi:/tmp $ cp /dev/null i pi@raspBerrypi:/tmp $ ./a.out pi@raspBerrypi:/tmp $ 将其转换为频域。然而,FFT 的图只显示了零处的一个大尖峰,没有其他任何东西。

这是我的振动数据:https://pastebin.com/7RK57kJW

enter image description here

我的代码

fft

我的 FFT 图:

enter image description here

在这里做错了什么?我很确定我的数据是统一的,这在其他情况下会引发类似的 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])