Podpróbkowanie chrominancji

 
Grafika komputerowa przyzwyczaiła nas w pewnym sensie do tego, że każdy element obrazu – piksel – przedstawiony jest jako trójka składowych R-G-B, czyli czerwony-zielony-niebieski. Jest to o tyle oczywiste, że z tych trzech kolorów w drodze addytywnego mieszania można stworzyć całą przestrzeń kolorów. Jednak w cyfrowym wideo w ogóle nie znalazło się miejsce dla RGB. Ba, już w standardzie JPEG, przeznaczonym dla zdjęć, zamiast RGB pojawiają się inne literki – YUV. Przestrzenie barw to temat na osobny, obszerny wpis, tutaj skoncentruję się na YUV a w szczególności na pewnej powszechnej i nieodzownej praktyce stosowanej w kodowaniu wideo, określanej jako podpróbkowanie chrominancji (chroma subsampling).

 Trochę historii

Telewizja analogowa w swoich początkach i przez długi czas była telewizją czarno białą. Czerń i biel – czyli dwie skrajne wartości jasności, inaczej luminancji, a pomiędzy nimi cały zakres tzw. szarości. Tym widzowie musieli się zadowalać przez lata. Podczas transmisji wystawnej ceremonii koronacji Elżbiety II w czarno białej telewizji widzowie musieli nieco wysilić wyobraźnię polegając na relacji komentatorów.
Lecz wkrótce opracowano standardy telewizji kolorowej. Na analogowy sygnał luminancji nałożono wysokoczęstotliwościowy sygnał niosący informację o barwie i nasyceniu i tak powstała telewizja kolorowa. Ponieważ forma sygnału luminancji nie zmieniła się – nadal był to sygnał analogowy, linia po linii, gdzie wyższa wartość oznaczała plamkę jaśniejszą a niższa ciemniejszą – stare odbiorniki czarno białe mogły w dalszym ciągu odbierać telewizję bez zniekształceń.

Z kolei komputery, ich karty graficzne i wyświetlacze, od CRT do LCD, przyzwyczaiły nas do zapisu obrazów w przestrzeni RGB, dość naturalnej i bezpośrednio zrozumiałej, wszak każdą barwę na ekranie możemy przedstawić jako sumę trzech źródeł światła – czerwonego, zielonego i niebieskiego.

YUV

W telewizji cyfrowej mamy z kolei do czynienia z przestrzenią YUV. Y jest skłądową luminancji, odpowiadającą jasności, czyli obrazowi “czarno białemu”, a U i V to składowe chrominancji, które wspólnie decydują o barwie i nasyceniu piksela. Dość trudno jest zobrazować U i V, w przeciwieństwie do RGB. Wikipedia ukazuje rozkład na YUV w sposób następujący:

barn

Jak widać Y odpowiada obrazowi w skali szarości (czarno białemu) a U i V barwom i nasyceniu.

W przypadku cyfrowego wideo naukowcy i inżynierowie poszli trochę dalej. Otóż ludzkie oko, mimo że widzi i rozróżnia kolory, nie jest zbyt czułe na niewielkie zmiany barw. I tu nie chodzi o legendarny spór czy kobiety lepiej rozróżniają kolory od mężczyzn – bardziej chodzi o biologię i konstrukcję oka. Pręcików, odpowiadających za rejestrację jasności mamy aż 20 razy więcej niż czułych na barwę czopków. A to pręciki powodują, że widzimy wyraźnie kontury, że jesteśmy w stanie zarejestrować nawet drobny ruch.
Idąc tym tropem inżynierowie już w standardzie JPEG wprowadzili podpróbkowanie chrominancji w stosunku 4:2:0. Co to znaczy? Że jeśli obrazek ma 100×100 pikseli, to próbek Y (luminancji) będzie 10000, lecz chrominancji U i V będzie odpowiednio tylko po 2500 U i 2500 V. Oko nie jest w stanie uchwycić, że w obrazie YUV 4:2:0 jest znacznie mniej informacji o barwie niż w obrazie oryginalnym.
O co w takim razie chodziło specom z JPEG i MPEG, że okradli nas z ładnych kilku bajtów obrazu ot tak? Chodzi przede wszystkim o oszczędność. Dzięki podpróbkowaniu, w przypadku schematu 4:2:0, rozmiar niezakodowanego obrazu spadł aż o połowę. Przez to możemy mówić o sporej stratności jeszcze przed etapem właściwej kompresji.

4:2:0, 4:1:1, 4:2:2 ?

Sposób próbkowania chrominancji oznacza się trzema liczbami 4:J:K . Pierwszą zawsze jest 4, bo oznacza liczbę próbek luminancji, do której odnosi się ten stosunek. Najłatwiej czytać tę czwórkę jako rząd 4 pikseli w poziomie. Na takie rzędy dzielimy cały obraz.
J jest liczbą próbek chrominancji w pierwszym polu (field) obrazu – termin pole wywodzi się z określania w ten sposób półobrazu w telewizji z przeplotem. Innymi słowy J mówi ile próbek każdej ze składowych chrominancji przypada na rząd próbek luminancji w nieparzystej linii. Trzecia liczba – K – mówi o tym ile dodatkowych próbek chrominancji w drugim polu przypada rząd próbek luminancji w linii parzystej. To niestety bezwzględnie wymaga ilustracji:

