You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中使用FFT对信号进行频率滤波?

用FFT滤除正弦信号的特定频率分量

很棒的选择——从简单的单频正弦波开始上手FFT滤波,绝对是快速理解频域处理逻辑的好办法!我来帮你把代码补全,还会一步步拆解每个环节的作用,让你清楚怎么实现滤除3Hz分量的目标。

完整实现代码

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fftfreq, irfft, rfft

# 1. 生成测试用的3Hz正弦波信号
t = np.linspace(0, 2*np.pi, 1000, endpoint=True)
target_freq = 3.0  # 目标频率(Hz)
amplitude = 100.0  # 信号振幅
raw_signal = amplitude * np.sin(2*np.pi*target_freq*t)

# 2. 计算采样相关参数
sample_interval = t[1] - t[0]  # 采样间隔
sample_rate = 1 / sample_interval  # 采样率
sample_count = len(raw_signal)  # 总采样点数

# 3. 对实信号做快速傅里叶变换(FFT)
freq_axis = fftfreq(sample_count, sample_interval)  # 生成频率轴
fft_result = rfft(raw_signal)  # rfft专为实信号优化,只返回正频率部分

# 4. 设计滤波器:精准滤除3Hz分量
# 考虑浮点精度误差,用小容差锁定目标频率范围
freq_tolerance = 0.1
# 创建掩码:保留所有非3Hz的频率分量
filter_mask = np.logical_or(
    np.abs(freq_axis[:len(fft_result)]) < (target_freq - freq_tolerance),
    np.abs(freq_axis[:len(fft_result)]) > (target_freq + freq_tolerance)
)
# 将目标频率的FFT系数置0
fft_result[~filter_mask] = 0.0

# 5. 逆FFT转换回时域信号
filtered_signal = irfft(fft_result)

# 6. 可视化原始信号、频谱和滤波结果
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 8))

# 原始信号时域图
ax1.plot(t, raw_signal)
ax1.set_title('原始3Hz正弦波(时域)')
ax1.set_xlabel('时间(秒)')
ax1.set_ylabel('振幅')

# FFT频谱图
ax2.plot(freq_axis[:len(fft_result)], np.abs(fft_result))
ax2.set_title('信号频域频谱')
ax2.set_xlabel('频率(Hz)')
ax2.set_ylabel('频谱幅度')
ax2.axvline(x=target_freq, color='red', linestyle='--', label='待滤除的3Hz分量')
ax2.legend()

# 滤波后信号时域图
ax3.plot(t, filtered_signal)
ax3.set_title('滤除3Hz分量后的信号(时域)')
ax3.set_xlabel('时间(秒)')
ax3.set_ylabel('振幅')

plt.tight_layout()
plt.show()

关键环节解释

  • 为什么用rfft而非普通fft? 因为我们处理的是实信号,rfft只计算正频率部分,比标准FFT节省一半的计算资源,后续用irfft还能自动处理共轭对称性,完美还原实信号。
  • 频率容差的必要性:由于采样点数有限,FFT的频率轴是离散的,可能无法精确对齐3Hz,设置小容差可以避免因浮点误差漏掉目标频率分量。
  • 滤波核心逻辑:FFT的本质是把时域信号分解成不同频率的正弦/余弦波叠加,在频域把对应频率的系数置0,就相当于在时域中移除了该频率的信号分量。

新手进阶提示

  1. 奈奎斯特采样定理:采样率必须大于信号最高频率的2倍,这里我们的采样率约159Hz,远高于3Hz的2倍,完全符合要求。
  2. 复杂信号适配:如果处理多频混合或带噪声的信号,只需调整filter_mask的逻辑即可实现低通/高通/带通滤波,比如要保留0-2Hz的分量,就把掩码设为freq_axis[:len(fft_result)] <= 2。
  3. 频谱幅度修正:实信号的rfft结果中,除了0Hz和奈奎斯特频率,其他频率的幅度是实际振幅的2倍,若需要精准对应原始信号振幅,记得做除以2的修正。

内容的提问来源于stack exchange,提问作者Kev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:24:23