• 【Python】通过Fourier变换实现频域滤波



    fftpack将被弃用,推荐使用 scipy.fft

    简介

    Fourier变换极其逆变换在数学上的定义如下

    F ( ω ) = ∫ − ∞ ∞ f ( t ) e − i ω t d t f ( t ) = π 2 ∫ − ∞ ∞ F ( ω ) e i ω t d ω F(\omega)=\int^\infty_{-\infty}f(t)e^{-i\omega t}\text dt\\ f(t)=\frac{\pi}{2}\int^\infty_{-\infty}F(\omega)e^{i\omega t}\text d\omega F(ω)=f(t)etdtf(t)=2πF(ω)etdω

    scipy中的Fourier变换函数位于fftpack模块中,下表整理出一部分与Fourier变换相关的函数,其中FFT为快速Fourier变换(Fast Fourier Transform);DCT为离散余弦变换(Discrete Cosine Transform);DST为离散正弦变换(discrete sine transform),另外,函数的前缀有如下含义

    • i 表示逆变换;
    • r 表示实数域,如开头无r表示在复数域
    函数说明
    fft, ifft, rfft, irfftFFT算法
    dct, idctDCT算法
    dst, idstDST算法
    fft2, ifft2复数域二维FFT
    fftn, ifftn复数域高维FFT
    fftshift, ifftshift
    rfftshift, irfftshift
    移动FFT的频谱,使得直流分量占据中心
    fftfreqFFT计算结果所对应的频率

    在数值计算中,一切输入输出均为离散值,所以实际上用到的是离散Fourier变换,即DFT,其功能是将离散的采样变换为一个离散的频谱分布。

    实操

    下面将手动创建一组采样点,并添加一点噪声,然后通过FFT获取其频域信息。

    import numpy as np
    from scipy import fftpack
    
    PI = np.pi*2
    fs = 60     #采样频率
    T = 100     #采样周期数
    N = fs*T    #采样点
    t = np.linspace(0, T, N)
    s = 2 * np.sin(PI * t) + 3 * np.sin(22 * PI * t) + 2 * np.random.randn(*t.shape)
    F = fftpack.fft(s)
    f = fftpack.fftfreq(N, 1.0/fs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    其中,t为时间序列,s为模拟的采样点,F是Fourier变换之后的结果。但由于fft默认是在复数域上的,故而可以查看其实部、虚部、模和辐角的值。

    下面对采样点以及Fourier变换的结果进行绘制

    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(2,2,1)
    ax.plot(t, s)
    ax.set_title("t vs s")
    f_abs = np.abs(F)
    ax = fig.add_subplot(2,2,2)
    ax.plot(f, f_abs)
    ax.set_title("fs vs |F|")
    ax = fig.add_subplot(2,2,3)
    ax.stem(f, f_abs)
    ax.set_xlim([0,2])
    ax.set_title("fs vs |F|")
    ax = fig.add_subplot(2,2,4)
    ax.stem(f, f_abs)
    ax.set_title("fs vs |F|")
    ax.set_xlim([21,23])
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果为

    在这里插入图片描述

    f = 1 f=1 f=1 f = 22 f=22 f=22处被筛选了出来。

    频域滤波

    有了这个,就可以在频域上对数据进行滤波,其思路是,对f_abs中的值进行阈值分割,例如,只筛选出低频部分,然后看一下滤波效果

    fig = plt.figure(1)
    f_filt = F * (np.abs(f) < 2)
    s_filt = fftpack.ifft(f_filt)
    ax = fig.add_subplot()
    ax.plot(t, s, lw=0.2)
    ax.plot(t, s_filt.real, lw=2)
    ax.set_title("threshold=2")
    ax.set_xlim([0,10])
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    效果如下

    在这里插入图片描述

  • 相关阅读:
    Android Studio 插件开发1、创建标题 通知等
    Linux内核源码的make zImage过程
    Flutter快学快用03 Hello Flutter:三步法掌握 Flutter,开始你的第一个应用
    Java异常:基本概念、分类和处理
    MATLAB算法实战应用案例精讲-【集成算法】集成学习模型stacking(附Python和R语言代码)
    Rsync远程同步+inotify监控
    ROS机器人应用(4)—— 查看里程计、IMU 话题信息
    即将开幕!阿里云飞天技术峰会邀您一同探秘云原生最佳实践
    【CAD二次开发】重新加载acad.pgp快捷菜单文件
    通过ffmpeg 下载在线的.m3u8格式视频
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/127743332