Compressione lossy immagini

29  Nov. 98(Pagina 28)


N.B.: Per motivi di occupazione questa pagina contiene immagini in formato Png che Explorer 3 non visualizza, a differenza di Netscape 4.

Ecco alcune riflessioni sui formati più adatti del momento, per immagazzinare una immagine, pur accettandone una certa perdita di qualità. Fondamentalente le immagini sono riconducibili a due categorie: fotografiche di scene naturali o comunque sfumate, e discrete con colori uniformi, spesso prodotte sinteticamente dal computer. Di solito nel primo caso si usa il Jpeg, nel secondo un formato lossless come Png o altri meno noti. Un esempio di immagine schematica è la seguente, un istogramma ottenuto con Exel:

Isogramma della Sfida Compressori

Questa immagine è stata rielaborata per ottenere meno colori e dettagli possibili, fino a portarla a sei colori (393 x 508 pixel). La sua occupazione è la seguente:
Bmp 100726 Byte   palette 16 colori
Bmp  12844 Byte   palette 16 colori, Run Length Encoding
Gif   5608 Byte   a 3 bit, ottenuta con WebGraphicsOptimizer 2.05 W95/NT (Wob)
Png   1988 Byte   a 4 bit, ottenuta con WOB
Bmf   1520 Byte   da Bmp con palette a 16 col.

Bmf è uno dei migliori formati di compressione lossless di immagini, benchè sia quasi sconosciuto. In compressione e decompressione ha circa la stessa velocità del Png, ma produce risultati molto più densi, specialmente con figure fotografiche. (Programma di Dmitry Shkarin, E-mail: shkarin@arstel.ru).

Immagine San256 di San Francisco, originale 256x256 in 256 grigiPer immagini fotografiche ho deciso di fare alcune prove per mostrare soprattutto il funzionamento del Jpeg e di alcuni programmi che lo implementano. L'immagine di prova è San256, uno scorcio di San Francisco molto usato nel campo delle elaborazioni d'immagine e sviluppo compressori. (256x256 pixel, b/n, 1Byte/pixel). Per prima cosa vediamo di capire quale è la sua entropia; comprimendola senza perdita di qualità (lossless) otteniamo i seguenti valori, in byte:
Raw    65536
Gif    61017
Gfb    44015 (GifBlaster)
Png    51663 (Wob e altri)
Eri    41842
Png    41227 (*)
LocoE  36157
Bmf    35388

Il Bmf si avvicina parecchio ai record di compressione, dubito che si possa scendere molto sotto i 33000 Byte per questa immagine. L'iimagine (*) è stata ottenuta col Paint Shop Pro v. 5, solo lui ci è riuscito, tutti gli altri programmi, incluso Photoshop 5 hanno prodotto risultati peggiori, simili al Wop.

