1 co je podstatou procesu komprese informací. Koncept komprese dat

ARCHIVACE

Komprese informací Je proces transformace informací uložených v souboru snížením redundance dat. Účelem tohoto procesu je snížit množství zabraných dat.

Archivní soubor Je speciálně vytvořený soubor obsahující jeden nebo více komprimovaných souborů.

Kompresní poměr: Kc = Vc / V o * 100 %

K c- kompresní poměr, V c- objem komprimovaný soubor, V o- původní velikost souboru.

Kompresní poměr závisí na:

1) použitý program - archivátor,

2) kompresní metoda,

3) typ zdrojového souboru: text, grafika, video, zvuk atd.

Programy, které balí a rozbalují soubory, se nazývají archivátory. Nejběžnější jsou: ARJ, ZIP, RAR. Přípona archivních souborů se shoduje s názvem archivátoru použitého k jejich vytvoření.

Archivátory umožňují vytvářet samorozbalovací archivní soubory, tzn. k jejich rozbalení není nutné spouštět archivační program, protože samy obsahují rozbalovací program. Tyto archivy se nazývají archivy SFX
(Sebeextrahování). Přípona těchto souborů je * .EXE.


Principy komprese informací

V libovolném textu jsou opakující se znaky. Je možné určit jeden znak a počet opakování. Efektivita tohoto algoritmu je ještě vyšší při aplikaci na grafické soubory. Když se podíváte na monitor, můžete vidět spoustu opakujících se bodů stejné barvy. Formát je založen na tomto principu komprese informací. grafické soubory PCX. Moderní archivátory rozlišují nejen opakující se symboly, ale také řetězce symbolů, jednotlivá slova.

Pokud text nepoužívá všechny znaky PC abecedy, pak k jejich zakódování můžete místo jednoho bajtu použít 8 bitů, méně čísla. Tento princip se používá v telegrafním aparátu, kde se používají pouze Rusové. velká písmena, k jejich reprezentaci stačí 5 bitů, což umožňuje zapsat tři znaky ve dvou bytech.

3. Následující princip využívá pravidelnosti, že písmena v textu se vyskytují s různou frekvencí. Například v tomto textu je nejběžnějším znakem mezera, velmi často se vyskytují symboly "a", "a". Tyto společné symboly mohou být reprezentovány krátkou kombinací bitů, zbytek symbolů může být kódován delší sekvencí. Například:

4. Fyzicky PC alokuje místo pro umístění souborů na disku v clusterech - po 4 KB blocích. Méně vyzdvihnout nelze. Pokud má soubor například 8193 bajtů (8 kB a 1 bajt), fyzicky to bude 16 kB nebo 16384 bajtů. Sloučení skupiny souborů do jednoho vám umožní ušetřit na těchto zbytcích. Při balení malých souborů jde o velkou úsporu.

Celkově se při samostatném umístění souborů nevyužije 6 KB, což je 100 % obsahu souborů. Ve druhém případě zůstávají nevyužity 2 KB, 33 %.


Archivátor zipů

Balení souborů pkzip [klíče]<имя архива>[cesty k souboru]

Klíče: -rp archivace s podadresáři se zachováním struktury

S OZP ochrana archivu heslem (PWD)

A přidat soubory do archivu

M přesunout soubory do archivu

V zobrazit obsah archivu

Pokud se archivují všechny soubory v adresáři, nezapomeňte zadat masku *.*

Rozbalení souborů pkunzip [klíče]<имя архива>[názvy souborů]

Přepínače: -d rozbalení s podadresáři se zachováním struktury

Heslo archivu SPWD (PWD)


Archivátor Arj

arj<команда>[klávesy]<имя архива>[názvy souborů]

U archivátoru arj jeden soubor provádí operace rozbalení i sbalení.

příkazy: A archivace

e rozbalení bez zachování struktury adresářů

X vybalení se zachováním struktury

Zobrazuji obsah archivu

m přesunout soubory do archivu

d odstranit soubory z archivu

Přepínače: -r sbalení s podadresáři se zachováním struktury

V rozdělení archivu na svazky s objemem svazku (pokud je zadán)

velikost standardních disket (360, 720, 1200, 1440) je uvedena v kilobajtech, velikost nestandardních disket je uvedena v bajtech

V je indikováno při rozbalování vícesvazkového archivu

G OZP archivní heslo ( OZP)

ZIP soubory

Rozbalování souborů

© 2015-2019 web
Všechna práva náleží jejich autorům. Tato stránka si nečiní nárok na autorství, ale poskytuje bezplatné použití.
Datum vytvoření stránky: 2016-08-08

V dnešní době mnoho uživatelů přemýšlí o tom, jak probíhá proces komprimace informací, aby se ušetřilo volné místo na pevném disku, protože je to jeden z nejúčinnějších způsobů využití využitelného místa na jakémkoli disku. Moderní uživatelé, kteří se potýkají s nedostatkem volného místa na disku, musí poměrně často mazat všechna data, aby uvolnili potřebné místo, zatímco pokročilejší uživatelé nejčastěji používají kompresi dat, aby snížili jejich objem.

Mnozí však ani nevědí, jak se proces komprese informací nazývá, nemluvě o tom, jaké algoritmy se používají a co aplikace každého z nich dává.

Měli byste komprimovat data?

Komprese dat je dnes poměrně důležitá a je nezbytná pro každého uživatele. Samozřejmě, že v naší době si téměř každý může koupit pokročilá zařízení pro ukládání dat, která poskytují možnost využívat dostatečně velké množství volného místa a jsou také vybavena vysokorychlostními kanály vysílání informací.

V tomto případě však musíte správně pochopit, že v průběhu času se také zvyšuje množství dat, která je třeba přenést. A jestliže doslova před deseti lety byl objem 700 MB považován za standard pro běžný film, dnes mohou mít filmy natočené v HD kvalitě objem i několik desítek gigabajtů, nemluvě o tom, kolik volného místa zabírají kvalitní filmy. ve formátu Blu-ray.

Kdy je nutná komprese dat?