yuv-y-grid

Stosunek 4:J:K wyznacza się w oparciu o prostokąt z próbkami luminancji od Y11 do Y24. Stąd można się już domyśleć, że obrazek bez podpróbkowania chrominancji będzie miał stosunek 4:4:4 . Na 4 próbki Y w pierwszym wierszu przypadać będzie po 4 próbki (czyli w sumie 8) chrominancji U i V, tak samo na 4 próbki w drugim wierszu przypadną po 4 kolejne próbki chrominancji.

4:4:4

yuv-444

Każda próbka luminancji ma odpowiadające sobie 2 próbki chrominancji U i V. Podpróbkowania tutaj nie ma. Weźmy zatem najpopularniejszy chyba schemat próbkowania – 4:2:0

4:2:0

yuv-420

Dla czterech próbek chrominancji z pierwszego wiersza mamy tylko po dwie próbki chrominancji. Trzecią cyfrą jest 0, co znaczy, że w drugim wierszu nie będzie dodatkowych próbek chrominancji, czyli że będą te, przypadające na wiersz pierwszy. Czyli na jeden kwadrat 2×2 pikseli przypada oddzielna para próbek chrominancji. Jest to już dość znaczne podpróbkowanie, aczkolwiek jak wspomniałem wyżej, bardzo częste.

4:1:1

 

yuv-411

W pierwszym wierszu tylko jedna para (U,V), w drugim dodatkowa pojedyncza para (U,V), w sumie ilość próbek będzie identyczna jak w próbkowaniu 4:2:0 . Ten schemat jest rzadko spotykany w cyfrowym wideo.

4:2:2

yuv-422

W przypadku 4:2:2 mamy dwie pary (U,V) na cztery Y w pierwszym rzędzie, oraz dodatkowe dwie pary w drugim rzędzie. Ten format jest spotykany czasami na przykład w wysokiej jakości materiałach kodowanych h264, który przewiduje zarówno próbkowanie 4:2:2 jak i 4:4:4. Czasami przy tym ostatnim schemacie używa się (moim zdaniem niepoprawnie) terminu “lossless”, co jednak tyczy się jedynie próbkowania a nie samej kompresji.

Można sobie spróbować wyobrazić pozostałe permutacje zapisu 4:J:K ale nie mają one większego sensu. Podobnie jak wspominany w Wikipedii schemat 3:1:1.

Zniekształcenia

W przypadku typowych filmów czy zdjęć JPEG nie da się w zasadzie zauważyć wpływu podpróbkowania chrominancji. Być może w przypadku kreskówki w rozdzielczości PAL, wysilając oczy i korzystając ze stopklatki dałoby się złowić gołym okiem jakieś zniekształcenia przy np. próbkowaniu 4:2:0. Dlatego przygotowałem specjalny materiał pokazujący jak podpróbkowanie może uwidocznić się na tyle, aby można było zaobserwować jego skutki.

W tym celu mam taki oto obrazek w rozmiarze 720×576:

chroma

Rozmiary prostokątów nie są równe. Krawędzie prostokątów spotykają się prawie w połowie szerokości i wysokości. Prawie, czyli w połowie minus jeden piksel. Chodzi o to, żeby w miejscu połączenia kodek był zmuszony uśrednić chrominancje sąsiadujących prostokątów przy próbkowaniu 4:2:0.

Teraz skorzystam z ffmpega, chociaż w zasadzie tym razem jest to avconv, czyli (nie do końca) niezależny fork ffmpega. Zamierzam zakodować przy pomocy x264 powyższy obrazek z próbkowaniem YUV 4:2:0

Oto co z tego wyszło:

https://dl.dropboxusercontent.com/u/24943126/chroma.mp4

Teraz w drugą stronę, czyli wybieramy pojedynczą zakodowaną ramkę i zapisujemy jako png

Która prezentuje się tak:

chroma420

Ciężko tu może coś wychwycić, więc pozwolę sobie na zbliżenie:

chroma420_zoom

Tak objawiło się uśrednienie chrominancji na styku pól o różnych kolorach. W zasadzie jest to mało zauważalne zniekształcenie, co idealnie tłumaczy dlaczego tęgie głowy z JPEG i MPEG zdecydowały się na taki trik.
W poprzednich wpisach wspominałem, że w zasadzie cała stratna kompresja obrazu i wideo opiera się na niedoskonałościach naszej percepcji. Do tego można śmiało dołączyć operację podpróbkowania chrominancji, jest to kolejny magiczny trik, który pozwala zaoszczędzić pasmo i miejsce na nośniku bez widocznej utraty jakości wideo.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">