东方耀AI技术分享

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4147|回复: 2
打印 上一主题 下一主题

[通信原理] 基于python(scipy和numpy)的快速傅里叶变换FFT

[复制链接]

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14439
QQ
跳转到指定楼层
楼主
发表于 2021-1-26 08:46:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

基于python(scipy和numpy)的快速傅里叶变换FFT


  1. import numpy as np
  2. from scipy.fftpack import fft, ifft
  3. import matplotlib.pyplot as plt
  4. from matplotlib.pylab import mpl
  5. # 基于python(scipy)的快速傅里叶变换FFT
  6. mpl.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
  7. mpl.rcParams['axes.unicode_minus'] = False  # 显示负号

  8. # fft简单滤波的步骤:
  9. # 1、将原信号进行FFT
  10. # 2、去掉需要滤波的频率
  11. # 3、逆变换得到信号数据

  12. # FFT——离散傅里叶变换(DFT)的快速算法。它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的
  13. # 采样点数为N。那么FFT之后结果就是一个为N点的复数。每一个点就对应着一个频率点。这个点的模值,就是该频率值下的幅度特性
  14. # 由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果

  15. # 采样点选择1400个,因为设置的信号频率分量最高为600赫兹,根据采样定理知采样频率要大于信号频率2倍,所以这里设置采样频率为1400赫兹(即一秒内有1400个采样点,一样意思的)
  16. # 一般实际应用中保证采样频率为信号最高频率的2.56~4倍
  17. N = 1400
  18. x_time = np.linspace(0, 1, N, endpoint=True)
  19. # x_time = np.arange(0, 1, 1/N)

  20. # 设置需要采样的信号,频率分量有200,400和600
  21. 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)

  22. print("变换之前,看看原始值:", y[:5])
  23. fft_y = fft(y)  # 快速傅里叶变换
  24. yreal = fft_y.real               # 获取实数部分
  25. yimag = fft_y.imag               # 获取虚数部分

  26. print("快速傅里叶变换后的长度=%d;看看前面的值=" % len(fft_y), fft_y[:5])
  27. # 变换之后的结果数据长度和原始采样信号是一样的
  28. # 每一个变换之后的值是一个复数,为a+bj的形式  复数具有模和角度
  29. # “振幅谱”“相位谱”,它其实就是通过对快速傅里叶变换得到的复数结果进一步求出来的
  30. # FFT得到的复数的模(即绝对值)就是对应的“振幅谱”,复数所对应的角度,就是所对应的“相位谱”


  31. x = np.arange(N)  # 频率个数
  32. half_x = x[range(int(N / 2))]  # 取一半区间

  33. abs_y = np.abs(fft_y)  # 取复数的绝对值,即复数的模(双边频谱)   振幅谱
  34. angle_y = np.angle(fft_y)  # 取复数的角度                     相位谱
  35. # 我们发现,振幅谱的纵坐标很大,而且具有对称性
  36. # 关键:关于振幅值很大的解释以及解决办法——归一化和取一半处理
  37. normalization_y = abs_y / N  # 归一化处理(双边频谱)
  38. normalization_half_y = normalization_y[range(int(N / 2))]  # 由于对称性,只取一半区间(单边频谱)

  39. plt.figure(figsize=(16, 8))

  40. plt.subplot(231)
  41. plt.plot(x_time, y)
  42. plt.title('原始波形')
  43. plt.xlabel('time')
  44. # plt.plot(x_time[:50], y[:50])
  45. # plt.title('原始波形(前50组样本)')

  46. plt.subplot(232)
  47. plt.plot(x, fft_y, 'black')
  48. plt.title('双边振幅谱(未求振幅绝对值)', fontsize=9, color='black')

  49. plt.subplot(233)
  50. plt.plot(x, abs_y, 'r')
  51. plt.title('双边振幅谱(未归一化)', fontsize=9, color='red')

  52. plt.subplot(234)
  53. plt.plot(x, angle_y, 'violet')
  54. plt.title('双边相位谱(未归一化)', fontsize=9, color='violet')

  55. plt.subplot(235)
  56. plt.plot(x, normalization_y, 'g')
  57. plt.title('双边振幅谱(归一化)', fontsize=9, color='green')

  58. plt.subplot(236)
  59. plt.plot(half_x, normalization_half_y, 'blue')
  60. plt.title('单边振幅谱(归一化)', fontsize=9, color='blue')

  61. # plt.savefig('fft.png', dpi=200)
  62. plt.show()
复制代码


fft.png (183.06 KB, 下载次数: 127)

fft.png
让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14439
QQ
沙发
 楼主| 发表于 2021-1-26 08:51:33 | 只看该作者
numpy中也有fft的实现:
from numpy import fft
fft_y = fft.fft(y)
让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14439
QQ
板凳
 楼主| 发表于 2021-1-26 08:53:05 | 只看该作者
东方耀 发表于 2021-1-26 08:51
numpy中也有fft的实现:
from numpy import fft
fft_y = fft.fft(y)
  1. import numpy as np
  2. import pandas as pd
  3. import math
  4. import matplotlib.pyplot as plt

  5. # 基于python(numpy)的快速傅里叶变换FFT
  6. x = np.linspace(0, 2 * np.pi, 50)
  7. # print(x)
  8. wave = np.cos(x)
  9. transformed = np.fft.fft(wave)  # 傅里叶变换

  10. # plt.plot(transformed) #绘制变换后的信号

  11. plt.plot(np.fft.ifft(transformed))  # 反变换

  12. plt.show()
复制代码
让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|人工智能工程师的摇篮 ( 湘ICP备2020019608号-1 )

GMT+8, 2024-5-19 16:19 , Processed in 0.184272 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表