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

ARCHIVÁTORY

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

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

Kompresní poměr: K c \u003d V c / V o * 100%

K c - kompresní poměr, V c- hlasitost 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 rozbalí 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 vám umožňují vytvářet samorozbalovací archivní soubory, tj. abyste je rozbalili, nemusíte spouštět archivační program, protože samy obsahují program rozbalení. Tyto archivy se nazývají archivy SFX
(SelF-Extrakce). Přípona těchto souborů je * .EXE.


Principy komprese informací

V každém textu jsou opakující se znaky. Je možné zadat jeden znak a počet opakování. Účinnost tohoto algoritmu je při použití na grafické soubory ještě vyšší. Když se podíváte na monitor, uvidíte spoustu opakujících se teček stejné barvy. Formát grafického souboru PCX je založen na tomto principu komprese informací. Moderní archivátoři rozlišují nejen opakující se symboly, ale také řetězce symbolů, jednotlivá slova.

Pokud text nepoužívá všechny znaky abecedy PC, můžete je pro jejich kódování použít místo jednoho bajtu, 8 bitů, menšího počtu. 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ž vám umožní napsat tři znaky do dvou bajtů.

3. V následujícím principu se používá pravidelnost, že písmena v textu se vyskytují s různou frekvencí. Například v tomto textu je mezera nejběžnějším znakem, velmi často se nacházejí symboly „a“, „a“. Tyto běžné symboly mohou být reprezentovány krátkou kombinací bitů, zbytek symbolů lze kódovat delší sekvencí. Například:

4. Fyzicky PC přiděluje prostor pro umístění souborů na disk ve shlucích - ve 4 KB blocích. Je nemožné zvýraznit méně. Například pokud má soubor 8193 bajtů (8 KB a 1 bajt), fyzicky to bude 16 KB nebo 16384 bajtů. Kombinace skupiny souborů do jednoho vám umožní ukládat na tyto zbytky. Při balení malých souborů je to velká úspora.

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


Archivátor zipů

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

Klíče: -rp archivace s podadresáři udržující strukturu

S PWD ochrana archivního hesla (PWD)

Přidat soubory do archivu

M přesunout soubory do archivu

V zobrazit obsah archivu

Pokud se archivují všechny soubory v adresáři, zadejte masku *.*

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

Přepínače: -d rozbalení s podadresáři udržující strukturu

Heslo archivu SPWD (PWD)


Archivátor Arj

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

U archivátoru arj provádí jeden soubor operace a rozbalení a zabalení.

Příkazy: a archivace

vybalení bez zachování adresářové struktury

x vybalení se zachováním struktury

prohlížím si obsah archivu

m přesunout soubory do archivu

d mazat soubory z archivu

Přepínače: -r balení s podadresáři udržující strukturu

V rozdělení archivu na svazky s obj. (Pokud je uvedeno)

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

Při rozbalování vícesvazkového archivu je uvedeno V.

G PWD archivovat heslo ( PWD)

Soubory ZIP

Rozbalování souborů

© 2015-2019 web
Všechna práva patří jejich autorům. Tento web si nenárokuje 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 komprese 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 v jakékoli jednotce. Docela často musí moderní uživatelé, kteří se potýkají s nedostatkem volného místa na jednotce, odstranit veškerá data, aby uvolnili potřebné místo, zatímco pokročilejší uživatelé nejčastěji používají kompresi dat, aby snížili jeho objem.

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

Měli byste komprimovat data?

Komprese dat je dnes docela 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 zakoupit pokročilá zařízení pro ukládání dat, která poskytují schopnost využívat poměrně velké množství volného místa a jsou vybavena vysokorychlostními informačními vysílacími kanály.

Je však třeba správně pochopit, že v průběhu času se také zvyšuje množství dat, která je třeba přenášet. A pokud byl doslova před deseti lety objem 700 MB považován za standard běžného filmu, dnes filmy vyrobené v kvalitě HD mohou mít objemy rovné několika desítkám gigabajtů, nemluvě o tom, kolik volného místa zabírají vysoké kvalitní filmy ve formátu Blu-ray.

