python - 时变频率的频谱图与标度图

标签 python signal-processing fft wavelet pywavelets

我正在比较特定信号的 FFT 与 CWT。

我不清楚如何从 CWT 的相应比例图中读取相应的频率和幅度。此外,我的印象是 CWT 相当不精确?

频谱图在预测精确频率方面似乎相当不错,但对于 CWT,我尝试了许多不同的小波,结果都是一样的。

我监督了什么吗?这不是解决这个问题的合适工具吗?

在下面,您可以找到我的示例源代码和相应的图。

import matplotlib.pyplot as plt
import numpy as np
from numpy import pi as π
from scipy.signal import spectrogram
import pywt

f_s = 200              # Sampling rate = number of measurements per second in [Hz]
t   = np.arange(-10,10, 1 / f_s) # Time between [-10s,10s].
T1  = np.tanh(t)/2  + 1.0 # Period in [s]
T2  = 0.125               # Period in [s]
f1  = 1 / T1              # Frequency in [Hz]
f2  = 1 / T2              # Frequency in [Hz] 

N = len(t)
x = 13 * np.sin(2 * π * f1 * t) + 42 * np.sin(2 * π * f2 * t)

fig, (ax1, ax2, ax3, ax4) = plt.subplots(4,1, sharex = True, figsize = (10,8))

# Signal
ax1.plot(t, x)
ax1.grid(True)
ax1.set_ylabel("$x(t)$")
ax1.set_title("Signal x(t)")

# Frequency change
ax2.plot(t, f1)
ax2.grid(True)
ax2.set_ylabel("$f_1$ in [Hz]")
ax2.set_title("Change of frequency $f_1(t)$")

# Moving fourier transform, i.e. spectrogram
Δt = 4 # window length in [s]
Nw = np.int(2**np.round(np.log2(Δt * f_s))) # Number of datapoints within window
f, t_, Sxx = spectrogram(x, f_s, window='hanning', nperseg=Nw, noverlap = Nw - 100, detrend=False, scaling='spectrum')
Δf  =  f[1] - f[0]
Δt_ = t_[1] - t_[0]
t2  = t_ + t[0] - Δt_

im = ax3.pcolormesh(t2, f - Δf/2, np.sqrt(2*Sxx), cmap = "inferno_r")#, alpha = 0.5)
ax3.grid(True)
ax3.set_ylabel("Frequency in [Hz]")
ax3.set_ylim(0, 10)
ax3.set_xlim(np.min(t2),np.max(t2))
ax3.set_title("Spectrogram using FFT and Hanning window")

# Wavelet transform, i.e. scaleogram
cwtmatr, freqs = pywt.cwt(x, np.arange(1, 512), "gaus1", sampling_period = 1 / f_s)
im2 = ax4.pcolormesh(t, freqs, cwtmatr, vmin=0, cmap = "inferno" )  
ax4.set_ylim(0,10)
ax4.set_ylabel("Frequency in [Hz]")
ax4.set_xlabel("Time in [s]")
ax4.set_title("Scaleogram using wavelet GAUS1")

# plt.savefig("./fourplot.pdf")

plt.show()

Plot

最佳答案

您的示例波形在任何给定时间仅由几个纯音组成,因此频谱图看起来非常干净和可读。
相比之下,小波图将看起来“困惑”,因为您必须对可能不同尺度(以及频率)的高斯小波求和,以近似原始信号中的每个分量纯音。
短时 FFT 和小波变换都属于时频变换范畴,但具有不同的内核。 FFT的核是纯音​​,但是你提供的小波变换的核是高斯小波。 FFT 纯音内核将与您在问题中显示的波形类型完全对应,但小波内核不会。
我怀疑您对不同小波得到的结果在数值上是否完全相同。肉眼看起来可能与您绘制的方式相同。看来您将小波用于错误的目的。小波在分析信号方面比绘制信号更有用。小波分析是独一无二的,因为小波组合中的每个数据点都同时编码频率、相位和窗口信息。这允许设计位于时间序列和频率分析之间的连续体上的算法,并且可以非常强大。
至于您对不同小波给出相同结果的说法,这是 显然不是真的对于所有小波:我调整了你的代码,它产生了跟随它的图像。当然,GAUS2 和 MEXH 似乎产生了相似的图(放大真正接近,你会发现它们有细微的不同),但那是因为二阶高斯小波看起来类似于墨西哥帽小波。


import matplotlib.pyplot as plt
import numpy as np
from numpy import pi as π
from scipy.signal import spectrogram, wavelets
import pywt
import random


f_s = 200              # Sampling rate = number of measurements per second in [Hz]
t   = np.arange(-10,10, 1 / f_s) # Time between [-10s,10s].
T1  = np.tanh(t)/2  + 1.0 # Period in [s]
T2  = 0.125               # Period in [s]
f1  = 1 / T1              # Frequency in [Hz]
f2  = 1 / T2              # Frequency in [Hz] 

N = len(t)
x = 13 * np.sin(2 * π * f1 * t) + 42 * np.sin(2 * π * f2 * t)

fig, (ax1, ax2, ax3, ax4) = plt.subplots(4,1, sharex = True, figsize = (10,8))


wvoptions=iter(['gaus1','gaus2','mexh','morl'])

axes=[ax1,ax2,ax3,ax4]


for ax in axes:
    # Wavelet transform, i.e. scaleogram
    try:
        choice=next(wvoptions)
        cwtmatr, freqs = pywt.cwt(x, np.arange(1, 512), choice, sampling_period = 1 / f_s)
        im = ax.pcolormesh(t, freqs, cwtmatr, vmin=0, cmap = "inferno" )  
        ax.set_ylim(0,10)
        ax.set_ylabel("Frequency in [Hz]")
        ax.set_xlabel("Time in [s]")
        ax.set_title(f"Scaleogram using wavelet {choice.upper()}")
    except:
        pass
# plt.savefig("./fourplot.pdf")

plt.tight_layout()
plt.show()
enter image description here

关于python - 时变频率的频谱图与标度图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54909178/

相关文章:

c++ - OFDM 频谱整形窗口

c++ - FFT 频谱显示不正确

c - 需要对近乎无限的数据点集进行 FFT

python - 如何在Python 3中重用父类(super class)方法的变量?

python - 酸洗时忽略不可酸洗的对象

javascript - WinJS 中的音频分析

c++ - 带通 FIR 滤波器

CUDA fft - Cooley tukey,如何利用并行性?

python - Python中int转string时如何指定格式?

python - 从 str 和 Enum 继承有哪些注意事项