Samozřejmě byste neměli očekávat, že proces komprese informací vám přinese mnoho výhod, ale existuje řada situací, ve kterých jsou některé metody komprese informací mimořádně užitečné a dokonce nezbytné:

  • Přenos určitých dokumentů e-mailem. To platí zejména pro situace, kdy potřebujete přenášet informace ve velkých objemech pomocí různých mobilních zařízení.
  • Proces komprimace informací za účelem zmenšení prostoru, který zabírají, se často používá při publikování určitých dat na různých webech, když je nutné ušetřit provoz;
  • Ušetřete volné místo na pevném disku, když neexistuje způsob, jak vyměnit nebo přidat nové úložné médium. Nejběžnější je zejména situace, kdy existují určitá omezení dostupného rozpočtu, ale na disku není dostatek volného místa.

Samozřejmě, kromě výše uvedeného stále existuje velké množství různých situací, ve kterých může být proces komprimace informací vyžadován za účelem snížení jejich objemu, ale tyto jsou zdaleka nejběžnější.

Jak lze komprimovat data?

Dnes existuje široká škála metod pro kompresi informací, ale všechny se dělí do dvou hlavních skupin – jde o kompresi s určitými ztrátami a také kompresi beze ztrát.

Použití poslední skupiny metod je relevantní, když musí být data obnovena s extrémně vysokou přesností, až na jeden bit. Tento přístup je jediný relevantní v případě, že je určitý textový dokument komprimován.

Zároveň stojí za zmínku skutečnost, že v některých situacích není potřeba co nejpřesnější obnova komprimovaných dat, proto je možné použít takové algoritmy, ve kterých jsou informace na disku komprimovány s určitými ztrátami. Výhodou ztrátové komprese je, že tato technologie je mnohem jednodušší na implementaci a také poskytuje nejvyšší možnou míru archivace.

Ztrátová komprese

Ztrátové informace poskytují řádově lepší kompresi při zachování dostatečné kvality informací. Ve většině případů se použití takových algoritmů provádí pro kompresi analogových dat, jako jsou všechny druhy obrázků nebo zvuků. V takových situacích se mohou rozbalené soubory značně lišit od původních informací, ale jsou prakticky k nerozeznání od lidského oka nebo ucha.

Bezeztrátová komprese

Algoritmy bezztrátové komprese poskytují nejpřesnější obnovu dat a eliminují jakoukoli ztrátu komprimovaných souborů. V tomto případě je však nutné správně pochopit skutečnost, že v v tomto případě komprese souborů není tak efektivní.

Generické metody

Mimo jiné existuje určitý počet univerzálních metod, kterými se provádí efektivní proces komprimace informací, aby se zmenšil prostor, který zabírají. Obecně existují pouze tři hlavní technologie:

  • Transformace proudu. V tomto případě je popis nových příchozích nekomprimovaných informací prováděn prostřednictvím již zpracovaných souborů, přičemž se nepočítají žádné pravděpodobnosti, ale znaky jsou kódovány pouze na základě těch souborů, které již prošly určitým zpracováním.
  • Statistická komprese. Tento proces komprese informací za účelem zmenšení místa, které zabírá na disku, se dělí na dvě podkategorie – adaptivní a blokové metody. Adaptivní verze umožňuje výpočet pravděpodobností pro nové soubory na základě informací, které již byly zpracovány během procesu kódování. Zejména by tyto metody měly zahrnovat také různé adaptivní varianty algoritmů Shannon-Fano a Huffman. Blokový algoritmus umožňuje samostatný výpočet každého bloku informací s následným přidáním do nejvíce komprimovaného bloku.
  • Bloková transformace. Příchozí informace jsou rozděleny do několika bloků a následně dochází k holistické transformaci. Je třeba říci, že určité metody, zejména ty založené na permutaci několika bloků, mohou v konečném důsledku vést k výraznému snížení množství komprimovatelné informace. Je však třeba správně chápat, že po takovém zpracování nakonec dojde k výraznému zlepšení, v jehož důsledku je následná komprese jinými algoritmy mnohem jednodušší a rychlejší.

Komprese kopírování

Jedna z nejdůležitějších součástí Rezervovat kopii je zařízení, do kterého se má přesunout potřebuje uživatel informace. Čím více dat přesunete, tím objemnější zařízení budete muset používat. Pokud se však chystáte provést proces komprese dat, pak je nepravděpodobné, že v tomto případě pro vás problém nedostatku volného místa zůstane relevantní.

Proč je to potřeba?

Schopnost komprimovat informace a zároveň výrazně zkrátit čas potřebný pro kopírování požadované soubory a zároveň dosáhnout efektivní úspory volného místa na disku. Jinými slovy, při použití komprese se informace budou kopírovat mnohem kompaktněji a rychleji a můžete ušetřit své peníze a finance, které byly nutné k nákupu většího disku. Kromě jiného komprimací informací také zkrátíte čas, který bude potřeba při přenosu všech dat na server nebo jejich kopírování přes síť.

Komprimaci dat pro zálohování lze provést do jednoho nebo několika souborů - v tomto případě bude vše záviset na tom, jaký program používáte a jaké informace komprimujete.

Při výběru obslužného programu se nezapomeňte podívat na to, jak moc dokáže vámi vybraný program komprimovat data. Záleží na typu informace, v důsledku čehož je účinnost komprese textové dokumenty může být více než 90 %, zatímco účinnost nebude vyšší než 5 %.

Dobrý den.
Dnes se chci dotknout tématu bezztrátové komprese dat. Navzdory tomu, že o Habrém již byly články věnované některým algoritmům, chtěl jsem o tom pohovořit trochu podrobněji.
Pokusím se podat jak matematický popis, tak popis v obvyklé formě, aby si každý našel něco zajímavého pro sebe.

V tomto článku se dotknu základů komprese a hlavních typů algoritmů.

Komprese. Je to v naší době nutné?

Samozřejmě ano. Všichni samozřejmě chápeme, že nyní máme přístup jak k velkoobjemovým paměťovým médiím, tak k vysokorychlostním kanálům přenosu dat. Zároveň však rostou objemy přenášených informací. Jestliže jsme před pár lety sledovali 700megabajtové filmy, které se vešly na jeden disk, dnes mohou filmy v HD kvalitě zabrat desítky gigabajtů.
Komprese všeho a všech samozřejmě nemá velký přínos. Stále však existují situace, ve kterých je komprese mimořádně užitečná, ne-li nezbytná.

  • Odesílání dokumentů prostřednictvím e-mailem(zejména velké objemy dokumentů pomocí mobilních zařízení)
  • Při publikování dokumentů na webech nutnost šetřit provoz
  • Úspora místa na disku při výměně nebo přidání úložiště je obtížné. Stává se to například v případech, kdy není snadné vyřadit rozpočet na kapitálové výdaje a na disku není dostatek místa.

