JPEG:n algoritmit ja niiden vaihtoehdot Tutkielma kurssille T-61.246 Digitaalinen signaalinkäsittely ja suodatus Marko Knuutila, 51284D Sisällysluettelo Johdanto...2 JPEG:n algoritmi... 2 Häviöttömät algoritmit... 5 Häviöllinen koodaus...6 Muunnos... 6 Kvantisointi...7 Subjektiivisuudesta... 8 Yhteenveto...8 LIITE 1... 10 LIITE 2... 11 1
Johdanto JPEG on todennäköisesti maailman käytetyin standardi luonnollisten, jatkuvasävyisten monokromaattisten sekä värikuvien pakkaukseen ja arkistointiin. Se toimii parhaiten valokuvien ja monisävyiseksi luotujen piirrosten pakkaamiseen, mistä syystä JPEG onkin de facto standardi digitaalikameroissa ja www:n kautta välitettävissä monivärisissä kuvissa. JPEG on periaatteellisesti häviöllinen pakkausmenetelmä (tässä tutkielmassa ei käsitellä JPEG-LS -laajennusta), toisin sanoen prosessoinnissa suoritetaan kvantisointi, joka pudottaa pois epärelevanttia informaatiota. Koska JPEG tuottaa vaihtelevan pituista koodia (käytetty bittimäärä pixeliä kohti ei ole vakio) on sen avulla helppo tuottaa myös eri suuruudella kvantisoituja kuvia halutun kuvanlaadun ja vaadittavan koon mukaan. JPEG:n algoritmi Kuva 1 Häviöllinen ja häviötön pakkaus JPEG:n toimintaa voidaan helposti havainnollistaa kahdella yksinkertaistetulla "laatikkorealisaatiolla". Kuvassa 1 havainnollistetaan yleistä häviöllisen pakkausmenetelmän toimintatapaa, johon kuuluu häviötön kompressointi sekä erikseen häviöllinen kvantisointi. Tavallisessa toiminnassa häviöllisestä koodauksesta saadut kertoimet pakataan häviöttömästi (nk. entropiakoodaus) - Äärimmäisessä tapauksessa häviöllinen lohko voidaan jättää pois, jolloin kuvan yksittäiset elementit (esim. pikselien väriarvot) pakataan suoraan häviöttömästi. 2
Kuva 2 JPEG-algoritmin realisaatio Kuva 2 esittää JPEG:n yksityiskohtaisempaa toteutusta. JPEG hyödyntää muunnoskoodausta (engl. transform coding), jossa varsinaiset kuvaelementit (esim. pikselit) aluksi muunnetaan muunnosavaruuteen diskreetin kosinimuunnoksen (DCT, discrete cosine transform) avulla. Optimaalisinta muunnoskoodaus olisi tehdä koko kuvalle, mutta käytännön laskutehorajoituksista johtuen JPEG:ssä DCT on standardoitu tehtäväksi 8x8-kokoisilla, toisiaan leikkaamattomilla elementtiryhmillä. Alkuperäisen kuvan elementeistä muuntamalla saadut kertoimet kvantisoidaan skalaarikvantisaattorilla, mistä saadaan huomattavasti parempi vääristymisen ja bittimäärän (R/D, rate/distortion) suhde, kuin alkuperäisten kuvaelementtien kvantisoinnilla olisi saatu. Muunnos myös muuttaa kuvaelementtien painoarvoja: yksi muunnettu kerroin ei enää vastaakaan vain yhtä pistettä kuvassa vaan se vaikuttaa tietynkokoiseen alueeseen kuvassa - jotkut kertoimet jopa koko kuvaan. DCT tuottaa yhden "tasavirtakertoimen" (DC-komponentti), joka määrittää kuvaelementtiryhmän yleisen ominaisuuden (esim. värisävyn ja tummuuden keskiarvon) lisäksi muunnoksesta saadaan joukko "vaihtovirtakomponentteja" (AC-komponentit, esim poikkeamat keskiarvosta), jotka "taajuudestaan" riippuen implikoivat eri suuruisia muutoksia, kuten reunojen jyrkkyyksiä ja muita nopeita värivaihteluja (kvantisoinnissa usein tiputetaan pois enemmän korkeataajuisia komponentteja, jolloin kuvan reunat "pyöristyvät" ja tulevat sameammiksi eli terävyys kärsii). DC-komponentin redundanssia pienennetään vielä ennustavalla erotuskoodauksella (predictive differential coding), jolloin entropiakoodaus on tehokkaampaa. AC-komponentit on järjestettävä joillain tapaa, sillä kaikki tallennus- ja siirtomediat käsittelevät vain yksiulotteista dataa (siis bittijonoja), vaikka kuvat ovat kaksiulotteisia. Oletusarvoisesti JPEG:ssä käytetään zig-zagskannausta, jossa aloitetaan pienimmän taajuisesta AC-komponentista ja edetään kohti suurempitaajuisia komponentteja - periaate on esitetty kuvassa 3. 3
Kuva 3 Zig-Zag-skannaus Häviöttömät algoritmit JPEG:ssa käytetään Huffman-koodausta. Menetelmässä koodataan JPEG-algoritmin häviöllisestä saadut kertoimet Huffman-koodiksi, jossa yleisimin esiintyvä symboli saa lyhimmän koodisanan ja harvimmin esiintyvä pisimmän koodisanan. Jotta vastaanottaja tietäisi oikean koodisanojen merkityksen, jokaisen JPEG-kuvan alkuun liitetään Huffman-taulukko, jossa jokaisen symbolin ja koodisanan yhteys on kerrottu. Pienikokoisilla kuvilla Huffman-taulukon koon suhde varsinaisen tiedon kokoon saattaa olla jo merkittävän suuri ja pahimmassa tapauksissa symbolit ilman Huffman-koodausta saattaisivat vielä vähemmän bittejä kuin koodisanat ja Huffman-taulukot. JPEG on kuitenkin tarkoitettu luonnollisten ja moniväristen kuvien arkistointiin, jolloin millään järjellisen kokoisella kuvalla ongelma ei muodostu kovin suureksi. Huffman-koodauksen toinen huono puoli on, että jokaista koodisanaa varten joudutaan käyttämään vähintään yksi bitti. Näin siis kuvan bittimäärä on vähintään koodattavien symbolien määrä. Tämäkin on merkityksellistä vain kuvilla, joissa on vain vähän värejä tai paljon yhtä väriä, mutta yhtä kaikki JPEG:n standardoinnin jälkeen koneiden laskentateho on kasvanut niin radikaalisti, että aritmeettinen koodaus on noussut varteenotettavaksi vaihtoehdoksi (ja se on myös standardoitu JPEG-2000:en). Aritmeettinenkoodaus on periaatteeltaan yksinkertainen. Siinä lasketaan todennäköisyydet jokaiselle syötteessä esiintyvälle symbolille (perustapauksessa "0" ja "1") ja jaetaan väli [0,1) näiden todennäköisyyksien kesken. Otetaan ensimmäinen koodattava symboli ja katsotaan mille välille se kuuluu. Jaetaan tämä väli jälleen kaikken todennäköisyyksien kesken ja tutkitaan mille välille seuraava koodattava symboli osuu ja jaetaan jälleen tämä väli todennäköisyyksien mukaan - jakamista jatketaan jonkun tietyn tai täysin mielivaltaisen syötesymbolimäärän verran, minkä jälkeen tuloksena on jokin murtoluku, jonka vastaanottaja pystyy yksikäsitteisesti tunnistamaan tietyksi symbolijonoksi tietäessään symbolien todennäköisyydet. Kuva 4 esittää aritmeettisen koodauksen ideaa graafisesti bittijonolle 1010 kun molempien bittien todennäköisyys on sama vastaanottajalle siis lähetetään vain kuvassa esitetty lukuarvo P ja tieto siitä, montako bittiä on koodattu. 4
Kuva 4 Aritmeettinen koodaus, kun P(1)=P(0)=0,5 Alin mahdollinen bittimäärä määritellään Shannonin rajan myötä laskemalla lähteen entropia. Kuvan käsittelyssä on löydetty keinoja pienentää kuvan elementtien entropiaa, jolloin myös entropiakoodauksella saavutetaan suurella todennäköisyydellä pienenpi bittimäärä (engl. bit rate). Kaksi tehokasta menetelmää on jo käytössä JPEG-algoritmissä: elementin tai kertoimen ennustaminen, eli ennustetaan seuraavaa syötteen alkiota tämän hetkisen alkion perusteella ja vasteena annetaan ennustetun arvon (käytännössä edellinen arvo) ja oikean arvon (tämänhetkinen arvo) erotus. JPEG-kuvat tallennetaan lähes poikkeuksetta luminenssi-krominenssi(ycbcr) -muodossa. Kuvat tosin esitetään tavallisesti RGB-muodossa, jossa jokaiselle värille (punainen, vihreä ja sininen) on oma kanavansa, mutta koska luonnollisissa kuvissa värikanavat ovat tasaisesti jakautuneita on niiden entropia suuri - muuttamalla kuva yhden valoisuuden sekä kahden värikomponentin tasoihin, muuttuvat kanavien histogrammit kapeimmiksi ja korkeammiksi, jolloin entropia pienenee ja entropiakoodaus tuottaa lyhyempää koodia. Luonnollisesti C(yan)M(agenda)Y(ellow)-väriesitys antaa yhtä huonon tuloksen kuin RGB:kin, mutta hyviin tuloksiin voitaisiin päästä myös HSB- tai CIELAB-esityksillä. Ne eivät kuitenkaan tuo ratkaisevasti parempaa tulosta kuin YCbCr-esityksestä saatu, mutta saattavat hankaloittaa prosessointia tai ainakin värien hahmottamista, joten niitä ei juurikaan käytetä. Häviöllinen koodaus Kvantisointi poistaa syötteestä epärelevanttia tietoa, jolla on mahdollisimman pieni merkitys kuvanlaadun kannalta. Havaitty kuvanlaatu on hyvin subjektiivinen käsite, joka riippuu niin katsojasta kuin nimenomaisesta kuvastakin. Muunnos Parhaaseen tulokseen päästään kvantisoimalla syötteestä muunnoksen kautta saatuja kertoimia eikä syötteen elementtejä itseään. Muunnokseksi voidaan valita mikätahansa haluttu ja mielellään helposti laskettavissa oleva muunnos y=ax, jossa y=muunnoskeroimet, A=muunnosmatriisi, x=nxn kuvasyöte. Tarkoituksenmukaista on kuitenkin löytää ortogonaalinen muunnos sillä tällöin tiedetään 5
muuntokertoimien määrän (sähköteknillisessä mielessä "vektorin energia") olevan sama kuin syötealkioiden määrä. Matemaatikot ovat todistaneet Karhunen-Loeve-muunnoksen(KLT) tuottavan optimaalisen energiakeskittymän korreloimattomilla muunnoskeroimilla. Tämä on ideaalinen tilanne kuvankäsittelyssä, mutta yksikään kuvaformaatti ei käytä KLT:ta muunnoskertoimien tuottamiseen, sillä muunnokselle ei tunneta nopeasti laskettavissa olevaa muotoa (vrt. Fast Fourier Transform) ja lisäksi KLT riippuu kulloinkin käsiteltävästä kuvasta (pakatun kuvan mukaan tulisi siis aina lisätä muunnoksen parametrit). Fourier-muunnokselle tunntetaan nopea laskutapa ja se ei ole riippuvainen käsiteltävän kuvan statistiikasta. Lisäksi Fourier-muunnos on yleisesti tunnetuin muunnosväline ja on näin helposti implementoitavissa sovellukseen kuin sovellukseen. Kokeilemalla kuitenkin osoittautuu, että luonnollisille kuville DFT (ja siten FFT) aiheuttaa mosaikkiefektiä kun lasketaan muunnosta lohkokoolla > 2, jolloin kuvan näkyvä laatu kärsii tai lohkokoon pysyessä pienenä, muunnos on tehoton. Hyvin lähelle KLT:n suorituskykyä sen sijaan pääsee diskreetti kosinimuunnos (DCT). DCT onkin lähes jokaisessa standardoidussa kuvien muunnoskoodaamisessa käytetty muunnos. Myös DCT:lle on löydetty FFT:hen verrattavissa oleva nopea toteutus, joka voidaan realisoida 8x8 kuvalle vain 5 (+8 skaalausta varten) kertolaskulla. Sekä tarvittava matriisikerroin, että yksinkertainen realisaatio löytyvät liittestä 2. Kvantisointi Kvantisoinnissa yksittäinen arvo pyöristetään johonkin lähimpänä olevaan, ennalta päätettyyn arvoon, joka pystytään ilmaisemaan pienemmällä bittimäärällä. JPEG:ssa käytetään tasavälistä skalaarikvantisointia (uniform scalar quantizer). Tasavälinen kvantisaattori on ajatukseltaan yksinkertainen ja helppototeuttaa, mutta se on hyvin harvalle kuvalle optimaali metodi. Toisaalta tasavälisyys mahdollistaa sulautetun kvantisoinnin, jolloin vasteena saatavan bittivirran alkuun liitetään vain osa muunnoskertoimista ja myöhemmin lisää ja taas lisää. Näin matalan bittinopeuksisen siirtomedian yli kuvaa siirrettäessä pystytään muodostamaan karkea kuva ennenkuin kaikki kuvan bitit ovat perillä. Tehokkuuden havaitsee selvästi www:stä kuvia siirtäessä, sillä hyvin mosaikkimaisen kuvan, joka tarkentuu vähitellen, voi saada ruudulleen sekunnissa, vaikka kokonaisen kuvan siirtoon kuluu kahdeksan sekuntia. Kuitenkin kvantisointivirheen minimoimiseksi tulisi tasavälisen sijaan käyttää esim. Lloyd-Max-kvantisaattoria, jossa päätöksentekokynnystä (engl. decision threshold) on siirretty kohti todennäköisempiä arvoja. Kaikkein suurin pakkaustehon nousu kuitenkin saavutetaan siirtymällä skalaarikvantisoinnista vekrtorikvantisointiin, jossa yksittäistä elementtiä (muunnoksesta saatua kerrointa) ei kvantisoida yksinään, vaan se kvantisoidaan yhdessä toisen elementin (edellisen/seuraava elementin) kanssa. Jos elementit ovat toisistaan riippuvaisia, niin niiden yhteinen todennäköisyyden tiheysfunktio ei peitä koko määritelyä avaruutta, vaan vain osan, jolloin yhtämonella kvantisointiportaalla tarvitsee kattaa vähemmän alaa ja näin kvantisointivirhe vähenee. Jopa elementtien ollessa riippumattomia kvantisointivirhe pienenee, sillä tällöin päätöksentekokynnykset saadaan tasaisemmin kvantisoidun arvon ympärille, mikä on esitetty kuvassa 5. Huomattava toki on, että vaikka usean elementin kvantisoinnissa virhe pienenee mitä enemmän elementtejä kvantisoidaan yhdessä (suurempi "koodivektori"), niin laskennan kompleksisuus kasvaa kahden potenssissa - esim. 512x512 lohko tuottaa koodivektoreita 2 512*512 =2 262144. Kuitenkin nykyisillä kotitietokoneilla esim. 8x8 lohkojen kvantisointi ei tuota lainkaan ongelmaa. Myöskään vektorikvantisaattorin ei tarvitse olla tasavälinen, eikä edes säännöllinen. Laskennallisen helppouden kannalta hyvä kompromissi onkin nk. Lattice-kvantisaattori, jossa päätöksentekokynnykset ovat tasavälein, mutta kvantisointiarvot eivät ole keskellä päätöksentekokynnyksiä, vaan ne on painotettu arvojen esiintymistodennäköisyyden mukaan. 6
Kuva 5 Skalaarikvantisointi lukusuoralla, skalaarikvantisointi esitettynä yhtäaikaa kahdella muuttujalla ja vekrtorikvantisointi kahdella muuttujalla, kun kvantisointirajojen muotoilulla pyritään kvantisointivirheen minimointiin ja kun x 1 ja x 2 ovat riippumattomia Subjektiivisuudesta Kuvan muuttaminen YCbCr-esitykseen on hyvä tyyppiesimerkki subjektiivisuuden tuomasta hyödystä: Ihmissilmä on paljon herkempi valoisuuden kuin värin muutokselle. Niinpä kvantisoimalla krominenssikomponentteja voimakkaammin kuin luminenssikomponenttia, voidaan bittimäärää pudottaa huomattavasti havaitun kuvanlaadun kärsimättä. Kuvassa 6 nähdään orginaalikuva, G- ja B-komponentteja kvantisoitu RGB-kuva sekä Cb- ja Cr-komponentteja kvantisoitu YCbCr-kuva. Kuva 6 Havaittu vääristymä samalla kvantisointisuhteella riippuu kvantisoiduista elementeistä JPEG käyttää luminenssi-krominenssi-esitystä oletusarvoisesti kuvien arkistoinnissa. Muita ihmissilmän epäideaalisuuksia se ei hyödynnä, mutta useimmat niistä ovatkin vielä psykofysiikan tutkimusten kohteena, eivätkä sinällään laskennallisesti hyödynnettävissä missään arkistointialgoritmissä. Yhteenveto JPEG on suosituin kuvien arkistoinimenetelmä, eikä suotta. Julkaisuvuonnaan 1991 se edusti uusimpia ja tehokkaimpia menetelmiä, jotka olivat tavallisella kotitietokoneellakin toteutettavissa järjellisessa ajassa. Kuitenkin niin koneet kuin menetelmätkin kehittyvät ja nykyään tunnetaan parannuksia JPEG:n algoritmeihin - mm. tässä esitellyt aritmeettinen koodaus Huffman-koodauksen tilalla ja vektorikvantisointi skalaarikvantisoinnin tilalla. Mahdollinen parannus olisi myös 7
moniresoluutioisuuden lisääminen eli että kuvasta olisi helposti irroitettavissa pienenpi resoluutioinen versio esim. kun www:n kuvaa haluttaisiin katsoa matkapuhelimen näytöltä. Muut JPEG:ssa käytetyt yksittäiset algoritmit edustavat edelleenkin kehityksen tehokkainta kärkeä, eikä juuri muita vaihtoehtoja yleisesti kuvankäsittelyssä tarjota. Kokonaan oma lukunsa on JPEG-2000-standardi, joka käyttää hyväkseen sekä aritmeettista koodausta, että vektorikvantisaatiota. Näiden lisäksi standardi tarjoaa laajan joukon määriteltyjä vaihtoehtoja, esim. häviöttömän koodauksen voi edelleenkin tehdä Huffman-koodauksella tai vaihtoehtoisesti aritmeettisella koodauksella; kvantisoitujen AC-komponenttien skannauksen voi tehdä zig-zag-skannauksella, ylhäältä-alas-skannauksella tai jollain muulla lukemattomista vaihtoehdoista. JPEG-2000:ssa on siis mahdollistettu vielä kaikki parannukset, joista JPEG:ssa tehtiin hyvä kompromisseja ja säilytetty silti kaikki toimivat osat. 8
LIITE 1 Lähteet: [1] D. Taubman: "JPEG2000-Image Compression Fundamentals, Standards and Practice", Kluwer Academic Publishers, 2002 [2] E. Steinbach: "Image and Video Compression", Technische Universität München, 2003 [3] D. Lee: An analytical study of JPEG functionalities, http://www.jpeg.org/public/wg1n1816.pdf, 2000 [4] E. Bodden: http://www.bodden.de/studies/ac/ 9
LIITE 2 Marko Knuutila: JPEG:n algoritmit ja niiden vaihtoehdot Nopea diskreetti kosinimuunnos, jonka muuntomatriisi A on hajoitettu kahdeksaan osaan, jotka noudattavat yhtälöä y=ax=spm 1 M 2 M 3 M 4 M 5 M 6 x, jossa y edustaa muunniksesta saatujen kertoimien vektoria ja x kuvapisteiden arvojen vektoria. Nopealle 8-DCT (käsitellään siis hyvänä kompromissina pidettävää 8x8-lohkoa) -algoritmille saadaan hyvin yksinkertainen realisaatio, jonka laskentaan tarvitaan vain viisi kertolaskua sekä skaalaukseen kahdeksan kertolaskua (laskennallisesti hyvin kevyt): Kuvassa laatikot a 1,a 2,... sekä s 0,s 1,... edustavat kertolaskua ja nuolet yhteenlaskua. 10