Kdy je nutná komprese dat?

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

  • Přenos určitých dokumentů prostřednictvím e-mailu. To platí zejména pro situace, kdy je nutné 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írá, 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, pokud není možné vyměnit nebo přidat nové úložné médium. Nejběžnější situace je zejména v případě, že existují určitá omezení dostupného rozpočtu, ale na disku není dostatek volného místa.

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

Jak lze komprimovat data?

Dnes existuje široká škála metod komprese informací, ale všechny jsou rozděleny do dvou hlavních skupin - to je komprese s určitými ztrátami, stejně jako komprese bez ztráty.

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í, pokud je komprimován určitý textový dokument.

Současně stojí za zmínku skutečnost, že v některých situacích není potřeba nejpřesnější obnovy 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 je mnohem snazší implementovat a poskytuje také nejvyšší možnou archivaci.

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í těchto algoritmů provádí ke kompresi analogových dat, jako jsou všechny druhy obrazů nebo zvuků. V takových situacích se rozbalené soubory mohou zcela lišit od původních informací, ale jsou prakticky nerozeznatelné od lidského oka nebo ucha.

Bezztrátová komprese

Bezztrátové kompresní algoritmy poskytují nejpřesnější obnovu dat, což eliminuje ztrátu komprimovaných souborů. V tomto případě je však třeba správně pochopit skutečnost, že v v tomto případě komprese souborů není tak efektivní.

Obecné metody

Mimo jiné existuje určitý počet univerzálních metod, kterými se provádí efektivní proces komprese informací za účelem zmenšení prostoru, který zabírá. Obecně existují pouze tři hlavní technologie:

  • Převod streamu. V tomto případě se popis nových příchozích nekomprimovaných informací provádí prostřednictvím již zpracovaných souborů, přičemž se nepočítají žádné pravděpodobnosti, ale znaky se kódují 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í prostoru, který na disku zabírá, je rozdělena do dvou podkategorií - adaptivní a blokové metody. Adaptivní verze umožňuje výpočet pravděpodobností nových souborů na základě informací, které již byly zpracovány během procesu kódování. Zejména by takové metody měly zahrnovat různé adaptivní verze algoritmů Shannon-Fano a Huffman. Blokový algoritmus poskytuje samostatný výpočet každého bloku informací s následným přidáním k nejvíce komprimovanému bloku.
  • Bloková transformace. Příchozí informace jsou rozděleny do několika bloků a poté dochází k holistické transformaci. Je třeba říci, že určité metody, zejména ty, které jsou založeny na permutaci několika bloků, mohou nakonec vést k významnému snížení množství informací, které jsou komprimovány. Musí však být správně pochopeno, že po takovém zpracování nakonec dojde k významnému zlepšení, v důsledku čehož je následná komprese pomocí jiných algoritmů mnohem jednodušší a rychlejší.

Kopírovat kompresi

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

Proč je to potřeba?

Schopnost komprimovat informace a současně výrazně zkrátit čas potřebný k kopírování souborů, které potřebujete, a přitom efektivně šetřit volné místo na disku. Jinými slovy, při použití komprese budou informace kopírovány mnohem kompaktněji a rychleji a můžete ušetřit své peníze a finance, které byly nutné k zakoupení větší jednotky. Mimo jiné komprimací informací také zkrátíte čas potřebný při přenosu všech dat na server nebo při jejich kopírování přes síť.

Kompresi 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 nástroje se nezapomeňte podívat, do jaké míry může vybraný program komprimovat data. Závisí to na typu informace, v důsledku čehož dochází k účinnosti komprese textové dokumenty může být více než 90%, přičemž efektivní bude nejvýše 5%.

Dobrý den.
Dnes se chci dotknout tématu bezztrátové komprese dat. Navzdory skutečnosti, že o Habrém již byly články věnované některým algoritmům, chtěl jsem o tom promluvit trochu podrobněji.
Pokusím se podat jak matematický popis, tak popis v obvyklé formě, aby si každý mohl najít 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. Samozřejmě všichni chápeme, že nyní máme přístup jak k velkoobjemovým úložným médiím, tak k vysokorychlostním kanálům pro přenos dat. Zároveň však roste objem přenášených informací. Pokud jsme před několika lety sledovali 700 megabajtové filmy, které se vejdou na jeden disk, dnes mohou filmy v HD kvalitě trvat desítky gigabajtů.
Komprese všeho a všeho samozřejmě nemá velkou výhodu. Stále však existují situace, kdy je komprese mimořádně užitečná, pokud není nutná.

  • Odesílání dokumentů e-mailem (zejména velké objemy dokumentů pomocí mobilních zařízení)
  • Při publikování dokumentů na webových stránkách je třeba šetřit provoz
  • Při výměně nebo přidání úložiště je obtížné ušetřit místo na disku. Například k tomu dochází v případech, kdy není snadné sestavit rozpočet na kapitálové výdaje a na disku není dostatek místa.

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

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