Samozřejmě si můžete vymyslet mnohem více situací, ve kterých se bude komprese hodit, ale nám stačí těchto pár příkladů.

Všechny kompresní metody lze rozdělit do dvou širokých skupin: ztrátová komprese a bezeztrátová komprese. Bezeztrátová komprese se používá, když je potřeba obnovit informace s bitovou přesností. Tento přístup je jediný možný při komprimaci např. textových dat.
V některých případech však není vyžadována přesná obnova informací a jsou povoleny algoritmy, které implementují ztrátovou kompresi, která je na rozdíl od bezztrátové komprese obvykle snadněji implementovatelná a poskytuje vyšší stupeň archivace.

Pojďme tedy k úvahám o bezeztrátových kompresních algoritmech.

Všestranné bezeztrátové kompresní metody

Obecně existují tři základní možnosti, na kterých jsou kompresní algoritmy postaveny.
První skupina metody - transformace proudu. To předpokládá popis nově příchozích nekomprimovaných dat přes již zpracovaná. V tomto případě se nepočítají žádné pravděpodobnosti, kódování znaků se provádí pouze na základě dat, která již byla zpracována, jako například u metod LZ (pojmenovaných po Abrahamu Lempelovi a Jacobu Zivovi). V tomto případě jsou druhý a další výskyty určitého dílčího řetězce již známého kodéru nahrazeny odkazy na jeho první výskyt.

Druhá skupina Metody jsou statistické kompresní metody. Tyto metody se dále dělí na adaptivní (neboli tokové) a blokové.
V první (adaptivní) verzi se pravděpodobnosti pro nová data počítají pomocí dat, která již byla zpracována během kódování. Tyto metody zahrnují adaptivní varianty algoritmu Huffman a Shannon-Fano.
Ve druhém (blokovém) případě se statistika každého datového bloku vypočítá samostatně a přidá se k nejvíce komprimovanému bloku. Patří mezi ně statické verze metod Huffman, Shannon-Fano a aritmetické kódování.

Třetí skupina Metody jsou tzv. blokové převodní metody. Příchozí data jsou rozdělena do bloků, které jsou následně transformovány jako celek. Některé metody, zejména ty založené na blokové permutaci, přitom nemusí vést k výraznému (nebo dokonce žádnému) snížení objemu dat. Po takovém zpracování se však datová struktura výrazně zlepší a následná komprese jinými algoritmy je úspěšnější a rychlejší.

Obecné principy, na kterých je založena komprese dat

Všechny metody komprese dat jsou založeny na jednoduchém logickém principu. Pokud si představíme, že nejběžnější prvky jsou zakódovány kratšími kódy a méně běžné delšími kódy, pak bude pro uložení všech dat potřeba méně místa, než kdyby byly všechny prvky reprezentovány kódy stejné délky.
Přesný vztah mezi frekvencemi prvků a optimálními délkami kódu je popsán v tzv. Shannonově větě o zdrojovém kódování, která definuje maximální limit bezztrátové komprese a Shannonovu entropii.

Trochu matematiky
Pokud je pravděpodobnost výskytu prvku s i rovna p (s i), pak bude nejvýhodnější tento prvek reprezentovat - log 2 p (s i) v bitech. Pokud je při kódování možné dosáhnout toho, že délka všech prvků bude zkrácena na log 2 p(si) bitů, pak bude délka celé kódované sekvence minimální pro všechny možné způsoby kódování. Navíc, pokud se rozdělení pravděpodobnosti všech prvků F = (p (s i)) nemění a pravděpodobnosti prvků jsou vzájemně nezávislé, pak lze průměrnou délku kódů vypočítat jako

Tato hodnota se nazývá entropie rozdělení pravděpodobnosti F neboli entropie zdroje v čase tento momentčas.
Obvykle však pravděpodobnost výskytu prvku nemůže být nezávislá, naopak závisí na některých faktorech. V tomto případě pro každý nový kódovaný prvek si bude mít rozdělení pravděpodobnosti F nějakou hodnotu Fk, to znamená pro každý prvek F = Fk a H = Hk.

Jinými slovy, můžeme říci, že zdroj je ve stavu k, což odpovídá určité množině pravděpodobností p k (s i) pro všechny prvky s i.

S přihlédnutím k této novele tedy můžeme průměrnou délku kódů vyjádřit jako

Kde P k je pravděpodobnost nalezení zdroje ve stavu k.

V této fázi tedy víme, že komprese je založena na nahrazení často se vyskytujících prvků krátkými kódy a naopak a také víme, jak určit průměrnou délku kódů. Ale co je kód, kódování a jak k němu dochází?

Bezpamětové kódování

Bezpamětové kódy jsou nejjednodušší kódy, na jejichž základě lze provádět kompresi dat. V kódu out-of-memory je každý znak v zakódovaném datovém vektoru nahrazen znakem kódové slovo z předponové sady binárních sekvencí nebo slov.
Podle mého názoru to není nejsrozumitelnější definice. Podívejme se na toto téma trochu podrobněji.

Nechte si dát nějakou abecedu , skládající se z určitého (konečného) počtu písmen. Nazvěme každou konečnou posloupnost znaků z této abecedy (A = a 1, a 2, ..., a n) slovo a číslo n je délka tohoto slova.

Nechť je také dána jiná abeceda ... Podobně označme slovo v této abecedě jako B.

Uveďme ještě dva zápisy pro množinu všech neprázdných slov v abecedě. Nechť je počet neprázdných slov v první abecedě a - ve druhé.

Nechť je dáno také zobrazení F, které každému slovu A z první abecedy přiřadí nějaké slovo B = F (A) z druhé abecedy. Potom se bude nazývat slovo B kód slovo A a bude zavolán přechod z původního slova do jeho kódu kódování.

Protože slovo může sestávat také z jednoho písmene, můžeme identifikovat shodu mezi písmeny první abecedy a odpovídajícími slovy z druhé:
1<->B 1
a 2<->B 2

a n<->B n

