Transformação discreta de wavelet - visualizando a relação entre coeficientes de detalhe decompostos e sinal


12

Estou tentando visualizar diretamente a relação entre os coeficientes de detalhe da transformada de wavelet discreta (DWT) e o sinal original / sua reconstrução. O objetivo é mostrar sua relação de maneira intuitiva. Eu gostaria de fazer (veja as perguntas abaixo): se a idéia e o processo que eu criei estão corretos até agora, e se eu estiver certo, seria melhor subtrair a aproximação do 1º nível do sinal original antes de visualizar sua relação .

Exemplo mínimo

Aqui está o exemplo mínimo em que baseio minha explicação, usando os dados de exemplo de ECG do Pythonpywavelets , que tem valores 1024, como um sinal 1D simples:

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'])

Sinal original

A decomposição é feita usando um Symmlet 5 com um total de 6 níveis:

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

A reconstrução (com perdas) do sinal funciona como esperado ao deixar intencionalmente coeficientes de detalhe de níveis mais altos (os sinais são plotados em escala x uniforme [0,1] por conveniência):

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'])

Sinal reconstruído

O DWT acima produz um vetor de aproximação de nível 1 de 24 valores, o nível 1 detalha o vetor de coeficiente de 24 valores, o vetor de detalhe de nível 2 de 40 valores, o nível 3 de 72 valores, o nível 4 de 135 valores, o nível 5 de 262 valores e o nível 6 de 516 valores:

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'])

Coeficientes de detalhe de nível 1 Coeficientes de detalhe de nível 2 Coeficientes de detalhe de nível 3 Coeficientes de detalhe de nível 4 Coeficientes de detalhe de nível 5 Coeficientes de detalhe de nível 6

Parece que vemos padrões claros em torno dos picos nos sinais originais (também preste atenção à escala y dos gráficos acima).

Agora às minhas perguntas:

  1. É correto que possamos relacionar diretamente esses coeficientes ao sinal? A amplitude do coeficiente corresponde à amplitude com a qual a wavelet ocorre no sinal (eixo y) e a posição do coeficiente corresponde ao tempo (eixo x). Ou há algo entre o que precisamos considerar?
  2. Após o DWT, a aproximação final do lvl1 permanece. Faz sentido não visualizar a relação dos coeficientes de detalhes com o sinal original, mas com o sinal original menos a aproximação lvl1? (Eu sei que provavelmente também veria a relação entre coeficientes e sinal sem fazer isso, veja, por exemplo, gráficos abaixo. É apenas para isso que faz sentido ou não. Se faz sentido para os coeficientes de detalhe do lvl1, também pode fazer sentido para coeficientes de detalhe lvl2 a serem comparados com o sinal original menos a aproximação lvl2, certo?). Um exemplo:

    # 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
    
  3. A visualização direta da relação entre os coeficientes de detalhes e o sinal que eu uso apenas plota o sinal e os coeficientes em um eixo x de [0,1]. Conceitualmente, isso deve ser válido, mas não tenho certeza se eu precisaria de um deslocamento em direção às margens (por exemplo, o primeiro e o último coeficiente do vetor não estejam posicionados no início ou no final do sinal):

    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'])
    

Relação entre os coeficientes de detalhe lvl1 e o sinal Relação entre os coeficientes de detalhe lvl2 e o sinal Relação entre os coeficientes de detalhe lvl3 e o sinal Relação entre os coeficientes de detalhe lvl4 e o sinal Relação entre os coeficientes de detalhe lvl5 e o sinal Relação entre os coeficientes de detalhe lvl6 e o ​​sinal

Existe uma explicação intuitiva para os coeficientes fortes que não estão diretamente nas posições dos picos nos dados originais (por exemplo, no nível 1, o mais baixo (mais forte negativo), em torno de 0,25, e o mais alto (mais forte, positivo) em torno de 0,75 )? Embora exista um padrão claro (atraso positivo + amplitude negativa, atraso negativo + amplitude positiva), esses parecem um pouco "distantes" para mim. Mas provavelmente existe uma boa explicação para isso.

Obrigado por responder!


Você não recebeu uma resposta, mas sua pergunta em si é um bom tutorial para implementar a análise de wavelet no Python. Obrigado!
Farzad

Respostas:


1

É necessário distinguir claramente entre os coeficientes de aproximação e detalhe em cada nível de decomposição e os níveis associados Detalhes e aproximação que envolvem não apenas os coeficientes, mas também os filtros inversos nesse nível, respectivamente


0

Só agora estou começando a me interessar por wavelets, e ainda estou lutando, mesmo com perguntas muito básicas, como "como escolher entre um monte de wavelets disponíveis" (provavelmente tem a ver com o número de níveis que você precisa para alcançar "o suficiente") representação) e "o que há de tão contagioso no denoising com wavelets", porque parece que sou capaz de obter melhores resultados para o meu tipo de dados com denoising gaussiano reto ou filtros medianos. Mas eu discordo ....

Uma coisa que observei acima é que sua numeração de nível parece inconsistente com o que acredito ser as convenções de wavelet usuais. Em particular, coeficientes [0] são as amplitudes de aproximação no último nível; no seu caso, 6 coeficientes [1] é a amplitude de detalhe no nível 6 coeficientes [2] é a amplitude de detalhe no nível 5 ... coeficientes [6] é o amplitude de detalhe no nível 1

Portanto, suas reconstruções são apenas do nível 5 e 6, não do nível 1 e 2, conforme indicado em suas parcelas.

=========

Atualização: mexi mais com seu código e acho que sua ideia de ilustrar a correlação entre coeficientes e recursos de sinal é sólida, mas não perfeita. Eu me diverti um pouco com seu código para ilustrar melhor isso, veja abaixo. Observe que em cada etapa eu redimensiono os coeficientes para a magnitude do sinal. Isso permite falar sobre o conceito de limiar também.

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)])
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.