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'])
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'])
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'])
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:
- 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?
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
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'])
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!