Università degli Studi di Padova Corso di Laurea Specialistica in Bioingegneria A.A. 26-27 27 INFORMATICA SANITARIA (Esercitazione sulla Compressione) Giovanni Sparacino Dipartimento di Ingegneria dell Informazione Università degli Studi di Padova Via Gradenigo 6/B, 35131 Padova Tel. 49 827 7741; e-mail: gianni@dei.unipd.it web: http://www.dei.unipd.it/~gianni Esercizio 1 (codifica RLE) FARE PER ULTIMO SE RIMANE TEMPO Il vettore x di dimensione 25 contiene i campioni di un segnale che rappresenta la presentazione di eventi identici come forma (caratterizzati da una template 1 1 1 1-1 -1) ma diversi in polarita' e ampiezza. a) Fare un plot del segnale e studiare come e' fatto (in particolare guardare come è possibile evidenziare i run) b) Progettare un modo efficiente di codificare le informazioni in un vettore di dimensione minore (suggerimento: sfruttare i run e pensare che poi sarà sufficiente archiviare polarita' e ampiezza degli eventi). Per semplicita', assumere che il segnale cominci con degli zeri, finisca con un evento completo, e che i run siano sempre piu' lunghi della durata della template c) Come verifica, scrivere e applicare la routine di decompressione al vettore ottenuto al punto b)
1 s egnale originale 5-5 -1 5 1 15 2 25 segnale compress o (lunghezza=36) 3 2 1-1 5 1 15 2 25 3 35 4 s egnale decompres so 1 5-5 -1 5 1 15 2 25 % dato il vettore x di dimesione 25 (rappresenta la presentazioni di eventi identici (template 1 1 1 1-1 -1) e denotati solo da polarita' e ampiezza) clear x=[ 3 3 3 3-3 -3 1 1 1 1-1 -1 4 4 4 4-4 -4 5 5 5 5-5 -5-6 -6-6 -6 6 6-3 -3-3 -3 3 3-1 -1-1 -1 1 1 3 3 3 3-3 -3-3 -3-3 -3 3 3 5 5 5 5-5 -5-7 -7-7 -7 7 7-1 -1-1 -1 1 1 ]; n=length(x); subplot(311) plot(x) title('segnale originale') pos=1; lrun=; k=1; Esempio di una delle possibili soluzioni while k<=n if x(k)== lrun=lrun+1; else amp=abs(x(k)); pol=sign(x(k)); xcompr(pos)=lrun; xcompr(pos+1)=pol; xcompr(pos+2)=amp; pos=pos+3; k=k+5; lrun=; k=k+1; subplot(312) stem(xcompr) title(['segnale compresso (lunghezza=' num2str(length(xcompr)) ')']) template=[1 1 1 1-1 -1]; nc=length(xcompr); xdecompr=[]; k=1; while k<=nc lrun=xcompr(k); pol=xcompr(k+1); ampl=xcompr(k+2); xdecompr=[xdecompr,zeros(1,lrun), pol*template*ampl]; k=k+3; subplot(313) plot(xdecompr) title('segnale decompresso')
Esercizio 2a (Compressione via DCT scartando le componenti HF) Il vettore y contiene una serie di 128 punti riferita al vettore t. Applicare la DCT all intera serie (in Matlab istruzione dct) e poi applicare la anti-dct (in Matlab idct) all interno di un ciclo for ripetuto 128 volte in cui le componenti utilizzate scono di una unità a ciclo, scartando le componenti ad alta frequenza (in altri termini, fare la idct da 128 componenti, poi dalle prime 127, poi dalle prime 126,... fino a fare la idct da 1 sola componente). Ad ogni iterazione, plottare sovrapposti il segnale originale e quello ottenuto dalla anti-dct e, in un altro riquadro della stessa figura, lo scostamento tra le due Come evolve l errore? 4 Ricos truzione us ando le prime 72 componenti 2-2 -4 5 1 15 2 25 3 35 1 Errore us ando le prime 72 componenti 5-5 -1 5 1 15 2 25 3 35 (plot da 72 componenti residue)
% simulazione compressione via DCT scartando i coefficienti ad alta frequenza Ty=dct(y); for k=1:128 Tya=[Ty(1:128-k+1) zeros(1,k-1)]; ya=idct(tya); plot(t,y,t,ya,'r--') title(['ricostruzione usando le prime ' num2str(128-k) ' componenti']) plot(t,y-ya,'r--') title(['errore usando le prime ' num2str(128-k) ' componenti']) pause Esercizio 2b (Compressione via DCT scartando le componenti meno energetiche) Raffinare l esercizio 2a, plottando l anti DCT che si ottiene scartando le componenti una alla volta, ma usando adesso come criterio di eliminazione l energia dei coefficienti (in altri termini, fare la idct da 128 componenti, poi dalle 127 più energetiche, poi dalle 126 più energetiche,... fino a fare la idct da 1 sola componente). Per ordinare i coefficienti in Matlab usare l istruzione sort (vd help). Ad ogni iterazione, plottare sovrapposti il segnale originale e quello ottenuto dalla anti-dct e, in un altro riquadro della stessa figura, lo scostamento tra le due Come evolve l errore?
4 Ricos truzione us ando le 11 componenti maggiormente energetiche 2-2 -4 5 1 15 2 25 3 35 6 Errore us ando le 11 componenti maggiormente energetiche 4 2-2 -4 5 1 15 2 25 3 35 (plot da 11 componenti residue) Ty=dct(y); [Ty2ord, indici]=sort(ty.^2); for k=1:128 indazzerare=indici(1:k) Tya=Ty; Tya(indazzerare)=; ya=idct(tya); plot(t,y,t,ya,'r--') title(['ricostruzione usando le ' num2str(128-k) ' componenti maggiormente energetiche']) plot(t,y-ya,'r--') title(['errore usando le ' num2str(128-k) ' componenti maggiormente energetiche']) pause
Esercizio 2c (Compressione via DCT con quantizzazione simil JPEG) Raffinare l esercizio 2a, applicando (come in JPEG) ai coefficienti della DCT il vettore di quantizzazione q. Per apprezzare il ruolo di q, eseguire l operazione in un ciclo ripetuto 1 volte, moltiplicando ogni volta q per un fattore di scala che va da 1 a 1. Ad ogni iterazione, plottare sovrapposti il segnale originale e quello ottenuto dalla anti-dct e, in un altro riquadro della stessa figura, lo scostamento tra le due. Ad ogni iterazione, calcolare anche il numero di zeri in coda alla sequenza dei coefficienti DCT quantizzati e scriverlo nel titolo del grafico. Come evolve l errore? 4 Ricostruzione usando fattore 1 (run lungo 112) 2-2 -4 5 1 15 2 25 3 35 6 Errore us ando fattore 1 (run lungo 112) 4 2-2 -4 5 1 15 2 25 3 35
4 Ricostruzione usando fattore 31 (run lungo 114) 2-2 -4 5 1 15 2 25 3 35 6 Errore us ando fattore 31 (run lungo 114) 4 2-2 -4-6 5 1 15 2 25 3 35 Ty=dct(y); sent=128; for k=1:1 q=k*round(.3*n+4); Tyq=round(Ty./q); Tya=Tyq.*q; while Tya(sent)== sent=sent-1; l_run=128-sent; ya=idct(tya); plot(t,y,t,ya,'r--') title(['ricostruzione usando fattore ' num2str(k) ' (run lungo ' num2str(l_run) ')']) plot(t,y-ya,'r--') title(['errore usando fattore ' num2str(k) ' (run lungo ' num2str(l_run) ')' ]) pause
Esercizio 3 (decorrelazione ed entropia) AGGIUNTO IL PUNTO d) a) Il segnale w è costituito da 4 campioni che spaziano da 1 a 16. Sfruttando l istruzione histc di Matlab (vd help) calcolare la frequenza relativa dei valori e plottare l istogramma (usare l istruzione bar, vd help). Calcolare poi l entropia della sorgente associabile al segnale b) Differenziare il segnale w (eventualmente sfruttare filter in Matlab), e, rilevato a vista che i livelli variano da -1 a +2, calcolare la frequenza relativa dei simboli, plottare l istogramma, e quindi calcolare l entropia c) Differenziare una seconda volta il segnale e, rilevato a vista che i livelli variano da -1 a +1, calcolare la frequenza relativa dei simboli, plottare l istogramma, e quindi calcolare l entropia d) (aggiunto il 1.12.26) relativamente al caso c) fare (a mano) la codifica di Huffman e trovare la stringa che codifica il segnale differenziato 2 volte. Confrontare la lunghezza della stringa trovata con quella della stringa che, usando un dizionario di codici a lunghezza fissa, codificherebbe il segnale w originale 2 s e g n a le o rig in a le 1 5 1 5 5 1 1 5 2 2 5 3 3 5 4. 4 is to g ra m m a s e g n a le o rig in a le (H = 3. 4 2 9 ). 3. 2. 1 2 4 6 8 1 1 2 1 4 1 6 1 8
2 segnale differenziato una volta 1.5 1.5 -.5-1 5 1 15 2 25 3 35 4.4 is togramma s egnale differenziato una volta (H=1.8413).3.2.1 1 2 3 4 1 segnale differenziato due volte.5 -.5-1 5 1 15 2 25 3 35 4.8 is togramma s egnale differenziato due volte (H=1.1219).6.4.2 1 2 3
y=w; t=(1:1:length(y))'; figure(1) plot(t,y,t,y,'o') title('segnale originale') edges=(1:1:16); p =histc(y,edges)/length(y)'; i=-log2(p); H=sum(i.*p); bar(p) title(['istogramma segnale originale (H=' num2str(h) ')']) figure(2) dy=filter([1-1],1,y); plot(t,dy,t,dy,'o') title('segnale differenziato una volta') edges=(-1:1:2); p =histc(dy,edges)/length(dy); i=-log2(p); H=sum(i.*p); bar(p) title(['istogramma segnale differenziato una volta (H=' num2str(h) ')']) figure(3) d2y=filter([1-1],1,dy); plot(t,d2y,t,d2y,'o') title('segnale differenziato due volte') edges=(-1:1:1); p =histc(d2y,edges)/length(d2y); i=-log2(p); H=sum(i.*p); bar(p) title(['istogramma segnale differenziato due volte (H=' num2str(h) ')'])