Studia Wieczorowe Wrocław, 27.03.2007 Kodowanie informacji Wykład 5 Kodowanie predykcyjne Idea: przewidujemy następny element ciągu i kodujemy różnicę między wartością przewidywaną i rzeczywistą, w oparciu o kontekst (wybrane symbole spośród wcześniej zakodowanych, w sąsiedztwie kodowanego), określamy rozkład prawdopodobieństwa stosowany przy kodowaniu bieżącego symbolu, zazwyczaj przy użyciu algorytmów dla ciągów niezależnych wartości. Przykład: Słowo prawdopodobieństwo, zakodowana część to prawdopo, rozkład dla następnej litery w kontekście prawdopo NA PEWNO preferuje d. WADA: np. kontekstów 8-literowych jest 26 8 czyli kolosalnie dużo. Predykcja z częściowym dopasowaniem (ppm=prediction with partial matching) Autorzy: Cleary, Witten Rok: 1984 Idea: stosujemy kodowanie arytmetyczne (właściwie implementację całkowitoliczbową) rozkłady prawdopodobieństwa zależne od kontekstu kodowanej litery, rozkłady ustalane dynamicznie, w oparciu o przeczytane dane! znamy rozkłady TYLKO dla kontekstów, które już wystąpiły, rozważamy konteksty o różnych długościach, ale nie większe od ustalonego maksimum. Pojęcia: Kontekst: Dany tekst prawdopod Dla ostatniej litery: Rząd kontekstu Kontekst 0 Pusty 1 o 2 po 3 opo Konteksty nietypowe: kontekst rzędu 0 liczba wystąpień litery,
kontekst rzędu 1 oznacza rozkład jednostajny na wszystkich symbolach alfabetu (rozważany, gdy litera nie wystąpiła w tekście w ogóle). Licznik kontekstu dla litery t i kontekstu k: określa ile razy t wystąpiła (w dotychczas przeczytanej części tekstu) w kontekście k. W przypadku kontekstu k rzędu 0 licznik określa liczbę wystąpień litery t w tekście. Symbol Escape wirtualny symbol w każdym kontekście, który kodujemy gdy symbol kodowany NIE wystąpił jeszcze w danym kontekście. UWAGA: przyjmujemy, że w każdym kontekście symbol Escape wystąpił jeden raz. Tablica częstości dla kontekstu k: zawiera liczniku kontekstu k dla wszystkich liter t, które wystąpiły w kontekście k, i dla symbolu Escape: Tablica kontekstów długości j: zawiera wszystkie konteksty o długości j, które wystąpiły w tekście, wraz z ich licznikami kontekstu. ALGORYTM KODOWANIA: Dane: Kodowany tekst x=x 1..x n Maksymalna długość kontekstu m. Algorytm (uwaga w praktyce używana całkowitoliczbowa wersja kodowania arytmetycznego): lw := 0; pr := 1; Dla każdego j=0,1,..,m Tablica kontekstów długości j - PUSTA Dla i = 1,2,...,n (kodowanie x i ): Niech p m to maksymalna wartość taka, że tablica kontekstu dla x i-p..x i-1 jest niepusta znaleziony = false Dla j = p, p-1,...2,1,0: y = x i-j..x i-1 zmodyfikuj licznik kontekstu y dla litery x i ; Jeśli (znaleziony=false oraz x i wystąpiło wcześniej w kontekście y): o wybierz podprzedział odpowiadający x i, zmodyfikuj lw, pr; o znaleziony := true Jeśli (znaleziony=true oraz x i NIE wystąpiło wcześniej w kontekście y): o wybierz podprzedział odpowiadający symbolowi Escape w kontekście y, zmodyfikuj lw, pr. Zakodowana postać tekstu to wartość znacznika (zaokrąglana tak jak w klasycznym kodowaniu arytmetycznym). DEKODOWANIE: analogicznie do dekodowania w przypadku kodowania arytmetycznego, z tym, że po każdym odkodowanym symbolu modyfikowane są tablice kontekstów, tak samo jak w procesie kodowania. Przykład sposób ustalania podprzedziałów:
Maksymalna długość kontekstu m=2 (w praktyce stosuje się co najmniej 5): Kodujemy fragment est, dokładniej literę t. Zakładamy, że tablica kontekstów długości 2 zawiera następującą tablicę częstości dla kontekstu es: Kontekst: es Litera Licznik s 3 y 2 Escape 1 Widzimy więc, że: t nie wystąpiło w kontekście es, kodujemy symbol Escape kodowanie Escape: prawdopodobieństwo równe 1/(3+2+1)=1/6, w podziale przedziału oryginalnego zajmuje ostatnią część [5/6; 1), modyfikujemy przedział. Dodajemy do tablicy kontekstu es wystąpienie t: Kontekst: es Litera Licznik s 3 t 1 y 2 Escape 1 Przechodzimy do kontekstów rzędu 1, dla s tablica zawiera: Kontekst: s Litera Licznik y 5 s 4 u 1 t 2 Escape 1 Zatem: kodujemy t: jego prawdopodobieństwo to 2/(5+4+1+2+1)=2/13, odpowiada mu przedział [10/13,12/13), wg tych proporcji dzielimy aktualny podprzedział; zwiększamy licznik t o jeden. Kontekst: s Litera Licznik y 5 s 4 u 1 t 3 Escape 1 modyfikujemy też tabelę kontekstu pustego! UWAGI: rozważane różne modyfikacje inaczej traktujące symbol Escape (ppma, ppmb, ppmc). wzrost długości kontekstu tylko do pewnego momentu zwiększa kompresję (dla długich
kontekstów będziemy być może musieli wielokrotnie kodować symbol Escape); zasada wyłączania: jeśli odrzuciliśmy dłuższy kontekst, to w krótszym nie uwzględniamy liter, które pojawiły się w dłuższym (PRZYKŁAD może być powyższy), co zwiększa prawdopodobieństwo symbolu kodowanego.
Algorytm Burrowsa-Wheelera (BWT) Autor: Burrows (1994) w oparciu o transformatę Wheelera (1983). Cechy: nie jest możliwe kodowanie on-line algorytm dekompresji mało oczywisty, ale wymaga mniej obliczeń niż kompresja. KODOWANIE: Dane: Tekst x=x 1..x n o długości n. Wynik: ciąg y 1..y n oraz liczba j z przedziału [1,n] Algorytm: 1. Niech X 1, X 2,...,X n to wszystkie przesunięcia cykliczne x 2. Niech Y 1, Y 2,...,Y n oznacza uporządkowany leksykograficznie zbiór {X 1,..,X n } 3. y i to ostatni znak napisu Y i 4. j to pozycja ciągu x w ciągu Y. Przykład. Dane (przyjmujemy, że kolejność liter alfabetu jest następująca ; < O < T < U): x=oto;tu;to X1 X2 X3 X4 X5 X6 X7 X8 X9 OTO;TU;TO TO;TU;TOO O;TU;TOOT ;TU;TOOTO TU;TOOTO; U;TOOTO;T ;TOOTO;TU TOOTO;TU; OOTO;TU;T Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 ;TOOTO;TU ;TU;TOOTO O;TU;TOOT OOTO;TU;T OTO;TU;TO TO;TU;TOO TOOTO;TU; TU;TOOTO; U;TOOTO;T Zakodowana postać tekstu: [UOTTOO;;T 5]. DEKODOWANIE: Dane: [y 1..y n j] Wynik: odkodowany ciąg D[1]..D[n] 1. Posortuj y 1..y n : niech z 1..z n to posortowany ciąg y 1..y n 2. Wartości 1..n oznacz jako WOLNE 3. Dla i = 1..n a. wyznacz minimalne k takie, że y i = z k i k WOLNE b. oznacz k jako zajęte c. T[i]:=k 4. D[n]:= y j 5. k := j 6. Dla i=1..n-1 a. k := T[k]
b. D[n-i] := y k PRZYKŁAD: Dane: [ UOTTOO;;T 5 ] Ciąg 1 2 3 4 5 6 7 8 9 y 1..y n U O T T O O ; ; T oryginalny z 1..z n ; ; O O O T T T U posortowany T 9 3 6 7 4 5 1 2 8 D O T O ; T U ; T O k = 5 4 7 1 9 8 2 3 PYTANIA: 1. Jaki cel kodowania skoro brak kompresji: Uzyskujemy długie ciągi powtórzeń tego samego symbolu a następnie wykorzystujemy metody kompresji bazujące na takiej zależności. 2. Skąd biorą się te ciągi powtórzeń? Przykład: jaki symbol występować będzie (często) na ostatniej pozycji cyklicznych przesunięć zaczynających się od est? Odpowiedź na to pytanie wyjaśnia, że w postaci zakodowanej będą występować ciągi powtórzeń tego samego znaku! 3. Czy ten algorytm jest poprawny czy dekompresja zawsze prowadzi do odtworzenia oryginalnego tekstu? Uzyskanie kompresji kodowanie ciągu wynikowego metodą mtf (move to front). Dane: ciąg x = x 1..x n Algorytm: 1. Przyporządkowanie kolejnych liczb naturalnych symbolom występującym w danych (od zera). 2. Dla i=1,..,n a. zakoduj x i za pomocą liczby odpowiadającej jego numerowi (i prześlij kod) b. przenieś x i na pozycję 0 (a symbole występujące przed nim o jedną pozycję niżej) Efekt: ciągi powtórzeń tego samego symbolu zostają zamienione na ciągi zer; dla wynikowego ciągu stosujemy metodę dla ciągów niezależnych wartości (np. kodowanie arytmetyczne). POPRAWNOŚĆ ALGORYTMU Burrowsa-Wheelera (dekodowanie): Obserwacje: 1. Traktujemy ciąg do zakodowania jako słowo cykliczne, w szczególności przyjmujemy, że ostatni symbol poprzedza pierwszy. 2. Wtedy relacja poprzedzania jest taka sama na wszystkich ciągach będących cyklicznymi przesunięciami ciągu oryginalnego. 3. Zauważmy, że
o ostatni symbol ciągu kodowanego (czyli x n ) znamy z jego postaci zakodowanej y (jest na pozycji j), o a pierwszy symbol ciągu x to j-ty symbol po posortowaniu y, czyli j-ty symbol ciągu z (tak samo jest dla innych ciągów!). 4. Gdybyśmy dla j-tego wiersza wśród wierszy posortowanych potrafili znaleźć POZYCJĘ j, jego cyklicznego przesunięcia o jeden w prawo to znalibyśmy przedostatni symbol tekstu, ponieważ - ostatni symbol stałby się pierwszym, przedostatni będzie ostatnim symbolem w j, który możemy prosto wyznaczyć z ciągu y (jest y[j ]). 5. Pozycje cyklicznych przesunięć wierszy w prawo wyznacza właśnie tablica T. Dowód: Niech y ciąg ostatnich pozycji w tablicy posortowanej, z ciąg pierwszych pozycji (czyli posortowany) Zauważmy, że cykliczne przesunięcie w prawo o jeden wiersza j - zaczyna się od ostatniego znaku wiersza j (powiedzmy a), - zatem jest na jednej z pozycji, na której w słowie z występuje litera a. Skoro jednak ciągi są posortowane, to dwa ciągi zaczynające się od a posortowane są względem pozostałych pozycji wobec tego przesunięcie w prawo pierwszego ciągu kończącego się na a jest na pozycji pierwszego a w słowie z, drugiego na pozycji drugiego a, itd. 6. W oparciu o powyższe obserwacje najpierw wyznaczamy ostatni symbol ciągu dekodowanego równy y j, jest on pierwszym symbolem w ciągu na pozycji T[j], więc poprzedza go ostatni w T[j] symbol y[t[j]], ten z kolei jest pierwszy w T[T[j]] więc poprzedza go y[t[t[j]]] itd. Przykład: [UOTTOO;;T 5] y= UOTTOO;;T z=;;oootttu PRZESUNIECIA: Y1 ;TOOTO;TU Y2 ;TU;TOOTO Y3 O;TU;TOOT Y4 OOTO;TU;T Y5 OTO;TU;TO Y6 TO;TU;TOO Y7 TOOTO;TU; Y8 TU;TOOTO; Y9 U;TOOTO;T
Bezstratny JPEG (JPEG-LS) JPEG=Joint Photographic Experts Group JPEG-LS: standard starszy statyczny i wieloprzebiegowy: KROK 1. wybieramy jeden z ośmiu trybów predykcji (np. najlepszy po sprawdzeniu wszystkich): I (i,j)= 1 0 2 I(i-1,j) 3 I(i,j-1) 4 I(i-1,j-1) 5 I(i,j-1) + I(i-1, j) I(i-1, j-1) 6 I(i,j-1) + (I(i-1,j)-I(i-1, j-1))/2 7 I(i-1,j) + (I(i,j-1) I(i-1, j-1))/2 8 (I(i,j-1) + I(i-1,j))/2 KROK 2. Dla kolejnych pikseli kodujemy różnice między wartością predykcji i faktyczną wartością piksela: I (i,j)-i(i,j). KROK 3. Ciąg utworzony w kroku 2 kodujemy algorytmem kodowania ciągów niezależnych wartości (np. kodowanie arytmetyczne). JPEG-LS: standard nowszy podejście dynamiczne, jednoprzebiegowe (podobne do CALIC) NN NNE NW N NE WW W X Krok 1: Dla piksela X wyznaczamy wartość przewidywaną wg algorytmu: 1. Jeśli NW max(w, N) to X = max(w,n), w przeciwnym razie: 2. Jeśli NW min(w, N) to X = min(w,n) 3. Jeśli nie zachodzi 1. ani 2. : X = W+N-NW Krok 2: X =X +S, gdzie S średnia wartość błędu predykcji w aktualnym kontekście Krok 3: Kodujemy różnicę między X a rzeczywistą wartość piksela X. Używamy kodu Golomba (adaptacyjnego!) najlepszego dla rozkładu geometrycznego zakładamy że przy liniowym wzroście błędu predykcji prawdopodobieństwo maleje wykładniczo.
Konteksty: Niech: D1 = NE-N D2 = N-NW D3 = NW-W W oparciu o parametry T 1, T 2, T 3 (które można dowolnie modyfikować może to robić nawet użytkownik ) określamy wektor kontekstu Q=(Q 1, Q 2, Q 3 ), gdzie Q i {-4, -3, -2, -1, 0, 1, 2, 3, 4} jeśli D i =0 to Q i =0 jeśli D i >0 to Q i =c takie, że T c-1 D i T c jeśli D i <0 to Q i =-c takie, że T c D i -T c-1. Liczba kontekstów = 9 3 =729 Redukcja liczby kontekstów: kontekst (Q 1, Q 2, Q 3 ) z Q 1 <0 zastępujemy przez (-Q 1, -Q 2, -Q 3 ) i ustawiamy SIGN:= -1 (w dalszym etapie do pierwotnej wartości przewidywanej dodajemy błąd predykcji mnożony przez SIGN) Odwzorowanie (Q 1, Q 2, Q 3 ) {1, 2,..., 365} Wiele poziomów rozdzielczości Metoda HINT: X X X X X X X X X X X X Kolejność kodowania: - kodujemy obraz złożony z pikseli - kodujemy obraz złożony z pikseli, korzystając z wartości, stosując predykcję i kodując różnice między wartością predykcji i rzeczywistą - kodujemy kolejno: X, i
Progresywna transmisja obrazu z kompresją schemat hierarchiczny Idea: najpierw przesyłamy wersje obrazu o mniejszej rozdzielczości, następnie o większej; wersje o większej rozdzielczości uzyskujemy z tych o mniejszej rozdzielczości. Metoda oszczędnego przejścia z obrazu o rozdzielczości mxm do rozdzielczości 2m x 2m: - na poziomie m x m jeden piksel reprezentuje średnią arytmetyczną czterech pikseli, do odbiorcy przesyłamy sumę wartości tych 4 pikseli; - przy przejściu do rozdzielczości 2mx2m przesyłamy wartości 3 pikseli, czwarty wyznaczamy jako różnicę między sumą wszystkich pikseli (znaną z poprzedniego poziomu rozdzielczości) i sumą trzech pikseli przesłanych.