[Sull' Hd di un moderno Pc oggi esistono moltissime versioni delle routine del Jpeg, nel mio computer almeno 15 - 20. Ciò mi ricorda quello che dice Donald Normand, nei suoi libri sul design: quante batterie (pile) o motori elettrici o orologi abbiamo in una casa moderna? Un numero enorme. Ciò è uno sperco piuttosto grande, in teoria sarebbe sufficiente una sola libreria di sistema.]

Il funzionamento del Jpeg è piuttosto complesso, quì posso dare solo una breve spiegazione. Esso divide l'immagine a quadretti 8x8 pixel, a ciasuno applica indipendentemente un processo a vari stadi, ripercorsi simmetricamente nella decompressione.
Inizialmente vien applicata la Trasformata Coseno, che non elimina informazione, ma la "riordina".
Immaginiamo di avere una serie di coppie di valori di altezza - peso di molte persone, approssimate al centimetro - chilogrammo. Tracciando sul piano i punti con le coordinate di queste coppie otteniamo una distribuzione a sigaro:Distribuzione a sigaro
Adesso la posizione di ogni punto può essere individuata con la stessa precisione dandone le coordinate rispetto ad una asse che passa per la lunghezza del sigaro e uno perpendicolare. Al netto si può rappresentare le coordinate dei punti del sigaro con la stessa precisione usando meno bit, rendendo molto fitte le "tacche" sull'asse del sigaro, e rade sull'altro asse.
I valori dei pixel del qudrato 8x8 possono essere pensati come coordinate di un punto in 64 dimensioni, di cui la traformata coseno riorganizza gli assi. In pratica l'effetto della Trasformata è quello di dividere le frequenze spaziali alte dell'immagine, da quelle medie e basse.
Lo stadio che elimina informazione è detto Quantizzazione, e si occupa essenzilmente di cancellare le alte frequenze dell'immagine, più o meno come un telefono attenua le alte frequenze del segnale audio vocale. Si è visto infatti che l'occhio ha meno sensibilità per le alte frequenze, quindi tale perdita è spesso inavvertita. (questa è detta codifica percettiva). Il fattore di Qualità che si specifica nel salvare una immagine, regola l'intensità del processo di quantizzazione.
    Il jpeg lavora in truecolor o a soli toni di grigio, entrambe le versioni possono essere rese progressive. Il Jpeg è un metodo quasi locale, lavora a blocchi elementari di 8x8 pixel. Quindi la codifica di una immagine parte dall'angolo in alto a sinistra, e per strisce alte otto pixel scende in basso. Però su una rete le informazioni talvolta arrivano lentamente e spesso è utile vedere una immagine completa fin dall'inizio, benchè a bassa qualità. Il Jpeg progressivo, come le Gif e le Png progressive, hanno questo scopo. Questo metodo distrugge in parte le correlazioni all'interno di una immagine, per cui le versioni lossless progressive sono spesso leggermente più grandi di quelle non progressive. Per il  Jpeg la situazione è differente. I file risultanti sono di solito sempre della stessa lunghezza, eccetto che col Wop, il quale produce Jpeg progressivi più densi, cioè più piccoli a parità di qualità. Il motivo mi è ignoto.
Un file jpeg progressivo è composto di strati, all'inizio del file sono riportate solo le informazioni relative alle frequenze spaziali più basse nell'immagine. Gli strati successivi contengono frequenze sempre più elevate. All'aumentare della frequenza gli strati crescono di dimensione in byte. Nel Wop il numero di starti è decidibile dall'utente, comunque cinque è il massimo pratico. In tale programma ho notato che all'aumentare di strati il file diventa sempre più denso, naturalmente fino a circa cinque. Ho notato anche che per le immagini meno dettagliate il limite di convenienza è più basso, intorno a tre strati.
Ho intenzione di mostrare come appare una immagine Jpeg Progressivo a stati parziali di caricamento. Per fare ciò ho aperto il file con Wordpad ed ho cancellato prima l'ultimo strato, lefrequenze più elevate, poi i successivi. Ho salvato ogni risultato intermedio, l'ho caricato in Paint Shop Pro 5, e l'ho salvato come un jpeg completo, ad alta qualità. In questa pagina potevo inserire puntatori direttamente ai file troncati, ma sfortunatamente Netscape 4 non visualizza correttamente tali spezzoni. Explorer 3 lo fa, ma per standard ho preferito riconvertire tutto in file jpeg completi.
 

San compressa in Jpeg
Jpeg originale, alta qualità, 10890 Byte
 
Tolto primo strato di alta frequenza da San
Tolto 1° strato ad alta freq., 6458 Byte
 
Tolto secondo strato di alta frequnza
Tolto 2° strato ad alta freq., 3177 Byte
 
Solo strato a bassa frequenza
Solo strato a bassa freq., 881 Byte
 
Comprimendo San256 a lunghezze molto simili col Jpeg, si ottengono risulati piuttosto differenti:
 
 
 
Immagine jpeg di San256 a media compressione
6467 Byte
 
Immagine jpeg di San256 a forte compressione
3114 Byte
Immagine jpeg di San256 alla massima compressione
872 Byte
Le immagini di seimila byte sono molto simili. Per quelle a tremila probabilmente risulta migliore l'immagine completa, qui sopra, nonostante la sgradevole tassellatura. Per le immagini a ottocento byte i risultati sono forse migliori per l'immagine spezzata.

Talvolta si ha solo un primo spezzone di una immagine in Jpeg progressivo, senza la possibilità di procurarcela tutta (capita con internet). In tal caso disporre di un file più lungo non sempre dà risultati migliori:

Immagine jpeg di San256 mal troncata
6899 Byte

Conviene eliminare l'ultimo strato ammezzato. E' facile, basta prendere un editor di testi e cercare, a partire dalla fine del file una sequenza di:

bisogna togliere tutto quello che segue questi, fino alla fine del file, stando attenti a non effettuare nessuna altra modifica del file. Quelle filate dividono gli strati.
Concludo che i programmi di decompressione jpeg sono grezzi, potrebbero fare automaticamente una cosa del genere. Inoltre nella decompressione di immagini a fattori di qualità Q molto bassi potrebbero fare automaticamente una interpolazione fra blocchi adiacenti, per ridurre il blocking.
Si potrebbe fare ancora di meglio: nella decompressione si potrebbe estrapolare lo spettro in ogni trasformata coseno, sostituendo una migliore ipotesi per i valori della trasformata non trasmessi, di solito assunti nulli. Vedi Digital Image Processing di Pratt, pag. 693-696, Ed. Wiley-interscience, 1978.

Pare che in PicPress, degli stessi autori di Minerva, sia stata parzialmente implementata un'idea che ho avuto tempo fa. Prendiamo l'utile Jpeg Optimizer (serve per scegliere interattivamente il livello di compressione Jpeg con cui si vuol salvare un'immagine). Spesso lo uso per convertire un Jpeg da precisione inutilmente alta in uno normale (Recentemente ad esempio da Q 98.5 a Q 78 !). Ad ogni salvataggio in jpeg aggiungiamo rumore all'immagine, soprattutto a causa delle quantizzazioni dei coefficienti della trasformata coseno. Idea: Jpeg Opt. potrebbe caricare l'immagine in un modo differente, potrebbe immagazzinare i coefficienti dell'immagine originale caricata, e lavorare con quelli, evitando due trasformate e una quantizzazione. (penso che la prima trasfmata non la faccia neppure Jpeg Opt., altrimenti sarebbe lento a ricalcolare l'immagine compressa). La cosa potrebbe essere fatta anche indipendentemente in ogni blocco 8x8: ad esempio se si vuol modificare un dettaglio di una immagine Jpeg, si possono salvare modificati solo i blocchi toccati, e copiare esattamente i bit degli altri blocchi...

    I metodi di salvataggio lossy, come Jpeg, aggiungono rumore ad una immagine, l'immagine salvata non è identica all'originale ma acquista un poco di rumore. Nel salvare una immagine in questo formato specifichiamo un parametro Q di qualità, che se abbastanza alto produce una immagine visivamente indistinguibile dall'originale. Il vantaggio di usare tale tipo di compressione è che produce file di immagini molto piccole.

Dettaglio dell'immagine B/N di Lenna compressa in Jpeg con Q=75
Lenna Jpeg Q= 75 (8KB)
Differenza fra Lenna e la sua compressione con Jpeg Q=75, poi moltplicata per 20 la luminosità
(Lenna75-Orig) * 20
   
Dettaglio dell'immagine B/N di Lenna compressa in Jpeg con Q=15
Lenna Jpeg Q= 15 (3KB)
Differenza fra Lenna e la sua compressione con Jpeg Q=15, poi moltplicata per 20 la luminosità
(Lenna15-Orig) * 20
Non si è mostrata l'immagine originale, che occupa 54KB in Bmp, perchè è quasi indistinguibile da quella in Jpeg con Q=75.

Caricando e salvando ripetutamente una immagine in Jpeg essa viene progressivamente rovinata. Ho ripetuto 103 volte tale processo, usando però un fattore di qualità piuttosto alto, Q =~ 78. Ecco l'originale e il risultato:

Dettaglio del disegno Gard, di un morfo di husky che NON fa la guardiaDettaglio di Gard dopo 103 salvataggi in Jpeg con Q =~ 78
Il risultato dopo tutto non è pessimo. La componente luminanza dell'immagine è quasi inalterata, si notano solo i blocchi 8x8 di colore differente. Per motivi che ignoro sembra che l'immagine abbia subito complessivamente una viratura al verde.
L'immagine è un dettaglio di Gard, diseganta da Bucky, questo esperimento è stato effettuato usando il convertitore grafico Alchemy, iterando tramite uno script Dos i seguenti tre comandi:
Alchemy -j -Q gard gardb
Del gard.jpg
Ren gardb.jpg gard.jpg
 

In realtà esistono molte immagini che non rientrano fra i due tipi suindicati. Ad esempio con spettrogrammi colorati può essere problematica la scelta del formato grafico migliore. Essendo policromi e sfumati, si pensa di usare il Jpeg. Ma i risultati sono deludenti, nonostante si usi un rapporto luminanza - cromo 1:1 nel Jpeg... (cioè non si sottocampionano le informazioni cromatiche). L'immagine originale è a 24 bit/pixel, ma usa solo 134 colori. Solo Photoshop 5 è riuscito a convertirla esattamente in una immagine con palette a 8 bit/pixel (nè Wop, Nè Paint Shop Pro 5)
Raw 53066 Byte
Png 33095 Byte
Bmf 27556 Byte
 

Stridio originale di rondine, filrtrato passa-basso a 16Khz
Stridio originale di rondine, Png a 134 colori, 8 bit/pixel, 33095 Byte
Stridio elaborato di rondine, filrtrato passa-basso a 16Khz, Jpeg
Zona superiore annerita, Jpg a 2 strati del del Wop,YIQ 4:4:4, 20862 Byte
Stridio elaborato di rondine, filrtrato passa-basso a 16Khz, 16 colori, png
Zona superiore annerita, Png del Wop a 16 colori, 4 bit/pixel, 9037 Byte
Ho dovuto annerire le parti nero-rumoroso per ottenere risulatati migliori coi compressori lossless. (si potrebbe fare un programma che rivela automaticamente tale confine fra il nero sporco e le zone non nere, forse basandosi su metodi entropici (il rumore non è comprimibile, ha entropia massima)).
L'ultima immagine (16 colori, 4 bit/pixel, annerita) occupa 6776 Byte in Bmf.

    Un importante fonte di rumore è quello elettronico dei sensori ottici. Lo si può vedere bene in un dettaglio ingrandito tre volte dell'immagine Lenna originale:

Dettaglio della fotografia B\N LennaDettaglio della fotografia B\N Lenna, ingrandita tre volte
Il seguente è lo stesso dettaglio dopo una filtratura antirumore estremamente sofisticata (tratto dalla pagina sul compressore lossless TMW0.51 di Bernd Meyer, bmeyer@cs.monash.edu.au):
Dettaglio della fotografia B\N Lenna, dal rumore filtratoDettaglio della fotografia B\N Lenna, dal rumore filtrato, ingrandita tre volte
Le immagini prodotte direttamente in un computer sono pressochè libere da tale rumore. Come si sa il rumore è entropicamente incomprimibile, quindi specialmente i buoni compressori lossless perdono molta efficienza se agiscono su immagini rumorose. Ad esempio l'immagine originale di lenna è 512 x 512 x 256 grigi ed occupa 258KB, compressa col Bmf occupa 132KB, mentre l'immagine filtrata, di dimesioni uguali, occupa solo 83KB col Bmf. Da notare che il filtraggio antirumore è stato fatto tanto bene che la perdita di segnale (microdettagli) è percepibile, ma minuscola.
 

Esistono altri formati grafici lossy, in particolare basati sulla trasformata frattale e su wavelet. I risultati della fractal compression sono a mio avviso quasi uguali al Jpeg, o leggermente peggiori, inoltre hanno una esecuzione molto più lenta. Comunque le immagini panoramiche sull'enclopedia Omnia 97 sono registrate in tale formato.
La compressione con Wavelet è apparentemente un poco migliore del Jpeg, a bassi data rate. I tempi di codifica sono comunque sempre un poco più alti.
Presto verrà formalizzato un nuovo formato grafico, il Jpeg2000. Non ho idea di come funzionerà, certo è che sarà molto elastico se dovrà soddisfare la lunghissima lista di richieste che gli vengoo poste.