Pojďme tedy k zvažování bezztrátových kompresních algoritmů.

Všestranné metody bezeztrátové komprese

Obecně existují tři základní možnosti, na nichž jsou kompresní algoritmy postaveny.
První skupina metody - transformace proudu. To předpokládá popis nových příchozích nekomprimovaných dat prostřednictvím již zpracovaných. 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 v metodách LZ (pojmenovaných po Abrahamovi Lempelovi a Jacobovi Zivovi). V tomto případě je druhý a další výskyt určitého dílčího řetězce, který je kodéru již znám, nahrazen odkazy na jeho první výskyt.

Druhá skupina Metody jsou statistické kompresní metody. Tyto metody jsou zase rozděleny na adaptivní (nebo tokové) a blokové.
V první (adaptivní) verzi je výpočet pravděpodobností pro nová data založen na datech již zpracovaných během kódování. Mezi tyto metody patří adaptivní verze algoritmů Huffman a Shannon-Fano.
V druhém (blokovém) případě se statistika každého datového bloku počítá samostatně a přidává se k nejvíce komprimovanému bloku. To zahrnuje statické verze metod Huffman, Shannon-Fano a aritmetické kódování.

Třetí skupina metody jsou takzvané metody převodu bloků. Příchozí data jsou rozdělena do bloků, které jsou poté zcela transformovány. Zároveň některé metody, zejména ty, které jsou založeny na blokové permutaci, nemusí vést k významnému (nebo dokonce žádnému) snížení množství dat. Po takovém zpracování se však datová struktura výrazně vylepšila a následná komprese jinými algoritmy je úspěšnější a rychlejší.

Obecné zásady, na nichž je komprese dat založena

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 kódovány kratšími kódy a méně běžné prvky s delšími kódy, bude k uložení všech dat zapotřebí 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í délkou kódu je popsán v takzvané Shannonově větě o kódování zdrojů, která definuje maximální bezztrátový limit komprese a Shannonovu entropii.

Trochu matematiky
Pokud se pravděpodobnost výskytu prvku s i rovná p (s i), pak bude nejvýhodnější tento prvek reprezentovat - log 2 p (s i) v bitech. Pokud je během kódování možné dosáhnout toho, že délka všech prvků bude snížena na log 2 p (s i) bitů, pak bude délka celé kódované sekvence minimální pro všechny možné metody kódování. Kromě toho, pokud se rozdělení pravděpodobnosti všech prvků F \u003d (p (s i)) nezmění a pravděpodobnosti prvků jsou vzájemně nezávislé, lze průměrnou délku kódů vypočítat jako

Tato hodnota se nazývá entropie rozdělení pravděpodobnosti F nebo entropie zdroje v tento moment čas.
Pravděpodobnost vzhledu prvku však obvykle nemůže být nezávislá, naopak záleží na některých faktorech. V tomto případě bude mít pro každý nový kódovaný prvek s i rozdělení pravděpodobnosti F určitou hodnotu F k, tj. Pro každý prvek F \u003d F k a H \u003d H k.

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 ohledem na tento pozměňovací návrh 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 se to stane?

Bezpaměťové kódování

Kódy bez paměti jsou nejjednodušší kódy, na jejichž základě lze provádět kompresi dat. V kódu bez paměti je každý znak v kódovaném datovém vektoru nahrazen kódovým slovem z předponované sady binárních sekvencí nebo slov.
Podle mého názoru to není nejjasnější definice. Podívejme se na toto téma trochu podrobněji.

Nechť je uvedena nějaká abeceda , skládající se z určitého (konečného) počtu písmen. Zavoláme každou konečnou posloupnost symbolů z této abecedy (A \u003d a 1, a 2, ..., a n) slovoa číslo n je délka tohoto slova.

