301フレームのムービークリップから収集した301値の配列があります。これは、1フレームから1つの値を意味します。ムービークリップは30 fpsで実行されているため、実際には10秒です
次に、この「信号」のパワースペクトルを取得したいと思います(右の軸を使用)。私は試した:
X = fft(S_[:,2]);
pl.plot(abs(X))
pl.show()
私も試しました:
X = fft(S_[:,2]);
pl.plot(abs(X)**2)
pl.show()
これは本当のスペクトルではないと思いますが。
シグナル:
スペクトル:
パワースペクトル:
誰でもこれで助けを提供できますか? Hz単位でプロットしたい。
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 Hzに達していました(numpyは-15として計算していましたが)。
rateがサンプリングレート(Hz)の場合、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に2つのピークがあります。
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)によって取得されます。
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は中心に対して対称であるため、値の半分で十分です。
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)