Cómo FFT (Transformada rápida de Fourier) para encontrar la amplitud y la frecuencia (súper detallado, incluido el proceso de derivación)


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, 400Hzy 600Hzde los cuatro 标准正弦函数componentes.
Diagrama de señal original

对应完整代码

# 采样点选择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).

Sin valor absoluto de amplitud bilateral

对应完整代码如下

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

Espectro de amplitud bilateral no normalizado

3. Normalización

La figura, el lado izquierdo del primer valor es 从原始信号中提取出来的0Hzuna 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:

  1. En este ejemplo, la amplitud correspondiente del componente de CC = 14000/1400 = 10
  2. 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:

  1. 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

Espectro normalizado bilateral
对应完整代码

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.

Espectro de amplitud unilateral normalizado

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:

  1. Frecuencia normalizada en el procesamiento de señales digitales
  2. Use python (scipy y numpy) para implementar la transformación rápida de Fourier (FFT), el tutorial más detallado
  3. Después de obtener el número complejo después de FFT, ¿cómo encontrar la frecuencia basada en este número complejo?
  4. Determinación de frecuencia y amplitud FFT
  5. En la transformada de Fourier, la fórmula de conversión entre la frecuencia circular w y la frecuencia f

Supongo que te gusta

Origin blog.csdn.net/weixin_39591031/article/details/110392352
Recomendado
Clasificación