Nechť je uvedena i jiná abeceda ... Podobně označujeme slovo v této abecedě jako B.

Pojďme si představit další dvě notace pro množinu všech neprázdných slov v abecedě. Dovolit je počet neprázdných slov v první abecedě a - ve druhé.

Nechte také dát mapování F, které přiřadí každému slovu A z první abecedy nějaké slovo B \u003d F (A) z druhé. Potom se zavolá slovo B. kód slovo A a bude volán přechod z původního slova na jeho kód kódování.

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

a n<-> B č

Tato korespondence se nazývá systém, a jsou označeny ∑.
V tomto případě volají slova B 1, B 2, ..., B n základní kódya typ kódování s jejich pomocí je abecední kódování... Většina z nás samozřejmě narazila na tento druh kódování, i když jsme nevěděli všechno, co jsem popsal výše.

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

Nechť slovo B má tvar B \u003d B "B" ". Pak se B" nazývá začátek, nebo předpona slovo B a B "" je jeho konec. Jedná se o poměrně jednoduchou definici, ale je třeba poznamenat, že pro každé slovo B lze považovat jak prázdné slovo ʌ („mezera“), tak samotné slovo B za začátky i konce.

Přiblížili jsme se tedy k pochopení definice kódů bez paměti. Poslední definicí, kterou musíme pochopit, je sada předpon. Schéma ∑ má vlastnost předpony, pokud pro libovolné 1≤i, j≤r, i ≠ j slovo B i není předponou slova Bj.
Jednoduše řečeno, sada předpon je konečná množina, ve které žádný prvek není předponou (nebo začátkem) jiného prvku. Jednoduchý příklad taková sada je například obyčejná abeceda.

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

  1. Je sestavena abeceda phabet znaků původní zprávy a abecední znaky jsou seřazeny 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 nějakým slovem B i z množiny předpon Ω.
  3. Každý znak je zakódován, následovaný kombinací kódů do jednoho datového proudu, což bude výsledek komprese.

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

Huffmanův algoritmus

Algoritmus Huffmana používá frekvenci výskytu stejných bytů v bloku vstupních dat a mapuje často se vyskytující bloky na kratší bitové řetězce a naopak. Tento kód je minimální - nadbytečný. Uvažujme o případu, kdy bez ohledu na vstupní proud se abeceda výstupního proudu skládá pouze ze 2 znaků - nula a jeden.

