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

如何从信号FFT中提取频率与对应幅值?求更优实现方法

问题描述

我有一个包含1.2Hz/9Hz/15Hz频率成分的信号,生成代码如下:

import numpy as np
import matplotlib.pyplot as plt

total_time = 5
sampling_frequency = 100

t = np.linspace(0, total_time, total_time * sampling_frequency, endpoint=False)
signal = np.sin(2 * np.pi * 1.2 * t) + 0.5*np.cos(2 * np.pi * 9 * t) + 0.75*np.sin(2 * np.pi * 15.0 * t)
plt.plot(t, signal)

对应的离散FFT实现代码:

fft_spectrum = np.fft.rfft(signal)
fft_spectrum_abs = np.abs(fft_spectrum) * 2 / (total_time * sampling_frequency)

freq = np.fft.rfftfreq(signal.size, d=1./sampling_frequency)

plt.plot(freq, fft_spectrum_abs)
plt.xlabel("frequency, Hz")
plt.ylabel("amplitude, units")
plt.show()

我需要从FFT结果中提取频率与对应幅值,当前使用的实现:

[
    (amp, freq) for amp, freq in sorted(zip(fft_spectrum_abs, freq), 
    key=lambda pair: pair[0]) if amp > 0.1
]
# 输出结果: [(0.4999999999999984, 9.0), (0.749999999999999, 15.0), (1.0, 1.2000000000000002)]

这个方法结果正确,但感觉是临时方案,请问有没有更优的实现方式?


更优实现方案

1. 用NumPy向量化操作提升效率

列表推导式属于Python层面的循环,处理大规模数据时效率偏低。改用NumPy布尔索引直接筛选,再利用数组排序,能大幅提升性能:

# 生成幅值阈值的布尔掩码
mask = fft_spectrum_abs > 0.1
# 筛选符合条件的幅值和频率
filtered_amps = fft_spectrum_abs[mask]
filtered_freqs = freq[mask]

# 获取按幅值排序的索引
sorted_idx = np.argsort(filtered_amps)
# 组合成排序后的(幅值, 频率)对
result = list(zip(filtered_amps[sorted_idx], filtered_freqs[sorted_idx]))

2. 基于峰值检测的精准提取

如果信号存在噪声,单纯阈值筛选可能误判噪声峰值。使用scipy.signal.find_peaks检测频谱中的真实峰值,能有效排除干扰:

from scipy.signal import find_peaks

# 检测峰值:设置最小高度(阈值)和最小距离避免相邻伪峰
peaks, _ = find_peaks(fft_spectrum_abs, height=0.1, distance=5)

# 获取峰值对应的幅值和频率
peak_amps = fft_spectrum_abs[peaks]
peak_freqs = freq[peaks]

# 按幅值排序
sorted_idx = np.argsort(peak_amps)
result = list(zip(peak_amps[sorted_idx], peak_freqs[sorted_idx]))

这种方式更适合实际带噪场景,只提取真正的信号成分。

3. 修正浮点数精度问题

结果中1.2Hz显示为1.2000000000000002是浮点数精度导致的,可通过格式化或四舍五入处理:

# 批量四舍五入到2位小数
peak_freqs_rounded = np.round(peak_freqs, 2)
result = list(zip(peak_amps[sorted_idx], peak_freqs_rounded[sorted_idx]))
# 输出: [(0.5, 9.0), (0.75, 15.0), (1.0, 1.2)]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:08:17