You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python中基于多FFT生成频谱图:现有代码结果不符预期

问题分析与解决方案

我明白你的问题所在了——你用错工具啦!scipy.signal.spectrogram是用来处理原始时域信号的,它会把时域信号切成多个小段,每个小段做FFT,最终生成时频图(X轴时间、Y轴频率、颜色对应功率)。但你输入的已经是单份FFT频域数据,用这个函数相当于把FFT结果当成时域信号再做一次分帧FFT,结果自然和你想要的完全不符。

你想要的是:一条水平的色块条(对应单个时间点的FFT结果),Y轴表示频率,每个位置的颜色对应该频率点的FFT数值。那直接可视化你的FFT数据就行,完全不需要用spectrogram

正确实现代码

下面是适配你需求的完整示例,假设你的data是2048点的FFT结果(幅度谱或功率谱均可):

import numpy as np
import matplotlib.pyplot as plt

# 替换成你的实际FFT数据
data = np.random.rand(2048)  # 模拟2048个浮点数的FFT结果
Fs = 2048  # 采样率,和你原代码保持一致

# 生成频率轴:默认用单边频谱(0到Fs/2),适合大多数场景
n = len(data)
f = np.linspace(0, Fs/2, n//2 + 1)
# 如果你的FFT是包含负频率的双边谱,替换成这行:
# f = np.fft.fftfreq(n, 1/Fs)

# 把一维FFT数据转成2D数组(pcolormesh要求输入为二维)
# 时间轴只保留一个点,对应单份FFT的时刻
Sxx = data[:len(f)].reshape(1, -1)  # 取单边频谱部分,转成(1, 频率点数)格式
t = [0]  # 单个时间点标记

# 绘制水平颜色条
plt.pcolormesh(t, f, Sxx.T, shading='auto')  # 转置Sxx让频率对应Y轴
plt.ylabel('Frequency (Hz)')
plt.xlabel('Time')
plt.title('Single FFT Spectrum as Horizontal Color Bar')
plt.colorbar(label='FFT Value')
plt.xticks(t)  # 只显示单个时间点刻度
plt.show()

关键细节说明

  • 频率轴适配:如果你的FFT是双边谱(包含负频率),直接用np.fft.fftfreq生成完整频率轴,同时去掉data[:len(f)]的截取操作;如果是单边谱(仅保留正频率),用np.linspace生成0到Fs/2的频率点即可。
  • 二维数组转换pcolormesh要求输入二维数据,我们把一维FFT转成(1, N)的二维格式,这样绘制出来就是对应单个时间点的水平色块条。
  • 转置操作Sxx.T是为了让频率对应Y轴、时间对应X轴,符合你的可视化需求。

如果你的FFT数据是4096点,只需要修改len(data)的对应值、调整采样率Fs即可,代码逻辑完全通用。

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

火山引擎 最新活动