Tabla de contenido
Cómo FFT (Transformada rápida de Fourier) para encontrar la amplitud y la frecuencia (súper detallado, incluido el proceso de derivación)
Para saber esta respuesta, verifiqué mucha información y la resumí.
注:本文代码的头文件等如下
import numpy as np
from scipy.fftpack import fft
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
mpl.rcParams['axes.unicode_minus'] = False # 显示负号
1. Batir una castaña
Establecimos
La frecuencia de muestreo es Fs | La frecuencia de señal más alta es F | El número de puntos de muestreo es N |
---|
Y hay una señal con la siguiente forma de onda. Los componentes de frecuencia de señal 0Hz
, 200Hz
, 400Hz
y 600Hz
de los cuatro 标准正弦函数
componentes.
对应完整代码
# 采样点选择1400个,因为设置的信号频率分量最高为600赫兹,根据采样定理知采样频率要大于信号频率2倍,
# 所以这里设置采样频率为1400赫兹(即一秒内有1400个采样点)
N = 1400 # 设置1400个采样点
x = np.linspace(0, 1, N) # 将0到1平分成1400份
# 设置需要采样的信号,频率分量有0,200,400和600
y = 7 * np.sin(2 * np.pi * 200 * x) + 5 * np.sin(
2 * np.pi * 400 * x) + 3 * np.sin(2 * np.pi * 600 * x) + 10 # 构造一个演示用的组合信号
plt.plot(x, y)
plt.title('原始波形')
plt.show()
Se puede ver que en este ejemplo
Frecuencia de muestreo Fs | Frecuencia de señal F | Número de puntos de muestreo N |
---|---|---|
1400 Hz | 600 Hz | 1.400 |
Entonces, después de la transformada rápida de Fourier (FFT), lo obtendremos N个复数
. Cada valor complejo contiene 一个特定频率的信息
. Según estos N números complejos, podemos conocer las frecuencias obtenidas al dividir la señal original y sus valores de amplitud.
对应代码
fft_y = fft(y) # 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组
2. Encuentra la amplitud
1. Transformada rápida de Fourier
De acuerdo con los datos obtenidos después de la transformada rápida de Fourier, se puede dibujar el siguiente gráfico irregular.
(Aquí, enfóquese primero en el eje vertical, y el eje horizontal se explicará en la siguiente sección).
对应完整代码如下
N = 1400 # 设置1400个采样点
x = np.linspace(0, 1, N) # 将0到1平分成1400份
y = 7 * np.sin(2 * np.pi * 200 * x) + 5 * np.sin(
2 * np.pi * 400 * x) + 3 * np.sin(2 * np.pi * 600 * x) + 10 # 构造一个演示用的组合信号
fft_y = fft(y) # 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组
x = np.arange(N) # 频率个数 (x的取值涉及到横轴的设置,这里暂时忽略,在第二节求频率时讲解)
plt.plot(x, fft_y, 'black')
plt.title('双边振幅谱(未求振幅绝对值)', fontsize=9, color='black')
plt.show()
2. Encuentra el valor absoluto de un número complejo
El gráfico dibujado directamente con números complejos no es lo que necesitamos. Primero se debe encontrar el valor absoluto (longitud modular) de todos los N números complejos
abs_y = np.abs(fft_y) # 取复数的绝对值,即复数的模
En base a esto, se puede dibujar la siguiente imagen
3. Normalización
La figura, el lado izquierdo del primer valor es 从原始信号中提取出来的0Hz
una intensidad de señal correspondiente (amplitud de señal), también conocida 直流分量
. Su correspondiente amplitud de señal es 当前值/FFT的采样点数N
, a saber
0Hz amplitud correspondiente = valor actual / número de puntos de muestreo N
Nota:
- En este ejemplo, la amplitud correspondiente del componente de CC = 14000/1400 = 10
- El valor actual es el valor absoluto (módulo de longitud) obtenido del número complejo actual
La amplitud de la señal correspondiente a los componentes distintos del componente de CC 当前值/(采样点数N/2)
es:
Amplitud correspondiente a otras frecuencias = valor actual / (número de puntos de muestreo N / 2)
Nota:
- En este ejemplo, 200 Hz corresponde a una amplitud = 5000 / (1400/2) ≈ 7,14 (5000 aquí es el valor estimado obtenido al mirar la imagen, solo por ejemplo, no necesariamente exacto), las otras frecuencias corresponden al mismo algoritmo de amplitud .
Entonces, después de la normalización, obtenemos la siguiente figura
对应完整代码
N = 1400 # 设置1400个采样点
x = np.linspace(0, 1, N) # 将0到1平分成1400份
y = 7 * np.sin(2 * np.pi * 200 * x) + 5 * np.sin(
2 * np.pi * 400 * x) + 3 * np.sin(2 * np.pi * 600 * x) + 10 # 构造一个演示用的组合信号
fft_y = fft(y) # 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组
x = np.arange(N) # 频率个数(x的取值涉及到横轴的设置,这里暂时忽略,在第二节求频率时讲解)
abs_y = np.abs(fft_y) # 取复数的绝对值,即复数的模
normalization_y = abs_y / (N / 2) # 归一化处理(双边频谱)
normalization_y[0] /= 2
plt.plot(x, abs_y, 'r')
plt.title('双边振幅谱(归一化)', fontsize=9, color='red')
plt.show()
resumen
Amplitud del componente DC (0Hz) | Otra amplitud de frecuencia |
---|---|
El valor absoluto del número complejo obtenido por fft / N | El valor absoluto del número complejo obtenido por fft / (N / 2) |
Tres. Encuentra la frecuencia
Primero coloque un párrafo de texto aquí, que explique el método de encontrar la frecuencia de manera más vívida.
Por ejemplo, tiene una señal analógica con la frecuencia más alta f = 32 kHz y una frecuencia de muestreo de 64 kHz. Realice un análisis FFT de 16 puntos en esta señal. El rango del subíndice n del punto de muestreo es 0, 1, 2, 3, …, 15. Luego, la frecuencia analógica de 64 kHz se divide en 16 partes, cada parte es 4kHz, esta 4kHz se llama resolución de frecuencia.
Por lo tanto, en la abscisa de la tabla de frecuencias:
n = 1 corresponde af es de 4 kHz
n = 2 corresponde af es de 8 kHz
...
n = 15 corresponde af es de 60 kHz
y el espectro de frecuencias es simétrico alrededor de n = 8, solo importa n = 0 Un espectro de ~ 7 es suficiente. Porque la frecuencia más alta de la señal original es de 32 kHz.
(Este párrafo está adaptado de la Referencia 1)
1. Fórmula de frecuencia
Por lo tanto, después de conocer la frecuencia de muestreo Fs, la frecuencia real correspondiente al x-ésimo (x comenzando desde 0) valor complejo después de la transformada rápida de Fourier (FFT) es
f (x) = x * (Fs / n)
Entonces, en este ejemplo,
La frecuencia del punto 0 f (0) = 0 * (1400/1400) = 0
La frecuencia del primer punto f (0) = 1 * (1400/1400) = 1
La frecuencia del segundo punto f (0) = 2 * (1400/1400) = 2
...
la frecuencia del punto 200 f (200) = 200 * ( 1400/1400 ) = 200
...
la frecuencia del punto 1400 f (200) = 1400 * (1400/1400) = 1400
(Debido a la coincidencia, la frecuencia correspondiente al x-ésimo punto es exactamente x)
Ahora sabemos por qué el valor de la coordenada del eje x se establece de esta manera.
2. Elimina los valores duplicados
Solo la mitad de la frecuencia de 0 a N / 2 es válida y la otra mitad es simétrica a esta mitad. Después de eliminar la duplicación, obtenemos la siguiente imagen.
Correspondiente al código completo:
N = 1400 # 设置1400个采样点
x = np.linspace(0, 1, N) # 将0到1平分成1400份
y = 7 * np.sin(2 * np.pi * 200 * x) + 5 * np.sin(
2 * np.pi * 400 * x) + 3 * np.sin(2 * np.pi * 600 * x) + 10 # 构造一个演示用的组合信号
fft_y = fft(y) # 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组
x = np.arange(N) # 频率个数(x的取值涉及到横轴的设置,这里暂时忽略,在第二节求频率时讲解)
half_x = x[range(int(N / 2))] # 取一半区间
abs_y = np.abs(fft_y) # 取复数的绝对值,即复数的模
normalization_y = abs_y / (N / 2) # 归一化处理(双边频谱)
normalization_y[0] /= 2
normalization_half_y = normalization_y[range(int(N / 2))] # 由于对称性,只取一半区间(单边频谱)
plt.plot(half_x, normalization_half_y, 'blue')
plt.title('单边振幅谱(归一化)', fontsize=9, color='blue')
plt.show()
resumen
Entre los n valores complejos obtenidos después de FFT, la frecuencia f (x) correspondiente al x-ésimo (x comienza desde 0) valor complejo es
f (x) = x * (Fs / n)
Apéndice: código completo
import numpy as np
from scipy.fftpack import fft
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
mpl.rcParams['axes.unicode_minus'] = False # 显示负号
# 采样点选择1400个,因为设置的信号频率分量最高为600赫兹,根据采样定理知采样频率要大于信号频率2倍,
# 所以这里设置采样频率为1400赫兹(即一秒内有1400个采样点,一样意思的)
N = 1400
x = np.linspace(0, 1, N)
# 设置需要采样的信号,频率分量有0,200,400和600
y = 7 * np.sin(2 * np.pi * 200 * x) + 5 * np.sin(
2 * np.pi * 400 * x) + 3 * np.sin(2 * np.pi * 600 * x) + 10
fft_y = fft(y) # 快速傅里叶变换
x = np.arange(N) # 频率个数
half_x = x[range(int(N / 2))] # 取一半区间
angle_y = np.angle(fft_y) # 取复数的角度
abs_y = np.abs(fft_y) # 取复数的绝对值,即复数的模(双边频谱)
normalization_y = abs_y / (N / 2) # 归一化处理(双边频谱)
normalization_y[0] /= 2 # 归一化处理(双边频谱)
normalization_half_y = normalization_y[range(int(N / 2))] # 由于对称性,只取一半区间(单边频谱)
plt.subplot(231)
plt.plot(x, y)
plt.title('原始波形')
plt.subplot(232)
plt.plot(x, fft_y, 'black')
plt.title('双边振幅谱(未求振幅绝对值)', fontsize=9, color='black')
plt.subplot(233)
plt.plot(x, abs_y, 'r')
plt.title('双边振幅谱(未归一化)', fontsize=9, color='red')
plt.subplot(234)
plt.plot(x, angle_y, 'violet')
plt.title('双边相位谱(未归一化)', fontsize=9, color='violet')
plt.subplot(235)
plt.plot(x, normalization_y, 'g')
plt.title('双边振幅谱(归一化)', fontsize=9, color='green')
plt.subplot(236)
plt.plot(half_x, normalization_half_y, 'blue')
plt.title('单边振幅谱(归一化)', fontsize=9, color='blue')
plt.show()
Apéndice: Proceso de derivación
Para obtener más detalles, consulte la conversión de la fórmula entre la frecuencia circular w y la frecuencia f en la transformada de Fourier
Materiales de referencia:
- Frecuencia normalizada en el procesamiento de señales digitales
- Use python (scipy y numpy) para implementar la transformación rápida de Fourier (FFT), el tutorial más detallado
- Después de obtener el número complejo después de FFT, ¿cómo encontrar la frecuencia basada en este número complejo?
- Determinación de frecuencia y amplitud FFT
- En la transformada de Fourier, la fórmula de conversión entre la frecuencia circular w y la frecuencia f