python - STFT 的节能
问题描述
我正在进行的项目需要一个短时间的傅立叶变换。为此,我使用 scipy.signal.stft。从理论上我们得知,时域信号与时频域具有相同的能量;Parseval 定理 ( https://en.wikipedia.org/wiki/Parseval%27s_theorem )。但是,当我使用 scipy.signal.stft 时,如果比较两个能量值的计算,我不会获得相同数量的能量。我很确定,这是因为在使用 scipy.signal.stft 时涉及到一些缩放,所以我通过源代码吐槽。经过一番深入搜索,我找到了 np.sqrt(1/(sum(win)**2)) 的比例因子。但是,使用此比例因子不起作用:
示例代码:
fs = 10e3
N = 1e5
amp = 2 * np.sqrt(2)
noise_power = 0.01 * fs / 2
time = np.arange(N) / float(fs)
mod = 500*np.cos(2*np.pi*0.25*time)
carrier = amp * np.sin(2*np.pi*3e3*time + mod)
noise = np.random.normal(scale=np.sqrt(noise_power),
size=time.shape)
noise *= np.exp(-time/5)
x = carrier + noise
frame_size = 1000
window = scipy.signal.windows.hann(frame_size,sym=False)
f, t, Zxx = scipy.signal.stft(x, fs, window=window, nperseg=frame_size)
scale = np.sqrt(1/(sum(window)**2))
Zxx_scaled = Zxx/scale
Et=np.sum(x**2)
Ef=np.sum(abs(Zxx_scaled)**2)/N
print("Et = %.3f" % Et)
print( "Ef = %.3f" % Ef)
结果(取决于噪声,但在规模上):
Et = 1641328.607
Ef = 6158.539
有谁知道如何正确缩放生成的 STFT 矩阵值以获得相等的能级并证明 STFT 的能量守恒?
(我正在寻找一个sum(window)**2
恒定的变换(和窗口),并且由于在 STFT 和 I-STFT 中使用了窗口,因此如果我使用 hann 窗口,我假设我有一个“紧框架”变换。但是,证明能量守恒是第一步……)
解决方案
推荐阅读
- android - 在 Android 上构建圆框相机
- docker - 将文件从 kubernetes 集群传输到其他 ec2 机器
- python - 模块“socket”没有属性“getsockname”
- r - 如何从包含具有给定步骤的数字序列的 for 循环中填充向量?
- scala - ONE Process中akka和ThreadPool+BlockingQueue的本质区别是什么?
- node.js - 将数据存储在特定于节点 express js 中请求的变量中
- javascript - 在 php 文件中动态添加或删除输入字段
- ubuntu-16.04 - Bugzilla,无需登录即可查看错误
- dask - 如何在 influxdb 中编写 dask 数据帧而不将其转换为熊猫?
- python - 将不同位置的数据绘制为等高线图