Comment FFT (Fast Fourier Transform) pour trouver l'amplitude et la fréquence (super détaillé, y compris le processus de dérivation)


Comment FFT (Fast Fourier Transform) pour trouver l'amplitude et la fréquence (super détaillé, y compris le processus de dérivation)

Afin de connaître cette réponse, j'ai vérifié beaucoup d'informations et les ai résumées.

注:本文代码的头文件等如下

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. Battez une châtaigne


Nous fixons

La fréquence d'échantillonnage est Fs La fréquence de signal la plus élevée est F Le nombre de points d'échantillonnage est N

Et il y a un signal avec la forme d'onde suivante. Les composantes de fréquence du signal 0Hz, 200Hz, 400Hzet 600Hzdes quatre 标准正弦函数composants.
Schéma de signal d'origine

对应完整代码

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


On peut voir que dans cet exemple

Fréquence d'échantillonnage Fs Fréquence du signal F Nombre de points d'échantillonnage N
1400 Hz 600 Hz 1 400

Donc, après la transformée de Fourier rapide (FFT), nous l'obtiendrons N个复数. Chaque valeur complexe contient 一个特定频率的信息. D'après ces N nombres complexes, on peut connaître les fréquences obtenues en séparant le signal d'origine et leurs valeurs d'amplitude.

对应代码

fft_y = fft(y)  # 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组


2. Trouvez l'amplitude

1. Transformée de Fourier rapide

Selon les données obtenues après la transformée de Fourier rapide, le graphe irrégulier suivant peut être dessiné.
(Ici, concentrez-vous d'abord sur l'axe vertical, et l'axe horizontal sera expliqué dans la section suivante.)

Pas de valeur absolue d'amplitude bilatérale

对应完整代码如下

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. Trouvez la valeur absolue d'un nombre complexe

Le graphe dessiné directement avec des nombres complexes n'est pas ce dont nous avons besoin. La valeur absolue (longueur modulaire) de tous les N nombres complexes doit être trouvée en premier

abs_y = np.abs(fft_y)  # 取复数的绝对值,即复数的模

Sur cette base, l'image suivante peut être dessinée

Spectre d'amplitude bilatéral non normalisé

3. Normalisation

La figure, le côté gauche de la première valeur est 从原始信号中提取出来的0Hzune intensité de signal correspondante (amplitude du signal), également connue 直流分量. Son amplitude de signal correspondante est 当前值/FFT的采样点数N, à savoir

Amplitude correspondante 0Hz = valeur actuelle / nombre de points d'échantillonnage N

Remarque:

  1. Dans cet exemple, l'amplitude correspondante de la composante CC = 14000/1400 = 10
  2. La valeur actuelle est la valeur absolue (longueur modulo) obtenue à partir du nombre complexe actuel

L'amplitude du signal correspondant aux composants autres que le composant DC 当前值/(采样点数N/2)est:

Amplitude correspondant aux autres fréquences = valeur actuelle / (nombre de points d'échantillonnage N / 2)

Remarque:

  1. Dans cet exemple, 200Hz correspond à une amplitude = 5000 / (1400/2) ≈ 7,14 (5000 ici est la valeur estimée obtenue en regardant l'image, juste par exemple, pas forcément précise), les autres fréquences correspondent au même algorithme d'amplitude .


Donc, après normalisation, nous obtenons le chiffre suivant

Spectre normalisé bilatéral
对应完整代码

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()

sommaire

Amplitude du composant CC (0 Hz) Autre amplitude de fréquence
La valeur absolue du nombre complexe obtenu par fft / N La valeur absolue du nombre complexe obtenu par fft / (N / 2)


Trois. Trouvez la fréquence

Mettez d'abord un paragraphe de texte ici, qui explique la méthode pour trouver la fréquence plus vivement.

Par exemple, vous avez un signal analogique avec la fréquence la plus élevée f = 32 kHz et une fréquence d'échantillonnage de 64 kHz. Effectuez une analyse FFT à 16 points sur ce signal. La plage de l'indice du point d'échantillonnage n est 0, 1, 2, 3, …, 15. Ensuite, la fréquence analogique de 64 kHz est divisée en 16 parties, chaque partie est de 4 kHz, cette 4 kHz est appelée résolution de fréquence.
Par conséquent, en abscisse du diagramme de fréquence:
n = 1 correspond à f est 4kHz
n = 2 correspond à f est 8kHz

n = 15 correspond à f est 60kHz
et le spectre de fréquence est symétrique autour de n = 8, attention juste à n = 0 Un spectre de ~ 7 est suffisant. Parce que la fréquence la plus élevée du signal d'origine est de 32 kHz.
(Ce paragraphe est adapté de la référence 1)


1. Formule de fréquence

Par conséquent, après avoir connu la fréquence d'échantillonnage Fs, la fréquence réelle correspondant à la xième (x à partir de 0) valeur complexe après la transformée de Fourier rapide (FFT) est

f (x) = x * (Fs / n)

Donc, dans cet exemple,

La fréquence du 0e point f (0) = 0 * (1400/1400) = 0
La fréquence du premier point f (0) = 1 * (1400/1400) = 1
La fréquence du deuxième point f (0) = 2 * (1400/1400) = 2

la fréquence du 200e point f (200) = 200 * (1400/1400) = 200

la fréquence du 1400e point f (200) = 1400 * (1400/1400) = 1400
(En raison de la coïncidence, la fréquence correspondant au x-ième point est exactement x)

Nous savons maintenant pourquoi la valeur des coordonnées de l'axe x est définie de cette manière.

2. Supprimer les valeurs en double

Seule la moitié de la fréquence de 0 à N / 2 est valide, et l'autre moitié est symétrique à cette moitié. Après avoir supprimé la duplication, nous obtenons l'image suivante

Spectre d'amplitude unilatéral normalisé

Correspondant au code complet:

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()

sommaire

Parmi les n valeurs complexes obtenues après FFT, la fréquence f (x) correspondant à la xième valeur complexe (x à partir de 0) est

f (x) = x * (Fs / n)



Annexe: code complet

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()


Annexe: Processus de dérivation

Pour plus de détails, voir la formule de conversion entre la fréquence circulaire w et la fréquence f dans la transformée de Fourier




Matériel de référence:

  1. Fréquence normalisée dans le traitement du signal numérique
  2. Utilisez python (scipy et numpy) pour implémenter la transformation de Fourier rapide (FFT) le tutoriel le plus détaillé
  3. Après avoir obtenu le nombre complexe après FFT, comment trouver la fréquence en fonction de ce nombre complexe?
  4. Détermination de la fréquence et de l'amplitude FFT
  5. Dans la transformée de Fourier, la conversion de formule entre la fréquence circulaire w et la fréquence f

Je suppose que tu aimes

Origine blog.csdn.net/weixin_39591031/article/details/110392352
conseillé
Classement