Tato korespondence se nazývá systém, a jsou označeny ∑.
V tomto případě slova B 1, B 2, ..., B n volají elementární kódy a typ kódování s jejich pomocí je abecední kódování... Samozřejmě, že většina z nás se setkala s tímto druhem kódování, a to i bez znalosti všeho, co jsem popsal výše.

Definovali jsme tedy pojmy abeceda, slovo, kód, a kódování... Nyní představíme koncept předpona.

Slovo B nechť má tvar B = B "B" ". Pak se B" nazývá začátek, popř předpona slovo B a B "" je jeho konec. Toto je poměrně jednoduchá definice, ale je třeba poznamenat, že pro jakékoli slovo B lze jak určité prázdné slovo ʌ ("mezera"), tak slovo B samotné považovat za začátek i konec.

Takže jsme blízko k pochopení definice kódů bez paměti. Poslední definicí, kterou musíme pochopit, je sada předpon. Schéma ∑ má prefixovou vlastnost, pokud pro jakékoli 1≤i, j≤r, i ≠ j slovo B i není předponou slova Bj.
Jednoduše řečeno, množina prefixů je konečná množina, ve které žádný prvek není prefixem (nebo začátkem) jakéhokoli jiného prvku. Jednoduchý příklad takovou množinou je například obyčejná abeceda.

Takže jsme přišli na základní definice. Jak tedy probíhá skutečné kódování bez paměti?
Probíhá ve třech etapách.

  1. Sestaví se abeceda symbolů Ψ původní zprávy a abecední symboly se seřadí v sestupném pořadí podle pravděpodobnosti jejich výskytu ve zprávě.
  2. Každý symbol a i z abecedy Ψ je spojen s určitým slovem B i z předponové množiny Ω.
  3. Každý znak je zakódován, následuje spojení kódů do jednoho datového toku, který bude výsledkem komprese.

Jedním z kanonických algoritmů, který ilustruje tuto metodu, je Huffmanův algoritmus.

Huffmanův algoritmus

Huffmanův algoritmus využívá frekvenci výskytu stejných bajtů ve vstupním datovém bloku a často se vyskytující bloky přiřazuje kratším bitovým řetězcům a naopak. Tento kód je minimálně nadbytečný. Uvažujme případ, kdy bez ohledu na vstupní proud se abeceda výstupního proudu skládá pouze ze 2 znaků - nula a jedna.

Nejprve musíme při kódování pomocí Huffmanova algoritmu sestavit obvod ∑. To se provádí následovně:

  1. Všechna písmena vstupní abecedy jsou seřazeny v sestupném pořadí pravděpodobností. Všechna slova z abecedy výstupního proudu (tedy to, co budeme kódovat) jsou zpočátku považována za prázdná (připomeňme, že abeceda výstupního proudu se skládá pouze ze znaků (0,1)).
  2. Dva symboly a j-1 a a j vstupního toku, které mají nejnižší pravděpodobnost výskytu, jsou sloučeny do jednoho „pseudosymbolu“ s pravděpodobností p rovna součtu pravděpodobností symbolů v něm obsažených. Poté přidáme 0 na začátek slova B j-1 a 1 na začátek slova B j, což budou následně kódy znaků a j-1 a a j.
  3. Tyto symboly odstraníme z abecedy původní zprávy, ale do této abecedy přidáme vygenerovaný pseudosymbol (přirozeně musí být do abecedy vložen na správné místo s přihlédnutím k jeho pravděpodobnosti).
Kroky 2 a 3 se opakují, dokud v abecedě nezůstane pouze 1 pseudoznak obsahující všechny původní znaky abecedy. V tomto případě, protože v každém kroku a pro každý znak se odpovídající slovo B i změní (přidáním jedničky nebo nuly), pak po dokončení tohoto postupu bude každému počátečnímu symbolu abecedy a odpovídat určitý kód B i i.

Pro lepší ilustraci zvažte malý příklad.
Předpokládejme, že máme abecedu složenou pouze ze čtyř znaků - (a 1, a 2, a 3, a 4). Předpokládejme také, že pravděpodobnosti výskytu těchto symbolů jsou p 1 = 0,5; p2 = 0,24; p3 = 0,15; p 4 = 0,11 (součet všech pravděpodobností je evidentně roven jedné).

Pojďme tedy vytvořit schéma pro danou abecedu.

  1. Spojíme dva znaky s nejnižší pravděpodobností (0,11 a 0,15) do pseudoznaku p ".
  2. Spojte dva znaky s nejnižší pravděpodobností (0,24 a 0,26) do pseudoznaku p "".
  3. Odstraňte zřetězené znaky a vložte výsledný pseudoznak do abecedy.
  4. Nakonec zkombinujeme zbývající dva symboly, abychom dostali vrchol stromu.

Pokud uděláte ilustraci tohoto procesu, dostanete něco takového:


Jak vidíte, při každém sloučení přiřadíme sloučeným znakům kódy 0 a 1.
Tímto způsobem, když je strom postaven, můžeme snadno získat kód pro každý znak. V našem případě budou kódy vypadat takto:

A 1 = 0
a 2 = 11
a 3 = 100
a 4 = 101

Protože žádný z těchto kódů není prefixem žádného jiného (to znamená, že máme notoricky známou sadu prefixů), můžeme jednoznačně identifikovat každý kód ve výstupním proudu.
Dosáhli jsme tedy toho, že nejčastější znak je zakódován nejkratším kódem a naopak.
Pokud předpokládáme, že zpočátku byl pro uložení každého znaku použit jeden bajt, pak můžeme vypočítat, jak moc se nám podařilo zredukovat data.

Předpokládejme, že na vstupu jsme měli řetězec 1000 znaků, ve kterém se znak a 1 vyskytl 500krát, a 2 - 240, a 3 - 150 a 4 - 110krát.

Zpočátku daný řetězec obsazeno 8000 bitů. Po zakódování získáme řetězec délky ∑p i l i = 500 * 1 + 240 * 2 + 150 * 3 + 110 * 3 = 1760 bitů. Podařilo se nám tedy zkomprimovat data faktorem 4,54, přičemž na zakódování každého znaku streamu bylo vynaloženo v průměru 1,76 bitu.