Nejprve při kódování pomocí Huffmanova algoritmu musíme vytvořit obvod ∑. To se děje 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 (tj. S čím 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 j vstupního proudu, které mají nejnižší pravděpodobnost výskytu, jsou spojeny do jednoho „pseudosymbolu“ s pravděpodobností p se rovná součtu pravděpodobností symbolů v něm obsažených. Potom 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ý pseudo-symbol (přirozeně musí být vložen do abecedy na správném místě, s ohledem na jeho pravděpodobnost).
Kroky 2 a 3 se opakují, dokud v abecedě nezůstane pouze 1 pseudo znak, který obsahuje všechny původní znaky abecedy. Navíc, protože v každém kroku a pro každý znak se mění odpovídající slovo B i (přidáním jednoho nebo nuly), pak po dokončení tohoto postupu bude určitý kód B i odpovídat každému počátečnímu symbolu abecedy a i.

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

Vytvořme tedy schéma pro danou abecedu.

  1. Spojíme dva znaky s nejnižší pravděpodobností (0,11 a 0,15) do pseudo-znaku p ".
  2. Zkombinujte 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ý pseudo znak do abecedy.
  4. Nakonec spojíme zbývající dva symboly, abychom dostali horní část stromu.

Pokud ilustrujete tento proces, získáte něco takového:


Jak vidíte, pokaždé, když sloučíme, 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 \u003d 0
a 2 \u003d 11
a 3 \u003d 100
a 4 \u003d 101

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

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

Zpočátku daný řetězec obsazeno 8000 bitů. Po kódování dostaneme řetězec délky ∑p i l i \u003d 500 * 1 + 240 * 2 + 150 * 3 + 110 * 3 \u003d 1760 bitů. Takže se nám podařilo komprimovat data faktorem 4,54 a utratit průměrně 1,76 bitu za kódování každého znaku streamu.

Dovolte mi připomenout, že podle Shannona je průměrná délka kódů. Dosazením našich pravděpodobností do této rovnice získáme průměrnou délku kódu rovnou 1,75496602732291, což je velmi, velmi blízké našemu výsledku.
Je však třeba mít na paměti, že kromě samotných dat musíme uložit kódovací tabulku, což mírně zvýší konečnou velikost kódovaných dat. 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 pravděpodobnostní tabulku a někdy je nutné ji dynamicky kompilovat procházením komprimovaných dat.

Závěr

V tomto článku jsem se tedy snažil mluvit obecné zásady, který se používá pro bezztrátovou kompresi, a také považován za jeden z kanonických algoritmů - Huffmanovo kódování.
Pokud je článek po chuti habro komunitě, pak rád napíšu pokračování, protože s bezztrátovou kompresí je stále mnoho zajímavých věcí; jedná se jak o klasické algoritmy, tak o předběžné datové transformace (například Burrows-Wheelerova transformace), a samozřejmě o specifické algoritmy pro kompresi zvuku, videa a obrázků (podle mého názoru 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 rok
  • D. Salomon. Komprese dat, obrázků a zvuku; ISBN 5-94836-027-X; 2004

GORKOFF 24. února 2015 v 11:41

Metody komprese dat

  • Algoritmy

Můj vědecký poradce a já připravujeme malou monografii o zpracování obrazu. Rozhodl jsem se předložit kapitolu věnovanou algoritmům komprese obrazu do HabraSociety. Vzhledem k tomu, že je těžké vejít do jedné kapitoly v rámci jednoho příspěvku, rozhodl jsem se jej rozdělit do tří příspěvků:
1. Metody komprese dat;
2. Bezztrátová komprese obrazu;
3. Komprese obrázků se ztrátou.
Níže si můžete přečíst první příspěvek ze série.

V tuto chvíli existuje velké množství bezztrátových kompresních algoritmů, které lze podmíněně rozdělit do dvou velkých skupin:
1. Algoritmy streamu a slovníku. Tato skupina zahrnuje algoritmy rodin RLE (run-length encoding), LZ * atd. Funkce všech algoritmů této skupiny spočívá v tom, že kódování nepoužívá informace o frekvencích znaků ve zprávě, ale informace o sekvencích s nimiž jsme se setkali dříve.
2. Algoritmy pro statistickou (entropickou) kompresi. Tato skupina algoritmů komprimuje informace pomocí nerovnoměrnosti frekvencí, s nimiž se ve zprávě vyskytují různé znaky. Algoritmy této skupiny zahrnují algoritmy pro aritmetické a předponové kódování (pomocí Shannon-Fanna, Huffmana, sekančních stromů).
Algoritmy transformace informací lze rozlišit do samostatné skupiny. Algoritmy této skupiny přímo nekomprimují informace, ale jejich aplikace výrazně zjednodušuje další kompresi pomocí streamovacích, slovníkových a entropických algoritmů.

Streamovací a slovníkové algoritmy

Spustit délkové kódování

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

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

Nejjednodušší metodou je následující modifikace: 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 je-li první bit 0, pak dalších 7 bitů označuje počet znaků, které je třeba vzít bez opakování. Pokud kódujete "ABABAB" pomocí této úpravy, dostaneme "-6ABABAB" (7 bajtů). Je zřejmé, že navrhovaná technika může významně zlepšit účinnost algoritmu RLE na neopakujících se sekvencích znaků. Implementace navrhovaného přístupu je uvedena v seznamu 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: \u003d 0;
  9. SetLength (EncodedString, 2 * délka (InMsg));
  10. while length (InMsg)\u003e \u003d 1 do
  11. začít
  12. MatchFl: \u003d (délka (InMsg)\u003e 1) a (InMsg [1] \u003d InMsg [2]);
  13. MatchCount: \u003d 1;
  14. while (MatchCount<= 126 ) and (MatchCount < length(InMsg) ) and ((InMsg[ MatchCount] = InMsg[ MatchCount + 1 ] ) = MatchFl) do
  15. MatchCount: \u003d MatchCount + 1;
  16. pokud tedy MatchFl
  17. začít
  18. N: \u003d N + 2;
  19. EncodedString [N - 2]: \u003d MatchCount + 128;
  20. EncodedString [N - 1]: \u003d ord (InMsg [1]);
  21. jiný
  22. začít
  23. pokud MatchCount<> délka (InMsg)
  24. MatchCount: \u003d MatchCount - 1;
  25. N: \u003d N + 1 + MatchCount;
  26. EncodedString [N - 1 - MatchCount]: \u003d - MatchCount + 128;
  27. for i: \u003d 1 to MatchCount do
  28. EncodedString [N - 1 - MatchCount + i]: \u003d ord (InMsg [i]);
  29. konec;
  30. odstranit (InMsg, 1, MatchCount);
  31. konec;
  32. SetLength (EncodedString, N);
  33. RLEEncode: \u003d EncodedString;
  34. konec;

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

Druhou metodou pro zvýšení efektivity algoritmu RLE je použití algoritmů transformace informací, které přímo nekomprimují data, ale přinášejí je do formy, která je pro kompresi výhodnější. Jako příklad takového algoritmu vezmeme v úvahu BWT permutaci, pojmenovanou podle vynálezců Burrows-Wheelerovy transformace. Tato permutace nemění samotné znaky, ale pouze mění jejich pořadí v řetězci, zatímco opakované podřetězce po použití permutace jsou shromažďovány v hustých skupinách, které jsou mnohem lépe komprimovány pomocí algoritmu RLE. Přímý převod BWT se sníží na posloupnost následujících kroků:
1. Přidání speciálního znaku konce řádku k původnímu řetězci, který nikde jinde nenajdete;
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 v seznamu 3.
  1. konst
  2. EOMsg \u003d "|" ;
  3. funkce BWTEncode (InMsg: ShortString): ShortString;
  4. OutMsg: ShortString;
  5. LastChar: ANSIChar;
  6. N, i: slovo;
  7. začít
  8. InMsg: \u003d InMsg + EOMsg;
  9. N: \u003d délka (InMsg);
  10. ShiftTable [1]: \u003d InMsg;
  11. pro i: \u003d 2 až N dělat
  12. začít
  13. LastChar: \u003d InMsg [N];
  14. InMsg: \u003d LastChar + kopie (InMsg, 1, N - 1);
  15. ShiftTable [i]: \u003d InMsg;
  16. konec;
  17. Třídit (ShiftTable);
  18. OutMsg: \u003d "";
  19. pro i: \u003d 1 až N dělat
  20. OutMsg: \u003d OutMsg + ShiftTable [i] [N];
  21. BWTEncode: \u003d OutMsg;
  22. konec;

Nejjednodušší způsob, jak vysvětlit tuto transformaci, je konkrétní příklad. Vezměme řetězec „ANANAS“ a souhlasíme s tím, že znakem konce řádku bude znak „|“. Všechny cyklické permutace tohoto řádku a výsledek jejich lexikografického třídění jsou uvedeny v tabulce. jeden.

Ty. přímý převod bude mít za následek řetězec "| ННАААС". Je dobře vidět, že tento řetězec je mnohem lepší než ten původní; je komprimován algoritmem RLE, protože obsahuje dlouhé posloupnosti opakovaných písmen.
Podobného efektu lze dosáhnout pomocí jiných transformací, ale výhodou transformace BWT je, že je reverzibilní, avšak 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 kódované zprávě;
Vyplňte pravý prázdný sloupec kódovanou zprávou;
Řazení řádků tabulky v lexikografickém pořadí;
Opakujte kroky 2–3, dokud nebudou prázdné sloupce;
Vraťte řádek, který končí znakem konce řádku.

Na první pohled není implementace inverzní transformace obtížná a jedna z možností implementace je uvedena v seznamu 4.

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

V praxi však účinnost závisí na vybraném třídicím algoritmu. Triviální algoritmy s kvadratickou složitostí budou mít zjevně 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 řádek z tabulky, který končí znakem „|“. Je snadné vidět, že toto je jediný řádek. Tak zkoumali jsme BWT transformaci na konkrétním příkladu.

Stručně řečeno, můžeme říci, že hlavní výhodou skupiny algoritmů RLE je jednoduchost a rychlost provozu (včetně rychlosti dekódování) a hlavní nevýhodou je neúčinnost na neopakujících se znakových sadách. Použití speciálních permutací zvyšuje účinnost algoritmu, ale také výrazně zvyšuje dobu zpracování (zejména dekódování).

Komprese slovníku (algoritmy LZ)

Skupina slovníkových algoritmů, na rozdíl od algoritmů skupiny RLE, nekóduje počet opakování znaků, ale dříve se vyskytly posloupnosti znaků. Během provozu uvažovaných algoritmů se dynamicky vytváří tabulka se seznamem již nalezených sekvencí a odpovídajícími kódy. 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 objeví ve vstupním řetězci;
Najděte ve slovníku nejdelší sekvenci (S), která odpovídá začátku kódované zprávy;
Vydejte kód nalezené sekvence a odeberte jej od začátku kódované zprávy;
Pokud nedojde na konec 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ě. Proces dokončení slovníku je uveden v tabulce. čtyři.

Při popisu algoritmu byl záměrně vynechán popis situace, kdy je slovník zcela vyplněn. V závislosti na verzi algoritmu je možné různé chování: úplné nebo částečné vyprázdnění slovníku, zastavení vyplňová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čení 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 nedojde později. Vymazáním slovníku lze současně odstranit časté sekvence. Většina použitých implementací při vyplňování slovníku začne sledovat kompresní poměr a když klesne pod určitou úroveň, slovník se znovu sestaví. Dále zvážíme nejjednodušší implementaci, která zastaví doplňování slovníku, když je plný.

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

Dříve nalezené subsekvence jsou uloženy v poli Words a jejich kódy jsou počty subsekvencí v tomto poli.
Rovněž definujeme funkce pro vyhledávání ve slovníku a přidání do slovníku:

  1. konst
  2. MAX_DICT_LENGTH \u003d 256;
  3. funkce FindInDict (D: TDictionary; str: ShortString): integer;
  4. r: celé číslo;
  5. i: celé číslo;
  6. fl: boolean;
  7. začít
  8. r: \u003d - 1;
  9. pokud D. WordCount\u003e 0 pak
  10. začít
  11. i: \u003d D. WordCount;
  12. fl: \u003d false;
  13. while (not fl) and (i\u003e \u003d 0) do
  14. začít
  15. i: \u003d i - 1;
  16. fl: \u003d D. Slova [i] \u003d str;
  17. konec;
  18. konec;
  19. pokud tedy fl
  20. r: \u003d i;
  21. FindInDict: \u003d r;
  22. konec;
  23. procedura AddToDict (var D: TDictionary; str: ShortString);
  24. začít
  25. pokud D. WordCount< MAX_DICT_LENGTH then
  26. začít
  27. D. WordCount: \u003d D. WordCount + 1;
  28. SetLength (D. Words, D. WordCount);
  29. D. Slova [D. WordCount - 1]: \u003d 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: TDikční;
  5. i, N: byte;
  6. začít
  7. SetLength (OutMsg, length (InMsg));
  8. N: \u003d 0;
  9. InitDict (D);
  10. zatímco délka (InMsg)\u003e 0
  11. začít
  12. tmpstr: \u003d InMsg [1];
  13. while (FindInDict (D, tmpstr)\u003e \u003d 0) and (length (InMsg)\u003e length (tmpstr)) do
  14. tmpstr: \u003d tmpstr + InMsg [délka (tmpstr) + 1];
  15. pokud FindInDict (D, tmpstr)< 0 then
  16. odstranit (tmpstr, délka (tmpstr), 1);
  17. OutMsg [N]: \u003d FindInDict (D, tmpstr);
  18. N: \u003d N + 1;
  19. odstranit (InMsg, 1, délka (tmpstr));
  20. pokud délka (InMsg)\u003e 0 pak
  21. AddToDict (D, tmpstr + InMsg [1]);
  22. konec;
  23. SetLength (OutMsg, N);
  24. LZWEncode: \u003d 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í třeba přenášet vytvořený slovník, stačí, aby byl slovník během dekódování inicializován stejným způsobem jako během kódování. Poté bude slovník zcela obnoven přímo během procesu dekódování zřetězením předchozí subsekvence a aktuálního symbolu.

Jediný problém je možný v následující situaci: když je nutné dekódovat subsekvenci, která ještě není ve slovníku. Je snadné vidět, že je to možné pouze v případě, že 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, tj. začíná a končí stejným znakem. CS je však podřetězec přidaný v předchozím kroku. Uvažovaná situace je jediná, kdy je nutné dekódovat řádek, který ještě nebyl přidán. Vzhledem k výše uvedenému můžeme navrhnout následující možnost dekódování komprimovaného řetězce:

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

Mezi výhody slovníkových algoritmů patří jejich větší účinnost komprese ve srovnání s RLE. Mělo by však být zřejmé, že skutečné použití těchto algoritmů je spojeno s určitými obtížemi při implementaci.

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ů. Kódy získané pomocí algoritmu Shannon-Fano mají navíc 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 k jedné. Algoritmus pro konstrukci Shannon-Fano kódů je uveden níže:
1. Rozdělte abecedu na dvě části, jejichž celková pravděpodobnost symbolů je co nejblíže k sobě.
2. Přidejte 0 ke kódu předpony první části znaků, přidejte 1 ke kódu předpony druhé části znaků.
3. U každé části (ve které jsou alespoň dva znaky) rekurzivně proveďte kroky 1-3.
Přes svou komparativní jednoduchost není algoritmus Shannon-Fano bez nevýhod, 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í řetězec: „AAAABVGDEZH“. Odpovídající strom Shannon-Fano a kódy z něj odvozené jsou zobrazeny na obr. jeden:

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

Kódování pomocí Huffmanových stromů

Huffmanova kódovací algoritmus, vyvinutý několik let po algoritmu Shannon-Fano, má také vlastnost prefixu a navíc je prokázána minimální redundance, a 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, zatímco váha uzlu je úměrná frekvenci symbolu ve zprávě;
2. Z množiny volných uzlů jsou vybrány dva uzly s minimální hmotností a je vytvořen nový (nadřazený) uzel s váhou rovnou součtu váh vybraných uzlů;
3. Vybrané uzly jsou odstraněny z bezplatné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 ve volném seznamu není více než jeden uzel;
5. Na základě vytvořeného stromu je každému znaku abecedy přiřazen předponový kód;
6. Zpráva je zakódována do přijatých kódů.

Zvažte stejný příklad jako v případě Shannon-Fanova algoritmu. Strom Huffman a kódy získané pro zprávu „AAAABVGDEZH“ jsou zobrazeny na obr. 2:

Je snadné vypočítat, že velikost kó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 existuje v současné době mnoho možností pro Huffmanovo kódování, včetně adaptivního kódování, které nevyžaduje přenos symbolových frekvencí.
Mezi nedostatky Huffmanova algoritmu patří významná část problémy spojené se složitostí implementace. Použití skutečný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 protože váha nadřazených uzlů neustále roste, dříve či později dojde k přetečení. I přes jednoduchost algoritmu tedy jeho správná implementace může stále způsobovat určité potíže, zejména u velkých abeced.

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

Kódování pomocí secantových funkcí je algoritmus vyvinutý autory, který umožňuje získání předponových kódů. Algoritmus je založen na myšlence konstrukce stromu, jehož každý uzel obsahuje sekánovou funkci. Pro podrobnější popis algoritmu je nutné zavést několik definic.
Slovo je seřazená posloupnost m bitů (číslo m se nazývá délka slova).
Sekanční literál je dvojice typu hodnoty výboj-výboj. Například literál (4,1) znamená, že 4 bity slova musí být 1. Pokud je splněna podmínka literálu, je literál považován za pravdivý, jinak je nepravdivý.
K-bit secant je sada k literálů. Pokud jsou všechny literály pravdivé, pak je funkce secant sama o sobě pravdivá, jinak je nepravdivá.

Strom je sestaven tak, aby každý uzel rozdělil abecedu na nejbližší možné části. Na obr. 3 ukazuje příklad sekančního stromu:

Strom funkcí secant v obecném případě nezaručuje optimální kódování, ale poskytuje extrémně vysokou rychlost operace kvůli jednoduchosti operace v uzlech.

Aritmetické kódování

Aritmetické kódování je jedním z nejvíce efektivní způsoby komprese 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. Aritmetický kódovací algoritmus pak bude vypadat takto:
Vezměte jako pracovní poloviční interval)