Transformée en ondelettes discrète - Visualisation de la relation entre les coefficients de détail décomposés et le signal

12

J'essaie de visualiser directement la relation entre les coefficients de détail de la transformation en ondelettes discrètes (DWT) et le signal d'origine / sa reconstruction. Le but est de montrer leur relation de manière intuitive. Je voudrais demander (voir les questions ci-dessous): si l'idée et le processus que j'ai trouvé sont corrects jusqu'à présent, et si j'ai raison, il serait préférable de soustraire l'approximation de 1er niveau du signal d'origine avant de visualiser leur relation .

Exemple minimal

Voici l'exemple minimal sur lequel je base mon explication, en utilisant les données d'exemple ECG de Pythonpywavelets , qui ont 1024 valeurs, comme un signal 1D simple:

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

Signal d'origine

La décomposition se fait à l'aide d'un Symmlet 5 avec un total de 6 niveaux:

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

La reconstruction (avec perte) du signal fonctionne comme prévu en omettant intentionnellement les coefficients de détail des niveaux supérieurs (les signaux sont tracés sur une échelle des x uniforme [0,1] pour plus de commodité):

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

Signal reconstruit

Le DWT ci-dessus donne un vecteur d'approximation de niveau 1 de 24 valeurs, un vecteur de coefficient de détail de niveau 1 de 24 valeurs, un vecteur de détail de niveau 2 de 40 valeurs, un niveau 3 de 72 valeurs, un niveau 4 de 135 valeurs, un niveau 5 de 262 valeurs et un niveau 6 valeurs sur 516:

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

Coefficients de détail de niveau 1 Coefficients de détail de niveau 2 Coefficients de détail de niveau 3 Coefficients de détail de niveau 4 Coefficients de détail de niveau 5 Coefficients de détail de niveau 6

Il semble que nous voyons des motifs clairs autour des pointes des signaux d'origine (faites également attention à l'échelle y des graphiques ci-dessus).

Passons maintenant à mes questions:

  1. Est-il exact que nous pouvons directement relier ces coefficients au signal? L'amplitude du coefficient correspond à l'amplitude avec laquelle l'ondelette se produit dans le signal (axe y), et la position du coefficient correspond au temps (axe x). Ou y a-t-il quelque chose entre les deux que nous devons considérer?
  2. Après le DWT, l'approximation finale lvl1 reste. Est-il judicieux de ne pas visualiser la relation des coefficients de détail avec le signal d'origine, mais plutôt avec le signal d'origine moins l'approximation lvl1? (Je sais que je verrais très probablement également la relation entre les coefficients et le signal sans le faire, voir par exemple les graphiques ci-dessous. C'est juste pour cela que cela a du sens ou non. Si cela a du sens pour les coefficients de détail lvl1, cela pourrait également avoir du sens pour lvl2 détailler les coefficients à comparer au signal d'origine moins l'approximation lvl2, non?). Un exemple:

    # 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. La visualisation directe de la relation entre les coefficients de détail et le signal que j'utilise ne fait que tracer à la fois le signal et les coefficients sur un axe x de [0,1]. Conceptuellement, cela devrait être valable, mais je ne sais pas si j'aurais réellement besoin d'un décalage vers les marges (par exemple, le premier et le dernier coefficient du vecteur n'étant pas positionnés au tout début ou à la fin du signal):

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

Relation entre les coefficients de détail lvl1 et le signal Relation entre les coefficients de détail lvl2 et le signal Relation entre les coefficients de détail lvl3 et le signal Relation entre les coefficients de détail lvl4 et le signal Relation entre les coefficients de détail lvl5 et le signal Relation entre les coefficients de détail lvl6 et le signal

Y a-t-il une explication intuitive pour les coefficients forts qui ne sont pas directement aux positions des pics dans les données originales (par exemple au niveau 1 le plus bas (le plus fort négatif) à environ 0,25, ainsi que le plus élevé (le plus fort positif) à environ 0,75 )? Bien qu'il existe un schéma clair (décalage positif + amplitude négative, décalage négatif + amplitude positive), ceux-ci me semblent un peu "éloignés". Mais il y a probablement une bonne explication à cela.

Merci de répondre!

geekoverdose
la source
Vous n'avez pas obtenu de réponse, mais votre question elle-même est un bon tutoriel pour implémenter l'analyse en ondelettes en Python. Je vous remercie!
Farzad

Réponses:

1

Il est nécessaire de distinguer clairement entre les coefficients d'approximation et de détail à chaque niveau de décomposition et les niveaux associés Détails et approximation qui impliquent non seulement les coefficients mais aussi les filtres inverses à ce niveau respectivement

CD86
la source
0

Je commence seulement maintenant à m'essayer aux ondelettes, et je continue de me battre même avec des questions très basiques comme "comment choisir parmi le groupe des ondelettes disponibles" (cela a probablement à voir avec le nombre de niveaux dont vous avez besoin pour atteindre "assez bien" représentation ") et" quel est tout le hoopla sur le débruitage avec des ondelettes ", parce que je semble pouvoir obtenir de meilleurs résultats pour mon type de données avec un débruitage gaussien droit ou des filtres médians. Mais je m'éloigne ...

Une chose que j'ai notée ci-dessus est que votre numérotation de niveau semble incompatible avec ce que je crois être les conventions habituelles en ondelettes. En particulier, les coeffs [0] sont les amplitudes d'approximation au dernier niveau, dans votre cas 6 coeffs [1] est l'amplitude de détail au niveau 6 coeffs [2] est l'amplitude de détail au niveau 5 ... les coeffs [6] sont les amplitude de détail au niveau 1

Vos reconstructions sont donc uniquement des niveaux 5 et 6, pas des niveaux 1 et 2 comme indiqué dans vos graphiques.

=========

Mise à jour: j'ai plus gâché votre code et je pense que votre idée d'illustrer la corrélation entre les coefficients et les caractéristiques du signal est bonne, mais pas parfaite. J'ai fouillé un peu avec votre code pour mieux illustrer cela, voir ci-dessous. Notez qu'à chaque étape, je redimensionne les coefficients à la grandeur du signal. Cela permet aussi de parler du concept de seuillage.

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)])
user40719
la source