我试图直接可视化离散小波变换(DWT)细节系数与原始信号/信号重构之间的关系。目的是以直观的方式显示它们之间的关系。我想问(请参阅下面的问题):到目前为止,我提出的想法和过程是否正确,如果对的话,最好在可视化它们之间的关系之前从原始信号中减去第一级近似值。

最小示例

这是我的解释的最小示例,我将Python的pywavelets的ECG示例数据(具有1024个值)作为简单的一维信号: br />
import pywt
import pywt.data
import numpy as np
import matplotlib.pyplot as plt

x = pywt.data.ecg()
plt.plot(x)
plt.legend(['Original signal'])




使用Symmlet 5进行分解,共有6个级别:

w = pywt.Wavelet('sym5')
plt.plot(w.dec_lo)
coeffs = pywt.wavedec(x, w, level=6)


(有意地)重构信号时,有意地忽略了较高级别的细节系数(为方便起见,信号在统一的x刻度[0,1]上绘制): >
def reconstruction_plot(yyy, **kwargs):
    """Plot signal vector on x [0,1] independently of amount of values it contains."""
    plt.plot(np.linspace(0, 1, len(yyy)), yyy, **kwargs)

reconstruction_plot(pywt.waverec(coeffs, w)) # full reconstruction 
#reconstruction_plot(pywt.waverec(coeffs[:-1] + [None] * 1, w)) # leaving out detail coefficients up to lvl 5
#reconstruction_plot(pywt.waverec(coeffs[:-2] + [None] * 2, w)) # leaving out detail coefficients up to lvl 4
#reconstruction_plot(pywt.waverec(coeffs[:-3] + [None] * 3, w)) # leaving out detail coefficients up to lvl 3
reconstruction_plot(pywt.waverec(coeffs[:-4] + [None] * 4, w)) # leaving out detail coefficients up to lvl 2
#reconstruction_plot(pywt.waverec(coeffs[:-5] + [None] * 5, w)) # leaving out detail coefficients up to lvl 1
reconstruction_plot(pywt.waverec(coeffs[:-6] + [None] * 6, w)) # leaving out all detail coefficients = reconstruction using lvl1 approximation only
plt.legend(['Full reconstruction', 'Reconstruction using detail coefficients lvl 1+2', 'Reconstruction using lvl 1 approximation only'])




上面的DWT产生一个24个值的1级近似矢量,一个24个值的1级细节系数矢量,一个40个值的2级细节矢量,等级3 of 72弗吉尼亚lues,135个值的4级,262个值的5级,516个值的6级:

plt.stem(coeffs[1]); plt.legend(['Lvl 1 detail coefficients'])
plt.stem(coeffs[2]); plt.legend(['Lvl 2 detail coefficients'])
plt.stem(coeffs[3]); plt.legend(['Lvl 3 detail coefficients'])
plt.stem(coeffs[4]); plt.legend(['Lvl 4 detail coefficients'])
plt.stem(coeffs[5]); plt.legend(['Lvl 5 detail coefficients'])
plt.stem(coeffs[6]); plt.legend(['Lvl 6 detail coefficients'])









我们似乎在原始信号的尖峰周围看到了清晰的图案(也请注意上面图的y比例)。

由于我的问题:


我们可以将这些系数直接与信号相关是正确的吗?系数的振幅对应于在信号上产生小波的振幅(y轴),系数的位置对应于时间(x轴)。还是我们之间需要考虑的事情?

