una transformada señales señal rápida potencia muestreo muestrear fourier espectro espectral discreta densidad convolucion python numpy scipy signal-processing

transformada - señales de audio en python



Trazado del espectro de potencia en python (5)

Como la FFT es simétrica en su centro, la mitad de los valores son suficientes.

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)

Tengo una matriz con 301 valores, que se recopilaron de un clip de película con 301 fotogramas. Esto significa 1 valor de 1 marco. El clip de película se está ejecutando a 30 fps, por lo que en realidad dura 10 segundos

Ahora me gustaría obtener el espectro de potencia de esta "señal" (con el eje derecho). Lo intenté:

X = fft(S_[:,2]); pl.plot(abs(X)) pl.show()

También intenté:

X = fft(S_[:,2]); pl.plot(abs(X)**2) pl.show()

Aunque no creo que este sea el espectro real.

la señal:

El espectro:

El espectro de potencia:

¿Alguien puede proporcionar alguna ayuda con esto? Me gustaría tener una parcela en Hz .


Desde la página de números de fpy http://docs.scipy.org/doc/numpy/reference/routines.fft.html :

Cuando la entrada a es una señal de dominio de tiempo y A = fft (a), np.abs (A) es su espectro de amplitud y np.abs (A) ** 2 es su espectro de potencia. El espectro de fase se obtiene mediante np.angle (A).


Numpy tiene una función de conveniencia, np.fft.fftfreq para calcular las frecuencias asociadas con los componentes 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])

Tenga en cuenta que la frecuencia más grande que ve en su caso no es de 30 Hz, pero

In [7]: max(freqs) Out[7]: 14.950166112956811

Nunca se ve la frecuencia de muestreo en un espectro de potencia. Si hubiera tenido un número par de muestras, entonces habría alcanzado la frecuencia de Nyquist , 15 Hz en su caso (aunque Numpy lo habría calculado como -15).


Si la frecuencia es la frecuencia de muestreo (Hz), entonces np.linspace(0, rate/2, n) es la matriz de frecuencia de cada punto en fft. Puede usar rfft para calcular la FFT en sus datos como valores reales:

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)

la señal x contiene una onda sin de 4Hz y 7Hz, así que hay dos picos a 4Hz y 7Hz.


También puede usar scipy.signal.welch para estimar la densidad espectral de potencia utilizando el método de Welch. Aquí hay una comparación entre np.fft.fft y 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()

El