|
单频信号的FFT与幅度谱和相位谱(Python)
- import numpy as np
- from scipy.fftpack import fft, ifft
- import matplotlib.pyplot as plt
- from matplotlib.font_manager import FontProperties
- font = FontProperties(fname="/usr/share/fonts/wps-office/simfang.ttf")
- # 单频信号的FFT与幅度谱和相位谱(Python)
- # 这里设置采样频率为1400赫兹(即一秒内有1400个采样点,一样意思的)
- # 一般实际应用中保证采样频率为信号最高频率的2.56~4倍
- fs = 1400
- x_time = np.linspace(0, 1, fs, endpoint=True) # 1是时宽
- print("1秒采样了多少个点=", len(x_time))
- # 1秒采样多少个点 1400个点 fs=1400
- # x_time = np.arange(0, 1, 1/N)
- # 设置需要采样的信号,频率分量有200,400和600
- f0 = 200
- # y = 7 * np.sin(2 * np.pi * 200 * x_time) + 5 * np.sin(2 * np.pi * 400 * x_time) + 3 * np.sin(2 * np.pi * 600 * x_time)
- y = 7 * np.cos(2 * np.pi * f0 * x_time)
- print("信号周期=%.5f,采样周期=%.5f" % (1/f0, 1/fs))
- fft_y = fft(y) # 快速傅里叶变换
- yreal = fft_y.real # 获取实数部分
- yimag = fft_y.imag # 获取虚数部分
- print("快速傅里叶变换后的长度=%d;看看前面的值=" % len(fft_y), fft_y[:5])
- # 变换之后的结果数据长度和原始采样信号是一样的
- # 每一个变换之后的值是一个复数,为a+bj的形式
- # “振幅谱”“相位谱”,它其实就是通过对快速傅里叶变换得到的复数结果进一步求出来的
- # FFT得到的复数的模(即abs)就是对应的“幅度谱”,复数所对应的相角,就是所对应的“相位谱”
- x_f = np.arange(fs) # 频率的序列 从0到采样率 频率步进为1
- # 实信号是双边频谱
- # x_f = np.arange(-fs/2, fs/2, 1) 还不能这样操作
- half_x_f = x_f[range(int(fs/2))] # 取一半 因为 振幅谱 是偶函数 相位谱 是奇函数
- abs_y = np.abs(fft_y) # 取复数的绝对值,即复数的模(双边频谱)
- angle_y = np.angle(fft_y) # 取复数的角度
- # 我们发现,振幅谱的纵坐标很大,而且具有对称性
- # 关键:关于振幅值很大的解释以及解决办法——归一化和取一半处理
- normalization_abs_y = abs_y / fs # 归一化处理(双边频谱)
- normalization_half_abs_y = normalization_abs_y[range(int(fs / 2))] # 由于对称性,只取前一半区间(单边频谱)
- plt.figure(figsize=(16, 12))
- plt.subplot(231)
- plt.plot(x_time[:20], y[:20], marker='o', markersize=8, markerfacecolor='r')
- plt.title('原始采样后波形', fontproperties=font, fontsize=20)
- plt.xlabel('time')
- plt.subplot(232)
- plt.plot(x_f, fft_y, 'black')
- plt.title('实信号的双边频谱(两个冲激)', fontproperties=font, fontsize=16)
- plt.xlabel('freq')
- plt.subplot(233)
- plt.plot(x_f, abs_y, 'r')
- plt.title('双边幅度谱(未归一化)', fontproperties=font, fontsize=16)
- plt.xlabel('freq')
- plt.subplot(234)
- plt.plot(x_f, angle_y, 'violet')
- plt.title('双边相位谱', fontproperties=font, fontsize=16)
- plt.xlabel('freq')
- plt.subplot(235)
- plt.plot(x_f, normalization_abs_y, 'g')
- plt.title('双边幅度谱(归一化的)', fontproperties=font, fontsize=16)
- plt.xlabel('freq')
- plt.subplot(236)
- plt.plot(half_x_f, normalization_half_abs_y, 'blue')
- plt.title('单边幅度谱(归一化的)', fontproperties=font, fontsize=16)
- plt.xlabel('freq')
- # plt.savefig('fft.png', dpi=200)
- plt.show()
复制代码
|
|