在DWT之后,最终的lvl1近似仍然存在。不可视化细节系数与原始信号的关系,而是与原始信号减去lvl1近似值,是否有意义? (我知道,如果不这样做,我很可能还会看到系数和信号之间的关系,请参见下面的图。仅仅是因为这有意义还是不正确。如果对于lvl1细节系数有意义,那么对于lvl2要与原始信号进行比较的细节系数减去lvl2近似值,对吧?一个例子:

# Reconstruction of signal using just lvl1 approximation
approx_lvl1 = pywt.waverec(coeffs[:-6] + [None] * 6, w)
# interpolate to original amount of samples (necessary due to numeric solution of transformation not yielding same amount of values)
approx_lvl1_interp = np.interp(x=np.arange(0, 1024), xp=np.linspace(0, 1024, len(approx_lvl1)), fp=approx_lvl1)
x_without_lvl1approx = x - approx_lvl1_interp



直接显示细节系数和信号之间的关系我只使用信号x和系数在x轴上绘制[0,1]。从概念上讲,这应该是有效的,但是我不确定是否真的需要向边距偏移(例如,向量的第一个和最后一个系数没有位于信号的开始或结尾处):

def reconstruction_stem(yyy, **kwargs):
    """Plot coefficient vector on x [0,1] independently of amount of values it contains."""
    plt.stem(np.linspace(0, 1, len(yyy)), yyy, **kwargs)

reconstruction_plot(x, color='orange')
reconstruction_plot(x_without_lvl1approx, color='red')
reconstruction_stem(coeffs[1])
plt.legend(['Original signal', 'Original signal - lvl1 approximation', 'Detail coefficients'])









对不是直接在原始数据的峰值位置处的强系数的直观解释(例如,在1级时,最低系数(最强的负数)在0.25附近,以及最高系数(最强的正数)在0.75附近)?尽管存在一个清晰的模式(正滞后+负振幅,负滞后+正振幅),但对于我来说,这些似乎有点“遥不可及”。但这可能是一个很好的解释。

感谢您的回答!

评论

您没有得到答案,但是您的问题本身是在Python中实现小波分析的很好的教程。谢谢!

#1 楼

必须清楚地区分每个分解级别的近似系数和细节系数,以及与“细节”和“近似值”相关联的各个级别,“细节”和“近似”不仅涉及系数,而且还涉及该级别的逆滤波器。

#2 楼

我现在才开始涉足小波,即使是非常基本的问题,例如“如何从可用小波的选择中进行选择”(可能与实现“足够好”所需的级别数有关),我仍在努力中表示法)和“关于用小波去噪的所有方法”,因为我似乎可以通过直接的高斯去噪或中值滤波器对我的数据类型实现更好的结果。但是我离题了。...

我在上面提到的一件事是,您的级别编号似乎与我认为的通常的小波约定不一致。特别是
coeffs [0]是最后一个电平的近似幅度,在您的情况下6
coeffs [1]是第6级的细节幅度
coeffs [2]是细节幅度在第5层
...
coeffs [6]是第1层的细节幅度

,因此您的重构仅来自第5层和第6层,而不是第1层和第2层在您的情节中指出。

=========


更新:我对您的代码更加困惑,并且我认为您的想法是说明系数和信号功能是声音,但并不完美。为了更好地说明这一点,我对您的代码做了一些修改,请参见下文。请注意,在每个步骤中,我都会将系数重新缩放为信号的大小。这也使我们可以谈论阈值的概念。

import pywt
import pywt.data
import numpy as np
import matplotlib.pyplot as plt

plt.close('all')

def reconstruction_plot(yyy, **kwargs):
    """Plot signal vector on x [0,1] independently of amount of values it contains."""
    #plt.figure()
    #plt.plot(np.linspace(0, 1, len(yyy)), yyy, **kwargs)
    ym = np.median(yyy)
    plt.plot(np.linspace(0, 1., num=len(yyy)), yyy-ym, **kwargs)


def reconstruction_stem(yyy, xmax, **kwargs):
    """Plot coefficient vector on x [0,1] independently of amount of values it contains."""
    ymax = yyy.max()
    plt.stem(np.linspace(0, 1., num=len(yyy)), yyy*(xmax/ymax), **kwargs)


x = pywt.data.ecg()
w = pywt.Wavelet('sym5')
nl = 6
coeffs = pywt.wavedec(x, w, level=nl)


'''
plt.figure()
plt.stem(coeffs[1]); plt.legend(['Lvl 6 detail coefficients'])
plt.figure()
plt.stem(coeffs[2]); plt.legend(['Lvl 5 detail coefficients'])
plt.figure()
plt.stem(coeffs[3]); plt.legend(['Lvl 4 detail coefficients'])
plt.figure()
plt.stem(coeffs[4]); plt.legend(['Lvl 3 detail coefficients'])
plt.figure()
plt.stem(coeffs[5]); plt.legend(['Lvl 2 detail coefficients'])
plt.figure()
plt.stem(coeffs[6]); plt.legend(['Lvl 1 detail coefficients'])
'''


xmax = x.max()
for i in range(nl):
    plt.figure()
    reconstruction_plot(x) # original signal 
    #reconstruction_plot(pywt.waverec(coeffs, w)) # full reconstruction 
    reconstruction_plot(pywt.waverec(coeffs[:i+2] + [None] * (nl-i-1), w)) # partial reconstruction 
    reconstruction_stem(coeffs[i+1], xmax, markerfmt ='none', linefmt='r-')
    #plt.legend(['Original', 'Full reconstruction', ('Rec to lvl %d')%(nl-i), ('Details for lvl %d')%(nl-i)])
    plt.legend(['Original', ('Rec to lvl %d')%(nl-i), ('Details for lvl %d')%(nl-i)])