Připomínám, že podle Shannona je průměrná délka kódů. Dosazením našich pravděpodobností do této rovnice dostaneme průměrnou délku kódu rovnou 1,75496602732291, což je velmi, velmi blízko našemu výsledku.
Je však třeba mít na paměti, že kromě samotných dat musíme uložit i kódovací tabulku, čímž se výsledná velikost kódovaných dat mírně zvětší. Je zřejmé, že v různých případech lze použít různé varianty algoritmu - například někdy je efektivnější použít předem stanovenou tabulku pravděpodobností a někdy je nutné ji sestavit dynamicky, procházením komprimovaných dat.

Závěr

V tomto článku jsem se tedy pokusil o tom mluvit obecné zásady, kterým dochází k bezeztrátové kompresi, a také považován za jeden z kanonických algoritmů - Huffmanovo kódování.
Pokud se článek líbí komunitě habro, pak rád napíšu pokračování, protože s bezztrátovou kompresí je stále mnoho zajímavých věcí; jsou to jak klasické algoritmy, tak předběžné transformace dat (např. Burrows-Wheelerova transformace), tak samozřejmě specifické algoritmy pro kompresi zvuku, videa a obrázků (podle mě nejzajímavější téma).

Literatura

  • Vatolin D., Ratushnyak A., Smirnov M., Yukin V. Metody komprese dat. Zařízení archivátorů, komprese obrázků a videí; ISBN 5-86404-170-X; 2003 r.
  • D. Salomon. Komprese dat, obrazu a zvuku; ISBN 5-94836-027-X; 2004

GORKOFF 24. února 2015 v 11:41

Metody komprese dat

  • Algoritmy

S mým vědeckým poradcem připravujeme malou monografii o zpracování obrazu. Rozhodl jsem se předložit kapitolu o algoritmech komprese obrazu k posouzení HabraSociety. Protože je těžké vměstnat celou kapitolu do jednoho příspěvku, rozhodl jsem se ji rozdělit do tří příspěvků:
1. Metody komprese dat;
2. Bezztrátová komprese obrázků;
3. Komprese obrazů se ztrátou.
Níže si můžete přečíst první příspěvek ze série.

V současné době existuje velké množství bezeztrátových kompresních algoritmů, které lze podmíněně rozdělit do dvou velkých skupin:
1. Streamové a slovníkové algoritmy. Tato skupina zahrnuje algoritmy rodin RLE (run-length encoding), LZ * atd. Charakteristickým rysem všech algoritmů této skupiny je, že kódování nepoužívá informace o frekvencích znaků ve zprávě, ale informace o sekvencích se kterými se setkali dříve.
2. Algoritmy pro statistickou (entropickou) kompresi. Tato skupina algoritmů komprimuje informace pomocí nerovnoměrnosti frekvencí, se kterými se ve zprávě vyskytují různé znaky. Algoritmy v této skupině zahrnují aritmetické a prefixové kódovací algoritmy (používající Shannon-Fanno, Huffman, secant stromy).
Algoritmy transformace informací lze rozdělit do samostatné skupiny. Algoritmy této skupiny informace přímo nekomprimují, ale jejich aplikace značně zjednodušuje další kompresi pomocí proudových, slovníkových a entropických algoritmů.

Streamovací a slovníkové algoritmy

Kódování délky běhu

Run-Length Encoding (RLE) je jedním z nejjednodušších a nejběžnějších algoritmů komprese dat. V tomto algoritmu je sekvence opakovaných znaků nahrazena znakem a počtem opakování.
Například řetězec "AAAAA", který vyžaduje 5 bajtů k uložení (za předpokladu, že je bajt alokován pro uložení jednoho znaku), lze nahradit řetězcem "5A", který se skládá ze dvou bajtů. Je zřejmé, že čím delší je série opakování, tím efektivnější je tento algoritmus.

Hlavní nevýhodou tohoto algoritmu je extrémně nízká účinnost na sekvence neopakujících se znaků. Pokud například vezmeme v úvahu sekvenci „ABABAB“ (6 bajtů), pak se po použití algoritmu RLE změní na „1A1B1A1B1A1B“ (12 bajtů). Existují různé metody, jak se s problémem neopakujících se znaků vypořádat.

Nejjednodušší metodou je následující úprava: bajt kódující počet opakování musí uchovávat informace nejen o počtu opakování, ale také o jejich přítomnosti. Pokud je první bit 1, pak dalších 7 bitů označuje počet opakování odpovídajícího znaku a pokud je první bit 0, pak dalších 7 bitů označuje počet znaků, které je třeba vzít bez opakování. Pokud zakódujete "ABABAB" pomocí této modifikace, dostaneme "-6ABABAB" (7 bajtů). Je zřejmé, že navrhovaná technika může výrazně zlepšit účinnost algoritmu RLE na neopakujících se sekvencích znaků. Implementace navrhovaného přístupu je uvedena ve výpisu 1:

  1. typ
  2. funkce RLEEncode (InMsg: ShortString): TRLEEncodedString;
  3. MatchFl: boolean;
  4. MatchCount: shortint;
  5. EncodedString: TRLEEncodedString;
  6. N, i: byte;
  7. začít
  8. N: = 0;
  9. SetLength (EncodedString, 2 * délka (InMsg));
  10. zatímco délka (InMsg)> = 1 do
  11. začít
  12. MatchFl: = (délka (InMsg)> 1) a (InMsg [1] = InMsg [2]);
  13. Počet shod: = 1;
  14. zatímco (MatchCount<= 126 ) and (MatchCount < length(InMsg) ) and ((InMsg[ MatchCount] = InMsg[ MatchCount + 1 ] ) = MatchFl) do
  15. MatchCount: = MatchCount + 1;
  16. pokud MatchFl pak
  17. začít
  18. N: = N + 2;
  19. EncodedString [N - 2]: = MatchCount + 128;
  20. EncodedString [N - 1]: = ord (InMsg [1]);
  21. jiný
  22. začít
  23. pokud MatchCount<>délka (InMsg).
  24. MatchCount: = MatchCount - 1;
  25. N: = N + 1 + MatchCount;
  26. EncodedString [N - 1 - MatchCount]: = - MatchCount + 128;
  27. for i: = 1 to MatchCount udělat
  28. EncodedString [N - 1 - MatchCount + i]: = ord (InMsg [i]);
  29. konec;
  30. smazat (InMsg, 1, MatchCount);
  31. konec;
  32. SetLength (EncodedString, N);
  33. RLEEncode: = EncodedString;
  34. konec;

Dekódování komprimované zprávy je velmi jednoduché a scvrkává se na jediný průchod komprimovanou zprávou, viz Výpis 2:
  1. typ
  2. TRLEEncodedString = pole bajtů;
  3. funkce RLEDecode (InMsg: TRLEEncodedString): ShortString;
  4. RepeatCount: shortint;
  5. i, j: slovo;
  6. OutMsg: ShortString;
  7. začít
  8. OutMsg: = "";
  9. i: = 0;
  10. zatímco já< length(InMsg) do
  11. začít
  12. RepeatCount: = InMsg [i] - 128;
  13. i: = i + 1;
  14. pokud RepeatCount< 0 then
  15. začít
  16. RepeatCount: = abs (RepeatCount);
  17. pro j: = i až i + RepeatCount - 1 do
  18. OutMsg: = OutMsg + chr (InMsg [j]);
  19. i: = i + Počet opakování;
  20. jiný
  21. začít
  22. for j: = 1 to RepeatCount do
  23. OutMsg: = OutMsg + chr (InMsg [i]);
  24. i: = i + 1;
  25. konec;
  26. konec;
  27. RLEDecode: = OutMsg;
  28. konec;

Druhou metodou pro zvýšení účinnosti algoritmu RLE je použití algoritmů transformace informací, které data přímo nekomprimují, ale převedou je do formy, která je pro kompresi výhodnější. Jako příklad takového algoritmu budeme uvažovat permutaci BWT pojmenovanou po vynálezcích Burrows-Wheelerovy transformace. Tato permutace nemění samotné znaky, ale pouze mění jejich pořadí v řetězci, přičemž opakované podřetězce se po aplikaci permutace shromažďují do hustých skupin, které jsou mnohem lépe komprimovány pomocí algoritmu RLE. Přímá konverze BWT je omezena na sekvenci následujících kroků:
1. Přidání speciálního znaku konce řádku k původnímu řetězci, který se nikde jinde nenachází;
2. Získání všech cyklických permutací původního řetězce;
3. Třídění přijatých řádků v lexikografickém pořadí;
4. Vrácení posledního sloupce výsledné matice.
Implementace tohoto algoritmu je uvedena ve výpisu 3.
  1. konst
  2. EOMsg = "|" ;
  3. funkce BWTEncode (InMsg: ShortString): ShortString;
  4. OutMsg: ShortString;
  5. LastChar: ANSIChar;
  6. N, i: slovo;
  7. začít
  8. InMsg: = InMsg + EOMsg;
  9. N: = délka (InMsg);
  10. ShiftTable [1]: = InMsg;
  11. pro i: = 2 až N do
  12. začít
  13. LastChar: = InMsg [N];
  14. InMsg: = LastChar + kopie (InMsg, 1, N - 1);
  15. ShiftTable [i]: = InMsg;
  16. konec;
  17. Seřadit (ShiftTable);
  18. OutMsg: = "";
  19. pro i: = 1 až N do
  20. OutMsg: = OutMsg + ShiftTable [i] [N];
  21. BWTEncode: = OutMsg;
  22. konec;

Nejjednodušší způsob, jak vysvětlit tuto transformaci, je na konkrétním příkladu. Vezměme řetězec "ANANAS" a dohodneme se, že znakem konce řádku bude symbol "|". Všechny cyklické permutace této řady a výsledek jejich lexikografického třídění jsou uvedeny v tabulce. jeden.

Tito. výsledkem přímého převodu bude řetězec "| ННАААС". Je snadné vidět, že tento řetězec je mnohem lepší než původní; je komprimován algoritmem RLE, protože obsahuje dlouhé podsekvence opakovaných písmen.
Obdobného efektu lze dosáhnout pomocí dalších transformací, výhodou BWT transformace je však to, že je reverzibilní, nicméně inverzní transformace je obtížnější než přímá. Chcete-li obnovit původní řetězec, musíte provést následující:
Vytvořte prázdnou matici n * n, kde n je počet znaků v zakódované zprávě;
Vyplňte prázdný sloupec zcela vpravo kódovanou zprávou;
Řazení řádků tabulky v lexikografickém pořadí;
Opakujte kroky 2-3, dokud nezůstanou prázdné sloupce;
Vraťte řádek, který končí znakem konce řádku.

Na první pohled je zpětná transformace přímočará a jedna z možností je zobrazena ve výpisu 4.

  1. konst
  2. EOMsg = "|" ;
  3. funkce BWTDecode (InMsg: ShortString): ShortString;
  4. OutMsg: ShortString;
  5. ShiftTable: pole ShortString;
  6. N, i, j: slovo;
  7. začít
  8. OutMsg: = "";
  9. N: = délka (InMsg);
  10. SetLength (ShiftTable, N + 1);
  11. pro i: = 0 až N do
  12. ShiftTable [i]: = "";
  13. pro i: = 1 až N do
  14. začít
  15. pro j: = 1 až N do
  16. ShiftTable [j]: = InMsg [j] + ShiftTable [j];
  17. Seřadit (ShiftTable);
  18. konec;
  19. pro i: = 1 až N do
  20. pokud ShiftTable [i] [N] = EOMsg pak
  21. OutMsg: = ShiftTable [i];
  22. odstranit (OutMsg, N, 1);
  23. BWTDecode: = OutMsg;
  24. konec;

V praxi však účinnost závisí na zvoleném třídicím algoritmu. Triviální algoritmy s kvadratickou složitostí budou mít samozřejmě extrémně negativní dopad na výkon, proto se doporučuje používat efektivní algoritmy.

Po seřazení tabulky získané v sedmém kroku je nutné vybrat z tabulky řádek končící znakem "|". Je snadné vidět, že toto je jediná linie. Že. zkoumali jsme transformaci BWT na konkrétním příkladu.

Souhrnně lze říci, že hlavní výhodou skupiny algoritmů RLE je jednoduchost a rychlost ovládání (včetně rychlosti dekódování) a hlavní nevýhodou je neefektivita na neopakujících se znakových sadách. Použití speciálních permutací zvyšuje efektivitu algoritmu, ale také výrazně zvyšuje dobu běhu (zejména dekódování).

Slovníková komprese (algoritmy LZ)

Skupina slovníkových algoritmů, na rozdíl od algoritmů skupiny RLE, nekóduje počet opakování znaků, ale dříve zjištěné sekvence znaků. Během provozu uvažovaných algoritmů se dynamicky vytváří tabulka se seznamem dříve nalezených sekvencí a jejich odpovídajících kódů. Tato tabulka se často nazývá slovník a odpovídající skupina algoritmů se nazývá slovník.

Nejjednodušší verze slovníkového algoritmu je popsána níže:
Inicializujte slovník se všemi znaky, které se objevují ve vstupním řetězci;
Najděte ve slovníku nejdelší sekvenci (S), která odpovídá začátku zakódované zprávy;
Vydejte kód nalezené sekvence a odstraňte jej ze začátku zakódované zprávy;
Pokud není dosaženo konce zprávy, přečtěte si další znak a přidejte Sc do slovníku, přejděte ke kroku 2. V opačném případě ukončete.

Například nově inicializovaná slovní zásoba pro frázi "CUCKOOKUCHONKUPILACAPUCHON" je uvedena v tabulce. 3:

Během procesu komprese bude slovník doplněn o sekvence nalezené ve zprávě. Postup doplňování slovníku je uveden v tabulce. 4.

Při popisu algoritmu byl záměrně vynechán popis situace, kdy je slovník zcela zaplněn. V závislosti na variantě algoritmu je možné různé chování: úplné nebo částečné vyprázdnění slovníku, zastavení plnění slovníku nebo rozšíření slovníku s odpovídajícím zvětšením šířky kódu. Každý z těchto přístupů má určité nevýhody. Například zastavení dokončování slovníku může vést k situaci, kdy slovník ukládá sekvence, které se vyskytují na začátku komprimovaného řetězce, ale později se nevyskytují. Vymazáním slovníku lze zároveň odstranit časté sekvence. Většina používaných implementací při vyplňování slovníku začne sledovat kompresní poměr, a když klesne pod určitou úroveň, slovník je přestavěn. Dále se budeme zabývat nejjednodušší implementací, která zastaví doplňování slovníku, když je plný.

Nejprve si definujme slovník jako záznam, který uchovává nejen nalezené podřetězce, ale také počet podřetězců uložených ve slovníku:

Dříve nalezené dílčí sekvence jsou uloženy v poli Words a jejich kódy jsou počty dílčích sekvencí v tomto poli.
Definujeme také funkce pro vyhledávání ve slovníku a přidávání do slovníku:

  1. konst
  2. MAX_DICT_LENGTH = 256;
  3. funkce FindInDict (D: TDictionary; str: ShortString): celé číslo;
  4. r: celé číslo;
  5. i: celé číslo;
  6. fl: boolean;
  7. začít
  8. r = -1;
  9. pokud D. WordCount> 0 pak
  10. začít
  11. i: = D. Počet slov;
  12. fl: = nepravda;
  13. zatímco (ne fl) a (i> = 0) ano
  14. začít
  15. i: = i-1;
  16. fl: = D. Slova [i] = str;
  17. konec;
  18. konec;
  19. pokud fl pak
  20. r: = i;
  21. FindInDict: = r;
  22. konec;
  23. procedure AddToDict (var D: TDictionary; str: ShortString);
  24. začít
  25. pokud D. WordCount< MAX_DICT_LENGTH then
  26. začít
  27. D. Počet slov: = D. Počet slov + 1;
  28. SetLength (D. Slova, D. Počet slov);
  29. D. Slova [D. Počet slov - 1]: = str;
  30. konec;
  31. konec;

Pomocí těchto funkcí lze proces kódování podle popsaného algoritmu implementovat následovně:
  1. funkce LZWEncode (InMsg: ShortString): TEncodedString;
  2. OutMsg: TEncodedString;
  3. tmpstr: ShortString;
  4. D: TDslovník;
  5. i, N: byte;
  6. začít
  7. SetLength (OutMsg, length (InMsg));
  8. N: = 0;
  9. InitDict (D);
  10. zatímco délka (InMsg)> 0 do
  11. začít
  12. tmpstr: = InMsg [1];
  13. zatímco (FindInDict (D, tmpstr)> = 0) a (délka (InMsg)> délka (tmpstr))
  14. tmpstr: = tmpstr + InMsg [délka (tmpstr) + 1];
  15. if FindInDict (D, tmpstr)< 0 then
  16. delete (tmpstr, délka (tmpstr), 1);
  17. OutMsg [N]: = FindInDict (D, tmpstr);
  18. N: = N + 1;
  19. smazat (InMsg, 1, délka (tmpstr));
  20. if length (InMsg)> 0 then
  21. AddToDict (D, tmpstr + InMsg [1]);
  22. konec;
  23. SetLength (OutMsg, N);
  24. LZWEncode: = OutMsg;
  25. konec;

Výsledkem kódování budou čísla slov ve slovníku.
Proces dekódování se redukuje na přímé dešifrování kódů, přičemž není potřeba přenášet vytvořený slovník, stačí, že při dekódování se slovník inicializuje stejně jako při kódování. Poté bude slovník zcela obnoven přímo během procesu dekódování zřetězením předchozí podsekvence a aktuálního symbolu.

Jediný problém je možný v následující situaci: když je potřeba dekódovat podsekvenci, která ještě není ve slovníku. Je snadné vidět, že je to možné pouze tehdy, když je nutné extrahovat podřetězec, který má být přidán v aktuálním kroku. To znamená, že podřetězec odpovídá vzoru cSc, tzn. začíná a končí stejným znakem. Navíc cS je podřetězec přidaný v předchozím kroku. Uvažovaná situace je jediná, kdy je potřeba dekódovat řádek, který ještě nebyl přidán. Vzhledem k výše uvedenému můžeme navrhnout následující možnost pro dekódování komprimovaného řetězce:

  1. funkce LZWDecode (InMsg: TEncodedString): ShortString;
  2. D: TDslovník;
  3. OutMsg, tmpstr: ShortString;
  4. i: byte;
  5. začít
  6. OutMsg: = "";
  7. tmpstr: = "";
  8. InitDict (D);
  9. pro i: = 0 až délka (InMsg) - 1 do
  10. začít
  11. if InMsg [i]> = D. WordCount pak
  12. tmpstr: = D. Slova [InMsg [i - 1]] + D. Slova [InMsg [i - 1]] [1]
  13. jiný
  14. tmpstr: = D. Slova [InMsg [i]];
  15. OutMsg: = OutMsg + tmpstr;
  16. pokud i> 0 pak
  17. AddToDict (D, D. Slova [InMsg [i - 1]] + tmpstr [1]);
  18. konec;
  19. LZWDecode: = OutMsg;
  20. konec;

