python实现FFT+滤波

python实现FFT+滤波demo

日期:2020.08.02
功能:
产生4个正弦波的原始信号采用FFT将其提取出来并图形化展示, 滤波得到原来的分项数据,并图形化展示

import matplotlib.pyplot as plt
import numpy as np
from scipy.fftpack import fft, ifft
import copy

plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
plt.rcParams['axes.unicode_minus'] = False  # 显示负号

# 根据采样定理知采样频率要>信号频率的2倍
# 设置的信号频率分量最高为400赫兹,因此采样点选择1000个
x = np.linspace(0, 1, 1000, endpoint = False)
# 产生原始信号——一个直流信号和四个正弦波的叠加
y = 2 + 4 * np.sin(2 * np.pi * 100 * x) + 6 * np.sin(2 * np.pi * 200 * x) + 8 * np.sin(
    2 * np.pi * 300 * x) + 10 * np.sin(2 * np.pi * 400 * x)
fft_y = fft(y)  # 对y进行傅里叶变换
fd = abs(fft(y))  # 幅度谱
normalization_fd = fd / (len(x) / 2)  # 归一化
normalization_fd[0] = normalization_fd[0] / 2  # 第一个点为直流分量,它的模值就是直流分量的N倍
half_normalization_fd = normalization_fd[range(int(len(x) / 2))]  # 由于对称性,只取一半区间
x = np.arange(len(y))
half_x = x[range(int(len(x) / 2))]  # 取一半区间

plt.subplot(331)
plt.plot(x[0:50], y[0:50])  # 由于采样点太过密集,看起来不好看,我们只显示前面的50组数据
plt.title('原始信号')

plt.subplot(332)
plt.plot(x, fd, 'r')
plt.title('未归一化的幅度谱')

plt.subplot(333)
plt.plot(x, normalization_fd, 'g')
plt.title('归一化后的幅度谱')

plt.subplot(334)
plt.plot(half_x, half_normalization_fd, 'b')
plt.title('归一化后的幅度谱(一半)')

# =============================滤波=============================
filter_y1 = copy.deepcopy(half_normalization_fd)
for i in range(len(half_x)):
    if i > 0:
        filter_y1[i] = 0
filter_y1 = np.fft.ifft(filter_y1)  # =============逆变换========
filter_y1 = filter_y1 * len(x) / 2  # 归一化的逆运算
plt.subplot(335)
plt.plot(half_x[:50], filter_y1[:50], 'g')
plt.title('第一个信号滤波结果')

filter_y2 = copy.deepcopy(half_normalization_fd)
for i in range(len(half_x)):
    if i < 50 or i > 150:
        filter_y2[i] = 0
filter_y2 = np.fft.ifft(filter_y2)
filter_y2 = filter_y2 * len(x) / 2
plt.subplot(336)
plt.plot(half_x[:50], filter_y2[:50], 'g')
plt.title('第二个信号滤波结果')

filter_y3 = copy.deepcopy(half_normalization_fd)
for i in range(len(half_x)):
    if i < 150 or i > 250:
        filter_y3[i] = 0
filter_y3 = np.fft.ifft(filter_y3)
filter_y3 = filter_y3 * len(x) / 2
plt.subplot(337)
plt.plot(half_x[:50], filter_y3[:50], 'g')
plt.title('第三个信号滤波结果')

filter_y4 = copy.deepcopy(half_normalization_fd)
for i in range(len(half_x)):
    if i < 250 or i > 350:
        filter_y4[i] = 0
filter_y4 = np.fft.ifft(filter_y4)
filter_y4 = filter_y4 * len(x) / 2
plt.subplot(338)
plt.plot(half_x[:50], filter_y4[:50], 'g')
plt.title('第四个信号滤波结果')

filter_y5 = copy.deepcopy(half_normalization_fd)
for i in range(len(half_x)):
    if i < 350:
        filter_y5[i] = 0
filter_y5 = np.fft.ifft(filter_y5)
filter_y5 = filter_y5 * len(x) / 2
plt.subplot(339)
plt.plot(half_x[:50], filter_y5[:50], 'g')
plt.title('第五个信号滤波结果')
plt.show()
嗯,Python中的fft滤波可以通过以下步骤实现: 1. 读取需要滤波的信号数据,并对其进行预处理,如去除直流分量、归一化等。 2. 对信号进行傅里叶变换,得到频率域上的信号。 3. 对频率域信号进行滤波处理,可以采用低通、高通、带通等滤波器。 4. 对滤波后的频率域信号进行傅里叶反变换,得到时间域上的滤波信号。 以下是一个简单的示例代码: ```python import numpy as np import matplotlib.pyplot as plt # 读取信号数据 data = np.loadtxt('signal.txt') # 去除直流分量 mean = np.mean(data) data = data - mean # 归一化 data = data / np.max(np.abs(data)) # 进行傅里叶变换,得到频率域信号 fft_data = np.fft.fft(data) # 构造一个低通滤波器,截止频率为100Hz cutoff_freq = 100 sampling_freq = 1000 num_samples = data.shape[0] freqs = np.fft.fftfreq(num_samples, 1/sampling_freq) filter_mask = np.abs(freqs) <= cutoff_freq fft_data_filtered = fft_data * filter_mask # 进行傅里叶反变换,得到时间域上的滤波信号 data_filtered = np.real(np.fft.ifft(fft_data_filtered)) # 绘制原始信号和滤波后的信号的时域波形和频域波形 fig, axs = plt.subplots(2, 2, figsize=(10, 6)) axs[0, 0].plot(data) axs[0, 0].set_title('Original Signal (Time Domain)') axs[0, 1].plot(freqs[:num_samples//2], np.abs(fft_data[:num_samples//2])) axs[0, 1].set_title('Original Signal (Frequency Domain)') axs[1, 0].plot(data_filtered) axs[1, 0].set_title('Filtered Signal (Time Domain)') axs[1, 1].plot(freqs[:num_samples//2], np.abs(fft_data_filtered[:num_samples//2])) axs[1, 1].set_title('Filtered Signal (Frequency Domain)') plt.show() ``` 其中,`signal.txt`为需要进行滤波的信号数据文件,代码中使用了一个简单的低通滤波器。你可以根据实际需求自行调整滤波器的类型和参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值