Skip to content
Snippets Groups Projects
Commit 044bb615 authored by Vojtech Moravec's avatar Vojtech Moravec
Browse files

Fixed grammer mistakes.

parent 15cb926e
No related branches found
No related tags found
No related merge requests found
No preview for this file type
This diff is collapsed.
......@@ -4,7 +4,7 @@ Námi vytvořený nástroj obsahuje jak enkodér, tak i dekodér. Enkodér se st
Enkodér se stará jak o samotnou kompresi, tak o vytvoření souboru ve speciálním formátu, který jsme nazvali QCMP. Tento binární formát je definován svou hlavičkou a její strukturu můžeme vidět v Tabulce \ref{tab:qcmp_header}. V této hlavičce $I_X$ značí velikost obrazu v dimenzi $X$, neboli šířka obrazu. Podobně $I_Y$ výšku obrazu a $I_Z$ je počet rovin, řezů datasetu. Následující tři hodnoty značí velikosti kvantizačního vektoru při vektorové kvantizaci. Velikosti rovin je pole délky $I_Z$, ve kterém je uložena informace o počtu bytů, potřebných k zakódování jednotlivých rovin.
Za hlavičkou již následují komprimovaná obrazová data. Obě implementované metody jsou slovníkové, neboť vytvářejí slovník určitých hodnot, nebo vektorů. Obraz je pomocí slovníku komprimován. Jejich výstupem je tedy proud indexů, odkazující na slovníkové záznamy. Pro zlepšení kompresního poměru, jsou tyto indexy kódovány pomocí Huffmanových binárních kódů.
Za hlavičkou již následují komprimovaná obrazová data. Obě implementované metody jsou slovníkové, neboť vytvářejí slovník určitých hodnot, nebo vektorů. Obraz je pomocí slovníku komprimován. Jejich výstupem je tedy proud indexů, odkazující na slovníkové záznamy. Pro zlepšení kompresního poměru jsou tyto indexy kódovány pomocí Huffmanových binárních kódů.
\begin{table}[ht!]
\centering
......@@ -32,8 +32,8 @@ Za hlavičkou již následují komprimovaná obrazová data. Obě implementovan
V našem programu podporujeme tzv. globální slovník (viz. typ slovníku v Tabulce \ref{tab:qcmp_header}). Globální slovník je jeden slovník, který je použit pro kompresi všech rovin datasetu. Pokud není zvolena tato možnost, je pro každou rovinu vytvořen vlastní slovník. Slovník pro každou rovinu znamená větší časovou náročnost, jelikož musí být vždy nalezen. Zároveň znamená také větší komprimovaný soubor, neboť všechny slovníky musí být zapsány. Naproti tomu při použití globálního slovníku je komprese rychlejší, neboť dochází pouze k jednomu učení a následné kompresi všech rovin. Výsledky při použití globálního slovníku budou probrány v následujících kapitolách.
Samotný globální slovník se dá vytvořit pomocí dvou způsobů. Kde první, méně náročný, způsob vytvoří slovník pomocí prostřední roviny bioinformatického datasetu. Proč je tento způsob přípustný bude dále vysvětleno v sekci \ref{sec:lossy_compression_data}. Druhou metodou, která je mnohem více univerzální, je vytvoření slovníku ze všech rovin, řezů daného datasetu. Tato technika je více paměťově náročná, neboť se do paměti musí nahrát všechny data rovin. Zároveň je tato metoda velmi vhodná pro superpočítače, které mají tuto paměť a výpočetní výkon k dispozici. Navíc je při této volby hojně využito paralelizace, která celý proces urychluje.
Samotný globální slovník se dá vytvořit pomocí dvou způsobů. Kde první, méně výpočetně náročný způsob, vytvoří slovník pomocí prostřední roviny bioinformatického datasetu. Proč je tento způsob přípustný, bude dále vysvětleno v sekci \ref{sec:lossy_compression_data}. Druhou metodou, která je mnohem více univerzální, je vytvoření slovníku ze všech rovin, řezů daného datasetu. Tato technika je více paměťově náročná, neboť se do paměti musí nahrát všechny data rovin. Zároveň je tato metoda velmi vhodná pro superpočítače, které mají tuto paměť a výpočetní výkon k dispozici. Navíc je při této volby hojně využito paralelizace, která celý proces urychluje.
Program nabízí řadu možností, jak celý proces komprese ovládat. Základní volbou je typ kvantizace, která se má použít a velikost slovníku. Velikost slovníku je zadávána jako mocnina dvojky. Našim cílem jsou slovníky velikostí 4 až 256. Velikost slovníku nepřímo určuje kompresní poměr, kde s menším slovníkem, můžeme očekávat menší soubory, ale také větší chybu v obraze, která vznikne kvantizací. Zároveň větší slovníky sebou přinášejí vyšší paměťovou a časovou náročnost. Při vektorové kvantizaci se také musí zvolit velikost kvantizačního vektoru, který je většinou dvoudimenzionální a můžeme si jej představit jako matici. Další možností je řádkový vektor. Jelikož jsou části našeho programu paralelizovány, tak si také můžeme zvolit počet jader, které chceme využít pro trénování slovníku, které celkově zabírá nejvíc času.
Program nabízí řadu možností, jak celý proces komprese ovládat. Základní volbou je typ kvantizace, která se má použít a velikost slovníku. Velikost slovníku je zadávána jako mocnina dvojky. Našim cílem jsou slovníky velikostí 4 až 256. Velikost slovníku nepřímo určuje kompresní poměr, kde s menším slovníkem můžeme očekávat menší soubory, ale také větší chybu v obraze, která vznikne kvantizací. Zároveň větší slovníky s sebou přinášejí vyšší paměťovou a časovou náročnost. Při vektorové kvantizaci se také musí zvolit velikost kvantizačního vektoru, který je většinou dvoudimenzionální a můžeme si jej představit jako matici. Další možností je řádkový vektor. Jelikož jsou části našeho programu paralelizovány, tak si také můžeme zvolit počet jader, které chceme využít pro trénování slovníku, které celkově zabírá nejvíc času.
Účel dekodéru neboli dekompresoru, je jasný, jeho hlavním úkolem je přečíst komprimovaný proud dat a převést jej na data obrazová. Mimo to umí také prozkoumat komprimovaný soubor a vypsat o něm informace. Dekompresor již nepotřebuje žádné další volby od uživatele, neboť všechny důležité informace jsou uloženy v QCMP hlavičce. Podle hlavičky si vytvoří správný dekompresor, který si již načte slovník Huffmanův strom. Pomocí Huffmanova stromu jsou jednotlivé binární kódy dekódovány na indexy slovníkových záznamů. Slovníkové objekty jsou následně kopírovány do výsledného souboru. Obecně se slovník spolu s informací, jak vybudovat Huffmanův strom, nachází před samotnými daty obrazové roviny. Pokud je použit globální slovník, tak ten je uložen před první rovinu a dále následují pouze obrazová data.
\ No newline at end of file
Účel dekodéru neboli dekompresoru je jasný, jeho hlavním úkolem je přečíst komprimovaný proud dat a převést jej na data obrazová. Mimo to umí také prozkoumat komprimovaný soubor a vypsat o něm informace. Dekompresor již nepotřebuje žádné další volby od uživatele, neboť všechny důležité informace jsou uloženy v QCMP hlavičce. Podle hlavičky si vytvoří správný dekompresor, který si již načte slovník Huffmanův strom. Pomocí Huffmanova stromu jsou jednotlivé binární kódy dekódovány na indexy slovníkových záznamů. Slovníkové objekty jsou následně kopírovány do výsledného souboru. Obecně se slovník, spolu s informací, jak vybudovat Huffmanův strom, nachází před samotnými daty obrazové roviny. Pokud je použit globální slovník, tak ten je uložen před první rovinu a dále následují pouze obrazová data.
\ No newline at end of file
Huffmanovo kódování \cite{huffman1952method} je velmi využívána metoda komprese dat. Tato metoda vytváří pro abecedu symbolů, známých pravděpodobností, nejlepší bitové kódy proměnné délky. Toto kódování může být v kompresním programu využito samostatně, nebo jak je tomu ve většina případů jako další kompresní krok. Později zmíněného využití použijeme v naší aplikaci.
Tento algoritmus přiřazuje nejpravděpodobnějším symbolům nejkratší kódy, a proto je nutné znát pravděpodobnost symbolů abecedy. V ideálním případě, by byly pravděpodobnosti symbolů rovny záporným mocninám dvojky. Huffmanovy kódy jsou tvořeny při budování stromové struktury.
Tento algoritmus přiřazuje nejpravděpodobnějším symbolům nejkratší kódy, a proto je nutné znát pravděpodobnost symbolů abecedy. V ideálním případě by byly pravděpodobnosti symbolů rovny záporným mocninám dvojky. Huffmanovy kódy jsou tvořeny při budování stromové struktury.
Na začátku jsou symboly vstupní abecedy seřazeny sestupně dle jejích pravděpodobností. \linebreak Ze symbolů jsou následně vytvořeny vrcholy stromu, které jsou vloženy do seznamu. Dále jsou ze seznamu odstraněny dva vrcholy s nejmenší pravděpodobností. Pomocí těchto dvou vrcholů vytvoříme nový vrchol, potomka, jehož pravděpodobnost se rovná součtu pravděpodobností dvou odstraněných vrcholů. Potomka vložíme do seznamu. Toto odebírání a slučování probíhá, dokud v seznamu nezůstane pouze jediný vrchol, kořen stromu \cite{davidsalomon2006}. Poté jsou hrany mezi vrcholy ohodnoceny bity 0 a 1. Nakonec postupně projdeme strom od kořene do všech listů, čímž vytvoříme binární kódy symbolů. Příklad budování Huffmanova stromu pro symboly $a_i$ můžeme vidět na Obrázku \ref{fig:huffman_tree}. Na pravé straně obrázku můžeme vidět vytvořené binární kódy.
\image{huffman.pdf}{Huffmanovo kódování}{fig:huffman_tree}{0.7}
Enkodér tedy převádí vstupní symboly na binární kódy, které jsou zapisovaný do komprimovaného proudu dat. Dekodér následně čte z proudu po bitech. Pomocí těchto bitů se posouvá v binárním Huffmanově stromu, dokud nedojde do listu. V listu se nachází samotný symbol. \linebreak Je tedy zřejmé, že dekodér musí být schopen zrekonstruovat stejný Huffmanův strom jako používal enkodér. Z tohoto důvodu, musí být spolu s komprimovanými daty zapsána vedlejší informace, která bude využita pro rekonstrukci Huffmanova stromu. Většinou se jedná buď o četnosti jednotlivých symbolů nebo o samotný strom v binární podobě.
Enkodér tedy převádí vstupní symboly na binární kódy, které jsou zapisovaný do komprimovaného proudu dat. Dekodér následně čte z proudu po bitech. Pomocí těchto bitů se posouvá v binárním Huffmanově stromu, dokud nedojde do listu. V listu se nachází samotný symbol. \linebreak Je tedy zřejmé, že dekodér musí být schopen zrekonstruovat stejný Huffmanův strom jako používal enkodér. Z tohoto důvodu musí být spolu s komprimovanými daty zapsána vedlejší informace, která bude využita pro rekonstrukci Huffmanova stromu. Většinou se jedná buď o četnosti jednotlivých symbolů nebo o samotný strom v binární podobě.
Délka nejdelšího binárního kódu je rovná výšce Huffmanova stromu, který když je vyvážený má velikost $\lceil\log_2 n\rceil$, kde $n$ je velikost abecedy. Nejvyšší možný Huffmanův strom má výšku $n-1$. Příklad nejvyššího stromu můžeme vidět i na Obrázku \ref{fig:huffman_tree}. V každém kroku algoritmu dojde sloučením dvou uzlů ke zvětšení výšky stromu.
\ No newline at end of file
Délka nejdelšího binárního kódu je rovná výšce Huffmanova stromu, který když je vyvážený má velikost $\lceil\log_2 n\rceil$, kde $n$ je velikost abecedy. Nejvyšší možný Huffmanův strom má výšku $n-1$. Příklad nejvyššího stromu můžeme vidět na Obrázku \ref{fig:huffman_tree}. V každém kroku algoritmu dojde sloučením dvou uzlů ke zvětšení výšky stromu.
\ No newline at end of file
Cílem této kapitoly je seznámit čtenáře s výsledky, kterých jsme dosáhli. Provedeme detailní analýzu kompresních výsledků, které jsme získali použitím námi implementovaných algoritmů skalární a vektorové kvantizace. Než se dostaneme k samotným výsledkům uvedeme a popíšeme na jakých bioinformatických datech budeme kompresi zkoušet. U tohoto taky zmíníme společné charakteristiky bioinformatických datasetů. Poté se již dostaneme k našich dvou algoritmů, nejdříve skalární kvantizace a následně vektorová kvantizace. Obě metodu budou nejdříve zkoumány zvlášť a následně je porovnáme jak dohromady, tak i s kompresí JPEG2000.
Cílem této kapitoly je seznámit čtenáře s výsledky, kterých jsme dosáhli. Provedeme detailní analýzu kompresních výsledků, které jsme získali použitím námi implementovaných algoritmů skalární a vektorové kvantizace. Než se dostaneme k samotným výsledkům, uvedeme a popíšeme na jakých bioinformatických datech budeme kompresi zkoušet. Spolu s představením testovaných dat, zmíníme některé společné charakteristiky bioinformatických datasetů. Pak již bude následovat analýza výsledků našich dvou algoritmů, nejdříve skalární kvantizace a následně vektorová kvantizace. Obě tyto metody nejdříve probereme zvlášť a poté je srovnáme mezi sebou i s kompresí JPEG2000.
\subsection{Popis testovaného datasetu}
\label{sec:lossy_compression_data}
......
Kompresi budeme testovat na datasetech získaných pomocí \emph{Light Sheet} mikroskopie. V této metodě fluorescenční mikroskopie je vzorek osvětlován excitačním paprskem, vytvarovaným do plochy a procházející vzorkem kolmo k objektivu mikroskopu. Vždy je osvětlena pouze tenká vrstva vzorku, za vzniku roviny nebo řezu. Mikroskop se vždy po nasnímání jedné roviny posune o určitou vzdálenost a takto nasnímá celý vzorek v několika rovinách. Ze vzorků získaných v jednom časovém bodu, lze poté také vytvořit 3D volumetrický obraz. Seskupení jednotlivých rovin poté nazýváme jako dataset. Samotné snímání se dá provádět taky v čase, díky čehož se mohou vytvářet časosběrná videa vývoje vzorku. V jednom datasetu se proto obvykle nacházejí snímané roviny v několika časových bodech.
Kompresi budeme testovat na datasetech získaných pomocí \emph{Light Sheet} mikroskopie. V této metodě fluorescenční mikroskopie je vzorek osvětlován excitačním paprskem, vytvarovaným do plochy a procházející vzorkem kolmo k objektivu mikroskopu. Vždy je osvětlena pouze tenká vrstva vzorku, za vzniku roviny neboli řezu. Mikroskop se vždy po nasnímání jedné roviny posune o určitou vzdálenost, a takto nasnímá celý vzorek v několika rovinách. Ze vzorků získaných v jednom časovém bodu, lze poté také vytvořit 3D volumetrický obraz. Seskupení jednotlivých rovin nazýváme datasetem. Samotné snímání se dá provádět taky v čase, díky čehož se mohou vytvářet časosběrná videa vývoje vzorku. V jednom datasetu se proto obvykle nacházejí snímané roviny v několika časových bodech.
My máme pro zkoumání k dispozici dva datasety embrya octomilky (\emph{Drosophila}), které byly získány ve stejný časový bod. Buňky embrya jsou geneticky modifikovány a jejich jednotlivé části mají na sobě napojené fluorescenční markery. Tyto markery reagují na různé barvy světla (různé vlnové délky) jinak. Celý vzorek je poté snímám pomocí dvou různých excitačních paprsků, lišících se ve vlnových délkách, za vzniku dvou datasetů. Ukázku z obou datasetů můžeme vidět na Obrázku \ref{fig:dataset_drosophila_embryo}, kde datasety rozlišujeme podle kanálu 0 a 1. Všechny roviny jsou rozměrů $1041 \times 996$ a v obou datasetech je jich celkem 946. Na těchto obrázcích si taky můžeme všimnou markeru mimo vzorky, které slouží k následné rekonstrukci 3D obrazu. Originálně byly tyto datasety uloženy pomocí 32 bitů na pixel, byly proto převedeny na 16 bitů na pixel, bez ztráty na kvalitě.
My máme pro zkoumání k dispozici dva datasety embrya octomilky (\emph{Drosophila}), které byly získány ve stejný časový bod. Buňky embrya jsou geneticky modifikovány a jejich jednotlivé části mají na sobě napojené fluorescenční markery. Tyto markery reagují na různé barvy světla (různé vlnové délky) jinak. Celý vzorek je poté snímám pomocí dvou různých excitačních paprsků, lišících se ve vlnových délkách, za vzniku dvou datasetů. Ukázku z obou datasetů můžeme vidět na Obrázku \ref{fig:dataset_drosophila_embryo}, kde datasety rozlišujeme podle kanálu 0 a 1. Všechny roviny jsou rozměrů $1041 \times 996$ a v obou datasetech je jich celkem 946. Na těchto obrázcích si taky můžeme všimnout markeru mimo vzorky, které slouží k následné rekonstrukci 3D obrazu. Originálně byly tyto datasety uloženy pomocí 32 bitů na pixel. My jsme je pro naše účely převedli na 16 bitů na pixel, bez ztráty na kvalitě.
\begin{figure}[ht!]
\centering
......@@ -20,7 +20,7 @@ My máme pro zkoumání k dispozici dva datasety embrya octomilky (\emph{Drosoph
\label{fig:dataset_drosophila_embryo}
\end{figure}
Dále na grafech v Obrázku \ref{fig:dataset_drosophila_embryo_hist} můžeme vidět rozdělení hodnot pixelů, které odpovídá snímkům z Obrázku \ref{fig:dataset_drosophila_embryo}. U obou kanálu platí, že i když je možný rozsah hodnot velký, tak většina pixelů má hodnotu do 30000. Zároveň se velká část pixelů pohybuje blízko nuly. Toto bude pravda obecně, neboť vzorek je v rovině reprezentován světlejšími pixely, které mají větší hodnoty, kdežto prostředí, ve kterém se vzorek nachází bude zaujímat většinovou část obrazu, které nereaguje na procházející světelný paprsek. Toto okolní prostředí je reprezentováno pixely s malými hodnotami. Informace získané z těchto histogramů nám sdělují, že mnoho pixelů nabývá podobné hodnoty a mělo být schopné vytvořit kvantizační hodnoty, které by dobře reprezentovali komprimovaný obraz.
Dále na grafech v Obrázku \ref{fig:dataset_drosophila_embryo_hist} můžeme vidět rozdělení hodnot pixelů, které odpovídá snímkům z Obrázku \ref{fig:dataset_drosophila_embryo}. U obou kanálů platí, že i když je možný rozsah hodnot velký, tak většina pixelů má hodnotu do 30000. Samotný vzorek je v obrazu reprezentován světlejšími pixely, které mají větší hodnoty a vznikly reakcí na procházející světelný paprsek. Zároveň se velká část pixelů pohybuje blízko nuly. Toto je pravda obecně, neboť většinovou část obrazu zaujímá okolí, prostředí, ve kterém se vzorek nachází. Toto okolí nereaguje na světlo, a proto je tato část obrazu tmavá, reprezentována pixely s malými hodnotami. Informace získané z těchto histogramů nám sdělují, že mnoho pixelů nabývá podobné hodnoty a mělo být možné vytvořit kvantizační objekty, které by dobře reprezentovaly komprimovaný obraz.
\begin{figure}[ht!]
\centering
......@@ -40,7 +40,7 @@ Dále na grafech v Obrázku \ref{fig:dataset_drosophila_embryo_hist} můžeme vi
\label{fig:dataset_drosophila_embryo_hist}
\end{figure}
Pří zmínce o globálním slovníku jsme slíbili, že v této sekci uvedeme vysvětlení, proč je možné využít prostřední roviny jako referenční, pro vytvoření slovníku pro všechny ostatní řezy. Z principu \emph{Light Sheet} mikroskopie víme, že vzorek je snímán po řezech a můžeme tedy předpokládat, že v prostřední rovině bude vzorek přítomen. Toto nemusí, a v našem případě ani není, pravda pro první a poslední snímané roviny. V našem případě se vzorek objevuje až po 180. rovině a znovu mizí někdy po 720. rovině. Přítomnost vzorku v referenčním rovině je velmi důležitá. Pro kvantizační slovník je mnohem důležitější se naučit hodnoty pixelů, které reprezentují vzorek nežli pixely, reprezentující okolí vzorku, které pro nás nenese důležitou informaci. Z tohoto důvodu předpokládáme, že prostřední řez obsahuje vzorek, a naučený slovník bude obsahovat skaláry nebo vektory, které dokážou dobře zrekonstruovat vzorek i v jiných rovinách. Toto by se dalo tvrdit i o jiných rovinách kolem prostřední, ale zrovna u této vybrané přepokládáme největší pravděpodobnost výskytu vzorku.
Pří zmínce o globálním slovníku jsme slíbili, že v této sekci uvedeme vysvětlení, proč je možné využít prostřední roviny jako referenční. Referenční rovina je použita k natrénování slovníku pro všechny ostatní řezy. Z principu \emph{Light Sheet} mikroskopie víme, že vzorek je snímán po řezech a můžeme tedy předpokládat, že v prostřední rovině bude vzorek přítomen. Toto nemusí, a v našem případě ani není, pravda pro první a poslední snímané roviny. V testovaných datasetech se vzorek objevuje až po 180. rovině a znovu mizí někdy po 720. rovině. Přítomnost vzorku v referenčním rovině je velmi důležitá. Pro kvantizační slovník je mnohem důležitější se naučit hodnoty pixelů, které reprezentují vzorek nežli pixely, reprezentující okolí vzorku. Okolí pro nás nenese důležitou informaci. Z tohoto důvodu předpokládáme, že prostřední řez obsahuje vzorek a naučený slovník bude obsahovat skaláry nebo vektory, které dokážou dobře zrekonstruovat vzorek i v jiných rovinách. Toto by se dalo tvrdit i o jiných rovinách kolem prostřední, ale zrovna u této vybrané přepokládáme největší pravděpodobnost výskytu vzorku.
% TODO(Moravec): Plane Entropy
......@@ -2,9 +2,10 @@ Druhou naší metodou, kterou vyzkoušíme na ztrátovou kompresi bioinformatick
Samotný nápad, že komprese sekvence, místo komprese symbolů může vést k lepším výsledkům, byl nejprve představen Claudem Shannonem. Tato myšlenka byla následně potvrzena, když byly postupně kódovány delší a delší sekvence symbolů najednou. Z tohoto vychází, že použitím této metody by mělo dojít k alespoň nějakému zlepšení oproti skalární kvantizaci. \cite{sayoodITDT}
Nejjednodušší algoritmus, by vytvořil slovník všech možných bloků velikosti $N$ a pří kódování by pouze zapisoval index do tohoto slovníku. Tento přístup je velmi neefektivní, neboť velikost slovníku by byla obrovská. Jestliže jeden prvek vektoru zabírá $k$ bitů, pak by velikost slovníku byla $2^{kN}$. Dalším přístupem by bylo přidávat nově objevené vektory z obrazu do slovníku postupně. Problémem tohoto přístupu je postupně rostoucí slovník a s tím i rostoucí velikost indexu v bitech. Z důvodu, že jsou oba tyto přístupy vytvářející slovníky všech možných vektorů vstupního obrazu, nepoužitelné je vektorová kvantizace ztrátová, neboť musíme vytvořit slovník omezené velikosti \cite{davidsalomon2006}. Přístup, který bude využívat dále popsaný algoritmus LBG, je založeny na analýze trénovacích dat, ve kterých se budeme snažit najít $L$, nejuniverzálnějších vektorů, které nejlépe popisují vstupní obraz.
Nejjednodušší algoritmus by vytvořil slovník všech možných bloků velikosti $N$ a pří kódování by pouze zapisoval index do tohoto slovníku. Tento přístup je velmi neefektivní, neboť velikost slovníku by byla obrovská. Jestliže jeden prvek vektoru zabírá $k$ bitů, pak by velikost slovníku byla $2^{kN}$. Dalším přístupem by bylo přidávat nově objevené vektory z obrazu do slovníku postupně. Problémem tohoto přístupu je postupně rostoucí slovník a s tím i rostoucí velikost indexu v bitech. Z důvodu, že jsou oba tyto přístupy vytvářející slovníky všech možných vektorů vstupního obrazu nepoužitelné, je vektorová kvantizace ztrátová, neboť musíme vytvořit slovník omezené velikosti \cite{davidsalomon2006}. Přístup, který bude využívat dále popsaný algoritmus LBG je založeny na analýze trénovacích dat, ve kterých se budeme snažit najít $L$ nejuniverzálnějších vektorů, které nejlépe popisují vstupní obraz.
Po nalezení slovníku je práce kompresoru již jednoduchá. Pro každý vstupní blok pixelů, musí kompresor najít nejpodobnější blok ve slovníku a do komprimovaného proudu dat zapsat jeho index. Velikost indexu je stejně jako u skalární kvantizace $\lceil\log_2 L\rceil$ bitů. Práce dekompresoru je poté velmi jednoduchá a jedná se pouze o vyhledání bloku ve slovníku podle jeho indexu. Navíc oproti skalární kvantizaci nahrazujeme jeden index $N$ hodnotami, takže je dekomprese ještě rychlejší. Podobnost bloku vstupních dat $B$ a slovníkového bloku $C$ měříme pomocí vzdálenosti mezi nimi. Tato vzdálenost je většinou určena jednou z rovnic uvedených v Rovnici \ref{eq:metrics}. První rovnice je Manhattanská metrika, $d_2$ je Euklidovská metrika a $d_3$ hledá největší rozdíl mezi dvojicí komponent dvou měřených vektorů.
Po nalezení slovníku je práce kompresoru již jednoduchá. Pro každý vstupní blok pixelů, musí kompresor najít nejpodobnější blok ve slovníku a do komprimovaného proudu dat zapsat jeho index. Velikost indexu je stejně jako u skalární kvantizace $\lceil\log_2 L\rceil$ bitů. Práce dekompresoru je poté velmi jednoduchá a jedná se pouze o vyhledání bloku ve slovníku podle jeho indexu. Navíc oproti skalární kvantizaci nahrazujeme jeden index $N$ hodnotami, takže je dekomprese ještě rychlejší. Podobnost bloku vstupních dat $B$ a slovníkového bloku $C$ měříme pomocí vzdálenosti mezi nimi. Tato vzdálenost je většinou určena jednou z rovnic uvedených v Rovnici \ref{eq:metrics}.
\begin{equation}
\begin{aligned}
d_1(B,C) &= \sum_{i=0}^{n} |b_i - c_i| \\
......@@ -13,14 +14,13 @@ Po nalezení slovníku je práce kompresoru již jednoduchá. Pro každý vstupn
\end{aligned}
\label{eq:metrics}
\end{equation}
\noindent kde, $d_1$ je Manhattanská metrika, $d_2$ je Euklidovská metrika a $d_3$ hledá největší rozdíl mezi dvojicí komponent dvou měřených vektorů.
V celé této sekci se bavíme o vektoru majícím $N$ prvků. Tyto vektory mohou být z klasických dvoudimenzionálních obrazů vytvořeny pomocí dvou různých způsobů. První základní způsob je vzít postupně blok $N$ pixelů v řadě. Druhým způsobem, který lépe využívá výhod dvoudimenzionálních obrazů, je vzít blok rozměrů $3\times 3$ či $5\times 5$, obecně $X\times Y$. Většinou se volí $X = Y$. Pomocí těchto dvoudimenzionálních bloků, lépe využíváme vlastnost podobnosti sousedních pixelů. Tato myšlenka se dá také využit dále na volumetrická data, kde bychom byli schopni vytvořit krychle rozměrů $X\times Y \times Z$. Samotný algoritmus LBG je nezávislý na této volbě, neboť bloky jsou vždy převedeny na základní vektory, se kterými algoritmus pracuje.
V celé této sekci se bavíme o vektoru majícím $N$ prvků. Tyto vektory mohou být z klasických dvoudimenzionálních obrazů vytvořeny pomocí dvou různých způsobů. První základní způsob je vzít postupně blok $N$ pixelů v řadě. Druhým způsobem, který lépe využívá výhod dvoudimenzionálních obrazů, je vzít blok rozměrů $3\times 3$ či $5\times 5$, obecně $X\times Y$. Většinou se volí $X = Y$. Pomocí těchto dvoudimenzionálních bloků lépe využíváme vlastnost podobnosti sousedních pixelů. Tato myšlenka se dá také využit dále na volumetrická data, kde bychom byli schopni vytvořit krychle rozměrů $X\times Y \times Z$. Samotný algoritmus LBG je nezávislý na této volbě, neboť bloky jsou vždy převedeny na základní vektory, se kterými algoritmus pracuje.
\subsubsection{LBG algoritmus}
\label{sec:lbg_algorithm}
LBG algoritmus, celým jménem Linde--Buzo--Graz \cite{lbg}, je algoritmus, který se snaží najít co nejlepší slovník dané velikosti, a to pomocí adaptace na vstupní trénovací data. Celý tento algoritmus je založen na shlukovacím algoritmu $k$-means. Algoritmus $k$-means dostane na vstupu trénovací vektory, které rozdělí do $k$ shluků. Ve shlucích jsou podobné vektory. V první iteraci je vybráno $k$ náhodných vektorů reprezentující shluky a ostatní vektory jsou přiřazeny k nejbližšímu shluku (měřeno např. pomocí euklidovské vzdálenosti). Následně je v rámci každého shluku vypočítán geometrický střed a příslušnost všech vektoru do shluků je přepočítána. Toto se opakuje, dokud se mění prvky ve shlucích. Je to také podobný přistup, který byl využit v rámci Lloyd--Max algoritmu v kapitole \ref{sec:lloyd_max}.
LBG algoritmus, celým jménem Linde--Buzo--Graz \cite{lbg}, je algoritmus, který se snaží najít co nejlepší slovník dané velikosti, a to pomocí adaptace na vstupní trénovací data. Celý tento algoritmus je založen na shlukovacím algoritmu $k$-means. Algoritmus $k$-means dostane na vstupu trénovací vektory, které rozdělí do $k$ shluků. Ve shlucích jsou podobné vektory. V první iteraci je vybráno $k$ náhodných vektorů, reprezentující shluky. Ostatní vektory jsou přiřazeny k nejbližšímu shluku (měřeno např. pomocí euklidovské vzdálenosti). Následně je v rámci každého shluku vypočítán geometrický střed a příslušnost všech vektorů do shluků je přepočítána. Toto se opakuje, dokud se mění prvky ve shlucích. Je to podobný přistup, který byl využit v rámci Lloyd--Max algoritmu v kapitole \ref{sec:lloyd_max}.
Konkrétní algoritmus LBG si popíšeme pomocí aplikace na kompresi obrazu a budeme vycházet z \cite{davidsalomon2006}. Trénovacími vektory pro nás budou bloky velikosti $N$, které získáme ze vstupního obrazu.
......@@ -29,20 +29,20 @@ Konkrétní algoritmus LBG si popíšeme pomocí aplikace na kompresi obrazu a b
\item Vytvoříme počáteční slovník o velikosti $L$, obsahující vektory délky $N$. Dále si zvolíme minimální hodnotu zlepšení $\epsilon$ a nastavíme hodnotu $D_{0} = \infty$.
\item Trénovací vektory postupně přiřadíme k nejbližšímu slovníkovému vektoru. Vzdálenost je měřena jednou z metrik uvedených v Rovnicích \ref{eq:metrics}. Uskupení slovníkového vektoru \linebreak a trénovacích vektorů budeme nazývat jako shluk.
\item V rámci každého shluku je vypočtena průměrná vzdálenost trénovacích vektorů od slovníkového vektoru. Tyto průměrné vzdálenosti shluků jsou zkombinovány v jednu průměrnou vzdálenost aktuálního slovníku, označovanou jako $D_{i}$, kde $i$ značí iteraci. $D_{i}$ je také označováno jako zkreslení slovníku v dané iteraci.
\item Je provedeno vyhodnocení zda došlo k vylepšení slovníku podle předpisu: $\frac{D_{i-1} - D_i}{D_i} \leq \epsilon$. Jestliže tato podmínka není splněna algoritmus končí.
\item V každém shluku je vypočítán nový geometrický střed, který se stává novým slovníkovým vektorem. Tento geometrický střed je vypočítán jako průměrný vektor ze všech trénovacích vektorů v daném shluku. Po této operaci máme, nový vylepšený slovník, který budeme dále zlepšovat. Pokračujeme prvním krokem.
\item Je provedeno vyhodnocení, zda došlo k vylepšení slovníku podle předpisu: $\frac{D_{i-1} - D_i}{D_i} \leq \epsilon$. Jestliže tato podmínka není splněna, tak algoritmus končí.
\item V každém shluku je vypočítán nový geometrický střed, který se stává novým slovníkovým vektorem. Tento geometrický střed je vypočítán jako průměrný vektor ze všech trénovacích vektorů v daném shluku. Po této operaci máme nový vylepšený slovník, který budeme dále zlepšovat. Pokračujeme prvním krokem.
\end{enumerate}
Pro praktické využití algoritmu je ještě třeba vyřešit pár problémů. Prvním problémem je velká závislost kvality slovníku na počátečním slovníku. Tento algoritmus nijak nezaručuje, že nalezne optimální řešení a volba počátečního slovníku je velmi důležitá. V originálním práci \cite{lbg}, byla navrhnuta technika postupného dělení slovníku na větší slovník. V dané době (1980) byla tato metoda označena za velmi výpočetně náročnou, ale aktuálně jí můžeme bez problému využít. Dělící technika funguje následovně:
\begin{enumerate}
\setcounter{enumi}{-1}
\item Vytvoříme slovník velikosti 1, kde daný vektor je průměrem všech trénovacích vektorů.
\item Každý slovníkový vektor $C$ rozdělíme na dva vektory pomocí perturbačního vektoru $e$, podle $C \pm e$. Po tomto rozdělení budeme mít dvakrát větší slovník. Druhou variantou je přenést všechny staré vektory do nového, většího slovníku a pro každý originální vektor navíc vytvořit druhý pomocí $C + e$.
\item Každý slovníkový vektor $C$ rozdělíme na dva vektory pomocí perturbačního vektoru $e$, podle $C \pm e$. Po tomto rozdělení budeme mít dvakrát větší slovník. Druhou variantou je přenést všechny staré vektory do nového, většího slovníku. Poté jsou ještě všechny tyto přenesené vektory rozděleny pomocí $C + e$.
\item Na aktuální slovník použijeme LBG algoritmus, abychom jej co nejvíce zlepšili.
\item Jestliže máme slovník požadované velikosti tak skončíme, jinak se přesuneme na první krok a pokračujeme s dělením.
\item Jestliže máme slovník požadované velikosti tak algoritmus končí, jinak se přesuneme na první krok a pokračujeme s dělením.
\end{enumerate}
Tato metoda dělení funguje velmi dobře a již nemusíme řešit ruční volbu počátečního slovníku pro algoritmus LBG. Avšak problémem je správná volba perturbačního vektoru $e$. Ručně zvolený $e$ by mohl teoreticky vést k dobrému rozdělení v rámci jednoho vektoru, ale ke špatnému \linebreak u všech ostatních. Proto, jsme se rozhodli použít dynamickou volbu, která byla popsána v \cite{adapteps}. Tato technika tvoří unikátní perturbační vektor pro každý shluk zvlášť. Vektor $e$ je tvořen podle trénovacích vektorů daného shluku, přesněji podle maximálních a minimálních hodnot v různých dimenzích vektorů. Pokud máme vektor $N = 4$, pak dimenzemi myslíme první, druhý až čtvrtý prvek vektoru. Perturbační vektor $e$ je pro každý shluk vytvořen dle Rovnice \ref{eq:adaptive_splitting_e}.
Tato metoda dělení funguje velmi dobře a již nemusíme řešit ruční volbu počátečního slovníku pro algoritmus LBG. Avšak problémem je správná volba perturbačního vektoru $e$. Ručně zvolený $e$ by mohl teoreticky vést k dobrému rozdělení v rámci jednoho vektoru, ale ke špatnému \linebreak u všech ostatních. Proto jsme se rozhodli použít dynamickou volbu, která byla popsána v \cite{adapteps}. Tato technika tvoří unikátní perturbační vektor pro každý shluk zvlášť. Vektor $e$ je tvořen podle trénovacích vektorů daného shluku, přesněji podle maximálních a minimálních hodnot v různých dimenzích vektorů. Pokud máme vektor $N = 4$, pak dimenzemi myslíme první, druhý až čtvrtý prvek vektoru. Perturbační vektor $e$ je pro každý shluk vytvořen dle Rovnice \ref{eq:adaptive_splitting_e}.
\begin{equation}
e = \left( \frac{w_{\text{max}}^1 - w_{\text{min}}^1}{4}, \frac{w_{\text{max}}^2 - w_{\text{min}}^2}{4}, \ldots, \frac{w_{\text{max}}^N - w_{\text{min}}^N}{4} \right)
......@@ -51,6 +51,6 @@ Tato metoda dělení funguje velmi dobře a již nemusíme řešit ruční volbu
\noindent V této rovnici $w_{\text{max}}^i$, resp. $w_{\text{min}}^i$ značí maximální, resp. minimální hodnotu trénovacích vektorů daného shluku v $i$-té dimenzi. Jediným problémem, který může nastat je prázdný shluk, kde žádný trénovací vektor nepřísluší vektoru slovníkovému. Pro tento shluk je $e$ vytvořen náhodně.
Druhým problémem u samotného LBG algoritmu, je vznik tzv. prázdného slovníkového vektoru. Tomuto vektoru nepřísluší žádné trénovací vektory a je tedy ve slovníku navíc. Prázdný shluk zabírá místo pro jiný vektor, který by mohl pomoci vytvořit optimální slovník. Řešením tohoto problému je smazat tento prázdný vektor ze slovníku a nahradit jej. Jako náhradní vektor je zvolen náhodný trénovací vektor z největšího shluku (největší počet trénovacích vektorů). Trénovací data největšího shluku jsou následně rozdělena mezi tyto dva vektory. Na diagramu v Obrázku \ref{fig:lbg_splitting} můžeme vizuálně pozorovat, jak fungují oba algoritmy, LBG i postupné dělení slovníku.
Druhým problémem u samotného LBG algoritmu je vznik tzv. prázdného slovníkového vektoru. Tomuto vektoru nepřísluší žádné trénovací vektory a je tedy ve slovníku navíc. Prázdný shluk zabírá místo pro jiný vektor, který by mohl pomoci vytvořit optimální slovník. Řešením tohoto problému je smazat tento prázdný vektor ze slovníku a nahradit jej. Jako náhradní vektor je zvolen náhodný trénovací vektor z největšího shluku (největší počet trénovacích vektorů). Trénovací data největšího shluku jsou následně rozdělena mezi tyto dva vektory. Na diagramu v Obrázku \ref{fig:lbg_splitting} můžeme vizuálně pozorovat, jak fungují oba algoritmy, LBG i postupné dělení slovníku.
\image{LBG.pdf}{Diagram LBG algoritmu}{fig:lbg_splitting}{0.7}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment