我有一个包含301个值的数组,这些值来自于一个包含301帧的电影剪辑。这意味着每帧取一个值。该电影剪辑以30fps的速度运行,因此实际上长度为10秒。
现在我想获取这个“信号”的功率谱(并且需要正确的轴)。我尝试过:
X = fft(S_[:,2]);
pl.plot(abs(X))
pl.show()
我也尝试了:
X = fft(S_[:,2]);
pl.plot(abs(X)**2)
pl.show()
虽然我不认为这是真正的光谱。信号:
![enter image description here](https://istack.dev59.com/MG8dz.webp)
![enter image description here](https://istack.dev59.com/VU17P.webp)
![enter image description here](https://istack.dev59.com/q8zQY.webp)
我有一个包含301个值的数组,这些值来自于一个包含301帧的电影剪辑。这意味着每帧取一个值。该电影剪辑以30fps的速度运行,因此实际上长度为10秒。
现在我想获取这个“信号”的功率谱(并且需要正确的轴)。我尝试过:
X = fft(S_[:,2]);
pl.plot(abs(X))
pl.show()
我也尝试了:
X = fft(S_[:,2]);
pl.plot(abs(X)**2)
pl.show()
虽然我不认为这是真正的光谱。Numpy有一个便利函数np.fft.fftfreq
,用于计算与FFT分量相关联的频率:
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
data = np.random.rand(301) - 0.5
ps = np.abs(np.fft.fft(data))**2
time_step = 1 / 30
freqs = np.fft.fftfreq(data.size, time_step)
idx = np.argsort(freqs)
plt.plot(freqs[idx], ps[idx])
请注意,在您的情况下看到的最大频率不是30 Hz,而是
In [7]: max(freqs)
Out[7]: 14.950166112956811
在功率谱中,你从来没有看到采样频率。如果你有偶数个样本,那么你将会达到奈奎斯特频率,在你的情况下是15赫兹(虽然numpy会计算为-15)。
如果rate是采样率(赫兹),那么np.linspace(0, rate/2, n)
就是fft中每个点的频率数组。如果你的数据是实数值,你可以使用rfft
来计算fft:
import numpy as np
import pylab as pl
rate = 30.0
t = np.arange(0, 10, 1/rate)
x = np.sin(2*np.pi*4*t) + np.sin(2*np.pi*7*t) + np.random.randn(len(t))*0.2
p = 20*np.log10(np.abs(np.fft.rfft(x)))
f = np.linspace(0, rate/2, len(p))
plot(f, p)
信号x包含4Hz和7Hz正弦波,因此在4Hz和7Hz处有两个峰值。
fft.rfft
时:p[0] -= 6.02; p[-1] -= 6.02
(absfft2[0] /= 2; absfft2[-1] /= 2
) - 请参见例如 Numerical Recipes 第 653页。 - denispl.plot(f, p)
才能运行代码。非常感谢您的回答,很有教育意义。 - wancharlenp.fft.frrt
,则相应的频率函数为 np.fft.rfftfreq
。 - Itamar Mushkin你也可以使用scipy.signal.welch来使用Welch方法估计功率谱密度。以下是np.fft.fft和scipy.signal.welch之间的比较:
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
fs = 10e3
N = 1e5
amp = 2*np.sqrt(2)
freq = 1234.0
noise_power = 0.001 * fs / 2
time = np.arange(N) / fs
x = amp*np.sin(2*np.pi*freq*time)
x += np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
# np.fft.fft
freqs = np.fft.fftfreq(time.size, 1/fs)
idx = np.argsort(freqs)
ps = np.abs(np.fft.fft(x))**2
plt.figure()
plt.plot(freqs[idx], ps[idx])
plt.title('Power spectrum (np.fft.fft)')
# signal.welch
f, Pxx_spec = signal.welch(x, fs, 'flattop', 1024, scaling='spectrum')
plt.figure()
plt.semilogy(f, np.sqrt(Pxx_spec))
plt.xlabel('frequency [Hz]')
plt.ylabel('Linear spectrum [V RMS]')
plt.title('Power spectrum (scipy.signal.welch)')
plt.show()
fft
,使用rfft
进行比较会更好。 - endolith从 numpy fft 页面http://docs.scipy.org/doc/numpy/reference/routines.fft.html:
当输入 a 是一个时域信号并且 A = fft(a),np.abs(A) 是它的振幅谱,np.abs(A)**2 是它的功率谱。相位谱由 np.angle(A) 获得。
import numpy as np
import matplotlib.pyplot as plt
fs = 30.0
t = np.arange(0,10,1/fs)
x = np.cos(2*np.pi*10*t)
xF = np.fft.fft(x)
N = len(xF)
xF = xF[0:N/2]
fr = np.linspace(0,fs/2,N/2)
plt.ion()
plt.plot(fr,abs(xF)**2)