Képfeldolgozás (interpolálás,decimálás,szűrés alapjai: a színkülönbségi jelek-alulmintavételezése során, transzformációs kódolás, intra- és inter-predikció) MATLAB-al Multimédia technológiák alapjai gyakorlat I-II.
Tartalomjegyzék 1. MATLAB Image Processing Toolbox 4 2. Színkülönbségi-jel alulmintavételezési struktúrák megvalósítása 5 3. Kvantálás, transzformációs kódolás 6 3.1. A "gamma-korrekció", mint forrás oldali nem-lineáris átviteli függvény hatása a kvantálásra...................................... 6 3.2. Unitér transzformációk vizsgálata......................... 7 3.3. KLT transzformáció vizsgálata........................... 8 3.4. JPEG-szerű DCT alapú képtömörítés vizsgálata.................. 8 3.5. Változó blokkméretű DCT alapú képtömörítés vizsgálata............ 9 4. Intra- és inter-prediktív tömörítés demonstrációs példaprogramok 10 4.1. Mozgáskompenzált predikció............................ 10 5. H.264 intra-predikció demo 11 3
1. MATLAB Image Processing Toolbox Az általunk leginkább használt függvények a következők: A = imread(filename); Az A mátrixba beolvassa a filename nevű képfile tartalmát, ahol A sorainak száma a kép pixelben mért magasságával, A oszlopainak száma a kép pixelben mért szélességével egyezik meg. Ha a filname nevű képfile nem monokróm kép, hanem tipikusan pl RGB formátumú, akkor A egy 3D mátrix, ahol A = imread(filename); [Height_px,Width_px,NumberOfComponents]=size(A); RGB kép esetében a harmadik dimenzió mérete (NumberOfComponents) természetesen három. Ezek alapján az RGB kép R összetevőjének 2D komponens képét a A = imread(filename); R = A(:,:,1); indexeléssel kaphatjuk meg. RGB formátumú kép YCbCr komponens ábrázolásba a B = rgb2ycbcr(a) transzformációval vihető át. Ekkor pl. a világosságjel (a 2D fekete-fehér képtartalom) Y = B(:,:,1); indexeléssel kapható. A visszafelé transzformációra az A = ycbcr2rgb(b); függvény szolgál. Az imread által támogatott formátumok, többek között: JPG, BMP, PNG, GIF, TIF, stb. A komponensenkénti bitmélység 8 bit, egyes formátumok (pl. JPEG,PNG,TIF) esetén 16 bit/komponens lehet. Fontos, hogy a beolvasott A mátrix adattípusa ennek megfelelően uint8, vagy uint16. A nagy pontosságú műveletek, jellemzően lebegőpontos műveletek elvégzése előtt a pixel adatokat, vagy az egész mátrixot célszerű single, vagy double formátumba konvertálni. A megjelenítés előtt pedig uint8 (vagy uint16) formátumba kell visszakonvertálni a mátrixot. Pl: 4
A = imread(filename1); B = imread(filename2); [M,N,C]=size(B); MSE = sqrt( (1/(M*N))*sum(sum(abs(double(A)-double(B)).^2))); imshow(uint8(mse)); Tetszőleges képmátrix megjelenítésére az imshow(a); függény szolgál. Alapvetően monokróm (fekete-fehér) képmátrix (ahol size(a,3)=1), vagy RGB képmátrix (ahol size(a,3)=3) megjelenítésére szolgál. YCbCr ábrázolású képmátrix megjelenítéséhez a mátrixot RGB-be kell konvertálni. A képmátrix átméretezésére az imresize függvény szolgál: B = imresize(a, scale); B = imresize(a, [numrows numcols]); A scale megadásával tetszőleges skálázható a képmátrix (scale>1: nagyítás, scale<1 kicsinyítés), illetve tetszőleges pixelben kifejezett új méret ([numrows numcols])is megadható. Ezen átméretezések minden esetben decimálással/interpolálással, illetve általánosságban a képraszter újramintavételezésével járnak. Ennek végrahajtására többféle interpolációs lehetőség/szűrés közül választhatunk, pl: B = imresize(a, scale, nearest ); B = imresize(a, scale, bilinear ); B = imresize(a, scale, bicubic ); Kicsinyítés (decimálás) esetén ezen eljárások mind tartalmazzák az anti-aliasing szűrést is. A konkrét interpolációs eljárásokról a későbbiekben szó lesz még 2. Színkülönbségi-jel alulmintavételezési struktúrák megvalósítása chroma_subsampling.m 5
A scripttel a 4:2:2, 4:2:0, 4:1:1 mintastruktúrák különböző szűrési eljárásokkal történő megvalósításának hatásait vizsgálhatjuk. Az RGB komponensű kép beolvasása után YCbCr komponens ábrázolásra térünk át. A Cr/Cb komponens képeket a kiválasztott alulmintavételezési struktúrának megfelelően, és a kiválasztott szűrési módszer alkalmazásával szűrjük (alul-áteresztő szűrés), majd decimáljuk. A szűrésre-decimálásra a MATLAB imresize függvényében implementált jó minőségű kettős-köbös (bicubic) interpolációra épülő alulmintavételezést használhatjuk, vagy az egyszerű [1/2 1/2], illetve [1/4 1/4 1/4 1/4] együtthatóvektorú átlagoló-aluláteresztő szűrőt (combfilter). A színkülönbségi jelek alulmintavételezése után, a kép megjelenítéséhez szükség van alulmintavételezett Cr/Cb komponensek eredeti mintaszámának visszaállítására (upsampling), vagyis a hiányzó Cr/Cb jelek "pótlására", melyre ismét a MATLAB imresize bicubic opcióját, vagy az egyszerű mintaismétlést alkalmazhatjuk. Vizsgáljuk meg különböző képekre az ismertetett dowsampling/upsampling eljárások kombinációt, természetesen az összehasonlítás különösen "drámai" a bicubic/bicubic, avg/repeat kombinációk összehasonlítása esetén. 3. Kvantálás, transzformációs kódolás 3.1. A "gamma-korrekció", mint forrás oldali nem-lineáris átviteli függvény hatása a kvantálásra quantizer_gamma.m A programkód segítségével beolvasunk egy tetszőleges lineáris tiff képet (annak világosságjel komponensét). A = imread( IMG_XXX_srgb_debayer_lin.tiff ); A = 0.2126 * A(:,:,1) + 0.7152 * A(:,:,2) + 0.0722 * A(:,:,3); A=uint8(A/255); A bemeneti TIFF kép 16 bites/komponens formátumú, ezért 8 bit/komponens formátumra történő konverzióhoz leosztjuk 256-al. A lineáris képet az ITU-709 transzfer karakterisztika szerint korrigáljuk, és ezt használjuk a továbbiakban referenciaképként. 6
A_ref=round(255*itu_709_nltf(double(A)/255)); Innen a program alapvetően két működési módban használható: a GAMMA-ENABLED=0 esetén a linearizált képmátrixot különböző bitmélységekre újrakvantáljuk, majd az újrakvantált képmátrixot gamma-korrigáljuk (szintén az ITU-709 transzfer függvény szerint), hogy a megjelenítésnél tónushelyes képet kapjunk (ne feledkezzünk meg a kijelző gamma karakterisztikájáról!) GAMMA-ENABLED=1 esetében a különböző bitmélységű újrakvantálás előtt gamma-korrigáljuk a képet (ITU-709 transzfer függvény szerint), így az újrakvantálás után a megjelenítésnél tónushelyes képet kapunk. Az ITU-709 transzfer karakterisztikát megvalósító függvény: function [Vg] = itu_709_nltf(v) Vg=zeros(size(V)); Vg(V<0.018)=4.5*V(V<0.018); Vg(V>=0.018)=1.099 *(V(V>=0.018)).^0.45-0.099; Az eredetileg 8 bites f kép b számú bitre történő újrakvantálása, majd az uint8 0-255 tartományára való visszaszorzása a következőképpen történik: L = 2^b; q = 256/L; fq = round(floor(f/q + 0.5)*q); Hasonlítsuk össze különböző képek esetén az újrakvantálás előtti, illetve a újrakvantálás utáni gamma-korrekció hatását. Figyeljünk a viszonylag homogén, illetve kis intenzitásgradiensű képterületek sávosodására. Melyik esetben jelentkezik jobban a sávosodás, milyen bitmélységeknél? 3.2. Unitér transzformációk vizsgálata base_images.m A script a DCT, DST, Hartley, Haar, Hadamard és Slant transzformációk bázisképeit jeleníti meg tetszőleges NxN-es blokkméret esetére. Tetszőleges beolvasott képet előállít ezen 7
bázisképek összegeként, megjeleníti a közbenső képeket, illetve a bázisképek számának függényében a PSNR értéket. A MATLAB script user input részében kiválaszthatjuk a vizsgálandó transzformáció típusát (TransformType), a transzformáció blokkméretét (N), valamint a show_img_num_base_imag vektorban megadott egész értékek segítségével megadhatjuk, hogy hány báziskép lineáris kombinációjaként előállított közelítő képeket szeretnénk megtekinteni. Pl. ha show_img_num_base 5 10], akkor az első 2, 5 illetve 10 báziskép lineáris kombinációjaként előállított közelítő képeket tekinthetjük meg. A bázisképek felhasználásának sorrendje sorfolytonos. Hasonlítsuk össze néhány képre, azonos blokkméret esetén a különböző transzformációs típusok hatékonyságát, elsősorban a PSNR érték alapján. Hogyan változik a transzformáció hatékonysága a blokkméret növelésével? 3.3. KLT transzformáció vizsgálata klt_example.m A script az adott kép NxN-es blokkjaira kiszámolt KLT transzformáció bázisképeit jeleníti meg tetszőleges NxN-es blokkméret esetére. Tetszőleges beolvasott képet előállít ezen bázisképek összegeként, megjeleníti a közbenső képeket, illetve a bázisképek számának függényében a PSNR értéket. A show_img_num_base_images vektorban megadott egész értékek segítségével megadhatjuk, hogy hány báziskép lineáris kombinációjaként előállított közelítő képeket szeretnénk megtekinteni. Pl. ha show_img_num_base_images=[2 5 10], akkor az első 2, 5 illetve 10 báziskép lineáris kombinációjaként előállított közelítő képeket tekinthetjük meg. A bázisképek felhasználásának sorrendje sorfolytonos. Állapítsuk meg a kódból, hogyan történik a blokkok kovarianciamátrixának közelítése! Hasonlítsuk össze néhány képre, azonos blokkméret esetén a KLT-közelítés hatékonyságát, elsősorban a PSNR érték alapján. Hasonlítsuk össze a KLT-közelítés hatékonyságát a DCT-hez képest, a 3.2 fejezet kódjának használatával 3.4. JPEG-szerű DCT alapú képtömörítés vizsgálata 8
JPEG_blockiness.m A kód tetszőleges képre (a világosságjel komponensre) elvégzi az NxN-es blokk alapú DCT transzformációt, és a kapott DCT együtthatókat a JPEG kvantáló mátrixának és egy Qscale skálafaktor szorzatának megfelelő kvantálási lépcsők szerint újrakvantálja. A kép egy tetszőlegesen kiválasztott sorának intenzitásprofilját megvizsgálhatjuk a DCT alapú tömörítés alkalmazása előtt (eredeti kép), és a a DCT alapú tömörítés alkalmazása után. A Selected_Row paraméterrel adhatjuk meg, hogy mely sor intenzitásprofilját szeretnénk megjeleníteni. Az eredeti, illetve a tömörített kép intenzitásprofiljának megjelenítésével egyszerű, 1D grafikon formájában jeleníthető meg a DCT együtthatók újrakvantálásának veszteséges hatása. Keressük meg az intenzitásprofilon a nagyfrekvenciás térbeli komponensek elhagyásának/újrakvantálásának hatásait: pl. éles kontrasztátmenetesek ellaposodása, hamis oszcillációk megjelenése. Keressük meg a homogén területeken a DC, illetve kisfrekvenciás AC komponensek újrakvantálásának hatásait: pl. blokkosodás. Vizsgáljuk meg néhány képre a blokkosodást, illetve a PSNR értéket a blokkméret (N), illetve kvantálási skálafaktor (Q_scale) függvényében! Mit valósít meg a Wq = [16 11 10 16 24 40 51 61; 12 12 14 19 26 58 60 55; 14 13 16 24 40 57 69 56; 14 17 22 29 51 87 80 62; 18 22 37 56 68 109 103 77; 24 35 55 64 81 194 113 92; 49 64 78 87 103 121 120 101; 72 92 95 98 121 100 103 99]; if not(n==size(wq,1)) Wq=round(imresize(Wq,[N N], nearest )); end kódrészlet? 3.5. Változó blokkméretű DCT alapú képtömörítés vizsgálata 9
var_n_block_dct.m A kód nagyban hasonlít a 3.4 fejezet JPEG-szerű kódolójához. Az alkalmazott DCT transzformáció ellenben nem fix NxN-es blokkméretű, hanem a képtartalom függvényében 2x2-től 32x32-ig terjedő blokkméretű DCT-t alkalmaz. A képtartalomfüggő blokkfelbontást (quadtree alapú szub-blokk képzést) a MATLAB Image Processing Toolbox qtdecomp függvénye segíti. A qtdecomp tetszőleges négyzetes képmátrix homogenitását vizsgálja. Ha a képmátrixon belül a homogenitás egy beállítható küszöbértéket teljesít, akkor a négyzetes blokkon nem bontja tovább. Ha a homogenitási kritérium nem teljesül, a négyzetes képmátrixot négy egyenlő részre bontja, majd ezek homogenitását vizsgálja. A függvény rekurzívan addig bontja szub-blokkokra az eredeti képblokkot, amíg minden szub-blokk teljesíti a homogenitási kritériumot, vagy a felbontás elérte a megadott legkisebb blokkméretet. A homogenitási határérték 0 és 1 között értelmezett. A kód a 8x8-as szabványos JPEG kvantáló mátrixot decimálja/interpolálja a 2x2-es-től 32x32-es blokkméretig. Minden blokkméret esetén a kapott kvantáló mátrixot megszorozza egy beállított (minden blokkméretre azonos) Qscale kvantálási skálafaktorral. Vizsgáljuk meg a változó blokkméretű kódolás hatását különböző képekre, különböző kvantálási skálafaktor (Qscale), és homogenitási határérték (Thresh) érték mellett. Hasonlítsuk össze a kapott PSNR értékeket ugyanarra a képre a 3.4 fejezet fix blokkméretű kódolójával kapott PSNR értékekkel! 4. Intra- és inter-prediktív tömörítés demonstrációs példaprogramok 4.1. Mozgáskompenzált predikció Vonatkozó MATLAB scriptek: motion_comp_pred_full_search_seq.m motion_comp_pred_hierch_search_seq.m mot_pred_coding.m Teljes keresés, illetve hierarchikus (3 felbontási szintet használó) keresést használó mozgáskompenzált predikció vizsgálata. Az football-seq, tennis-seq, stefan-seq alkönyvtárakban található képszekvenciák néhány 10 - max. 100 képkockát tartalmazó részletein vizsgáljuk meg a két script működését. 10
A vizsgálandó szekvencia a filename_mask változóban megadott alkönyvtárnévvel választható ki, míg a vizsgált tartomány frame-ekben mért hossza a seq_length paraméterrel. A for I=1:seq_length-1, sor módosításával a vizsgált tartományt tetszőleges tartományra módosíthatjuk. Pl. a 10.... 20. képkockák közötti tartomány elemzéséhez: for I=10:20, A teljes keresés esetén választhatunk full, half, quarter - pixel pontosságú mozgásvektor meghatározások között (PredictionType változó), természetesen a pontosság esetén a sebesség rovására. Hasonlítsuk össze a teljes keresés sebességét, illetve pontosságát (PSNR) alapján a hierarchikus keresés pontosságához képest, ugyanazon szekvencia ugyanazon intervallumára. 5. H.264 intra-predikció demo intra_pred_h264.m A kód tetszőleges kép 4x4-es blokkméret alapú intra-predikciós hibaképét számolja ki a H.264/AVC szabvány szerinti 9 lehetséges predikciós irány/lehetőség használatával. A képet 4x4-es blokkokra osztja, és minden 4x4-es blokkot a tőle balra és fölötte lévő blokkok szomszédos pixeleinek meghatározott lineáris kombinációjából prediktíven kódol. Minden blokk esetében a lehető legkisebb predikciós hibát eredményező predikciós irányt választja. Vizsgáljuk meg, hogy a különböző képek esetén a használt predikciós irányoknak milyen statisztikája alakul ki. Hogyan értelmezhető a program végén kiírt predikciós nyereség? fprintf( Prediction Gain = %5.2f db\n,20*log10(std2(a)/std2(e))) A predikciós irányok szerinti predikciós hibaképet számító IntraBlkPredict függvényben szereplő SAD kritérium mit fejez ki, és miért lehet előnyösebb a használata, mint az MSE használata? 11