Mezi výhody slovníkových algoritmů patří vyšší účinnost komprese ve srovnání s RLE. Nicméně je třeba si uvědomit, že skutečné použití těchto algoritmů je spojeno s určitými implementačními obtížemi.

Entropické kódování

Kódování se stromy Shannon-Fano

Algoritmus Shannon-Fano je jedním z prvních vyvinutých kompresních algoritmů. Algoritmus je založen na myšlence reprezentovat častější znaky pomocí kratších kódů. Navíc kódy získané pomocí algoritmu Shannon-Fano mají vlastnost prefix: tj. žádný kód není začátkem žádného jiného kódu. Vlastnost prefix zajišťuje, že kódování je jedna ku jedné. Algoritmus pro konstrukci Shannon-Fano kódů je uveden níže:
1. Rozdělte abecedu na dvě části, přičemž celkové pravděpodobnosti symbolů jsou co nejblíže k sobě.
2. Ke kódu prefixu první části znaků přidejte 0, ke kódu prefixu druhé části znaků přidejte 1.
3. Pro každou část (ve které jsou alespoň dvě postavy) rekurzivně proveďte kroky 1-3.
Navzdory své komparativní jednoduchosti není algoritmus Shannon-Fano bez nedostatků, z nichž nejvýznamnější je neoptimální kódování. Ačkoli je rozdělení v každém kroku optimální, algoritmus nezaručuje optimální výsledek jako celek. Zvažte například následující řádek: "AAAABVGDEZH". Odpovídající Shannon-Fano strom a z něj odvozené kódy jsou znázorněny na Obr. jeden:

Bez kódování bude zpráva zabírat 40 bitů (za předpokladu, že každý znak je zakódován 4 bity) a pomocí Shannon-Fano algoritmu 4 * 2 + 2 + 4 + 4 + 3 + 3 + 3 = 27 bitů. Objem zpráv se snížil o 32,5 %, ale níže bude ukázáno, že tento výsledek lze výrazně zlepšit.

Kódování pomocí Huffman Trees

Huffmanův kódovací algoritmus, vyvinutý několik let po algoritmu Shannon-Fano, má také prefixovou vlastnost a navíc osvědčenou minimální redundanci, právě proto je extrémně rozšířený. K získání Huffmanových kódů se používá následující algoritmus:
1. Všechny symboly abecedy jsou reprezentovány jako volné uzly, přičemž váha uzlu je úměrná frekvenci symbolu ve zprávě;
2. Z množiny volných uzlů se vyberou dva uzly s minimální váhou a vytvoří se nový (rodičovský) uzel s váhou rovnou součtu vah vybraných uzlů;
3. Vybrané uzly jsou odstraněny z volného seznamu a nadřazený uzel vytvořený na jejich základě je přidán do tohoto seznamu;
4. Kroky 2-3 se opakují, dokud není ve volném seznamu více než jeden uzel;
5. Na základě sestrojeného stromu je každému znaku abecedy přiřazen prefixový kód;
6. Zpráva je zakódována přijatými kódy.

Zvažte stejný příklad jako v případě Shannon-Fano algoritmu. Huffmanův strom a kódy získané pro zprávu „AAAAABVGDEZH“ jsou znázorněny na Obr. 2:

Je snadné vypočítat, že velikost zakódované zprávy bude 26 bitů, což je méně než v algoritmu Shannon-Fano. Samostatně je třeba poznamenat, že vzhledem k popularitě Huffmanova algoritmu v současné době existuje mnoho možností pro Huffmanovo kódování, včetně adaptivního kódování, které nevyžaduje přenos frekvencí symbolů.
Mezi nevýhody Huffmanova algoritmu patří významnou část problémy spojené se složitostí implementace. Použití reálných proměnných pro ukládání frekvencí symbolů je spojeno se ztrátou přesnosti, proto se v praxi často používají celočíselné proměnné, ale od hmotnost rodičovských uzlin neustále roste, dříve nebo později dojde k přetečení. I přes jednoduchost algoritmu může jeho správná implementace stále způsobovat určité potíže, zejména u velkých abeced.

Kódování se sečnými funkčními stromy

Kódování pomocí funkcí secant je algoritmus vyvinutý autory, který umožňuje získat předponové kódy. Algoritmus je založen na myšlence sestavení stromu, jehož každý uzel obsahuje funkci secant. Pro podrobnější popis algoritmu je nutné uvést několik definic.
Slovo je uspořádaná sekvence m bitů (číslo m se nazývá délka slova).
Secant literal je dvojice typu hodnota vybití-vybití. Například literál (4,1) znamená, že 4 bity slova musí být 1. Pokud je splněna podmínka literálu, pak je literál považován za pravdivý, jinak je nepravdivý.
K-bitový sekant je množina k literálů. Pokud jsou všechny literály pravdivé, pak je pravdivá i samotná funkce secant, jinak je nepravdivá.

Strom je postaven tak, že každý uzel rozděluje abecedu na co nejbližší části. Na Obr. 3 ukazuje příklad sečného stromu:

Strom funkcí sečny v obecném případě nezaručuje optimální kódování, ale poskytuje extrémně vysokou rychlost práce díky jednoduchosti provozu v uzlech.

Aritmetické kódování

Aritmetické kódování je jedním z nejvíce efektivní způsoby komprimaci informací. Na rozdíl od Huffmanova algoritmu vám aritmetické kódování umožňuje kódovat zprávy s entropií menší než 1 bit na symbol. Protože většina aritmetických kódovacích algoritmů je chráněna patenty, níže budou popsány pouze základní myšlenky.
Předpokládejme, že v použité abecedě je N symbolů a_1, ..., a_N, s frekvencemi p_1, ..., p_N, v tomto pořadí. Potom bude algoritmus aritmetického kódování vypadat takto:
Berte jako pracovní poloviční interval)