データ圧縮について

by だうぴ

1.なぜデータを圧縮するのか。
データの圧縮を行う理由は、電話網などのネットワークでは使用時間に応じて課金されるので、送受信されるデータの量が少ないほど課金が少なくて済むためで、パソコン通信時代からオンラインでソフトウェア流通させるために必要なものとして発達してきました。
また、オンラインソフトウェアを流通させるためには複数のファイルを一つにまとめる機能がある方が便利なため、以上の2つの機能を持つソフトウェア(=アーカイバ)として有名なのが、「LHA」と「PKZIP」で、それぞれで圧縮したときのファイルの拡張子はlzh(何故lzhになるのかは後述します)、zipになることで知られています。

2.どのようにデータを圧縮しているのか。
(A)ランレングス符号化法
ファイルの圧縮、解凍の操作方法に関しては、lhasa特集などの初心者向けサイトにまかせることにして、実際にどのようにしてデータを圧縮しているのかについて触れていきます。
例えば、普通の紙をスキャナで読み込んだ以下のようなデータがあったとします。なお、先頭は必ず白から始まることがわかっていると仮定します。

白白白白白黒黒黒白白黒黒黒黒黒黒黒黒黒

ここで、白を1,黒を0として符号化すると

1111100011000000000    ・・・(1)

と合計19ビットの情報量が必要になります。しかし、白が5個、黒が3個、白が2個、黒が9個続いているので、「5329」と表現してあげれば情報量が少なくなるはずです。コンピュータでは2進数しか扱えないので、単純に5329を2進数にすると、10111101001となりますが、どこが切れ目かわからないのでこのままでは元に戻せません。101 11 10 1001と分ければ「5329」になりますが、10 11 110 1001と分けてしまうと「2369」になってしまいます。つまり、符号化する場合は元に戻せるような体系になっていなければなりません
ここで、以下のような符号化表を用意します。

ランレングス(連続数) 符号
1 000
2 001
3 010
4 011
5 1000
6 1010
7 1001
8 1011
9 110000
10 110001


(1)の情報を上の符号化表に従って符号化すると

1000010001110000     ・・・(1)’

となり、合計16ビットの情報量で済むので3ビット分圧縮されたことになります。
(1)’を(1)に上の表を使って戻せるか(復号できるか)どうかをやってみます。
(1)’の先頭ビットは 1 ですが、上の符号化表の符号項目に 1 はありません。先頭2ビットまで見ると、 10 ですが、やはりありません。先頭3ビットまでみると 100 ですが、やはりありません。先頭4ビットまでみると、 1000 ですが、符号項目に 1000 があり、対応するランレングス(連続数)は 5 になります。つまり最初は5ビット連続であることがわかります。
次に、5ビット目から同様のことを行うと、010 まで見た時点で、ランレングスが3になっていることがわかります。
そして、その次は同様に、001 でランレングスが2、最後が110000となるのでランレングスが9となります。
先頭は白から始まることがわかっているので、1111100011000000000 となり、元に戻すことが出来ます。

以上のように同じデータの連続数(ランレングス)に注目して圧縮する符号化法を、ランレングス符号化法といいます
ランレングス符号化法は、同じデータが連続している場合は高圧縮率が期待できますが、世の中には同じデータが連続しているということはあまりありません。使用例としては静止画フォーマットRLE形式等に利用されています。

(B)ハフマン符号化法
今度は、以下のようなデータがあったとします。

最近10日間の天気
晴れ 晴れ 曇り 晴れ 雨 晴れ 曇り 雪 晴れ 晴れ

ここで単純に、晴れ 00 、曇り 01 、雨 10 、雪 11 、として符号化すると、

00 00 01 00 10 00 01 11 00 00      ・・・(2)

と情報量は20ビットになります。このデータの場合はランレングス符号化法では同一連続データがないため、ほとんど圧縮されません。
そこで、符号化表を以下のようなものにします。

天気 晴れ 曇り
  0 10 110 111

以上の表で最初の天気を符号化すると

0 0 10 0 110 0 10 111 0 0      ・・・(2)'

となり、(2)と(2)’を比べると情報量が4ビット少なくなります。

晴れ 晴れ 曇り 晴れ 晴れ 曇り 晴れ 晴れ
00 00 01 00 10 00 01 11 00 00
0 0 10 0 110 0 10 111 0 0


以上のように、出現頻度の高いデータに短いビット数を使い、出現頻度の低いデータに長いビット数を割り当てて、全体としてデータの圧縮を行う符号化法をハフマン符号化法といいます。ハフマン符号化法は、Huffmanという人が、発明した方法のためそのように呼ばれています。また、(2)のようにデータによって符号長が変わらない場合をFLC(Fixed Length Code、可変長コード)、(2)’のようにデータによって符号長が変わる場合をVLC(Variable Length Code、可変長コード)と言います。
ハフマン符号化法は基本的な圧縮方法として、LHAPKZIPなどのアーカイバMNP5、MNP7等のプロトコルをはじめとして広い範囲で利用されています。

(C)Lempel-Ziv符号化法
ハフマン符号化法では、出現頻度を求めるのに1回、圧縮に1回、合計2回データの読み込みを行うため、処理速度が遅いという欠点があります。そこで、Abraham Lempelと、Jacob Zivの2人は、別の圧縮方法を考案しました。
Lempel-Ziv符号化法では、なるべく長い文字列が繰り返し現れるパターンを見つけだして、短い文字列に置き換えていくための辞書を作成します。
例えば、

元の単語 辞書登録名
Windows WIN
ハフマン ハフ
Lempel-Ziv LZ
ランレングス ラレ

というような感じの辞書データを作っていきます。パソコンを少々使い込んでいる人は、よく入力する長い単語に対して、短い名前で単語登録をしていると思いますが、それと同じ原理です。Lempel-Ziv符号化法では、辞書データが付加されるため、小さいデータでは逆にファイルサイズが大きくなってしまうことがあります。

LHAでは、圧縮符号化法にLempel-Ziv符号化法ハフマン符号化法を併用しています。拡張子がlzhとなっているのは、Lempel-ZivとHuffmanの頭文字から取られています

Lempel-Ziv符号化法は、LHAPKZIPなどのアーカイバ、GIF静止画フォーマット、V42.bisなどのプロトコル、といった広い範囲で利用されています。

3.エントロピーと平均符号長

ときどき、「LHAで圧縮を繰り返せば、どんどんファイルサイズが小さくなっていくのですか?」という質問を受けることがあります。この質問に対する解答は、「2度目以降は圧縮してもファイルサイズは小さくならない」ということになります。では、何故そうなるのでしょうか?

オリジナルデータには、「本来の情報」部分と「冗長部分」から構成されています。LHAによる圧縮符号化では、「冗長部分」を省いて、「本来の情報」だけを残すということを行います。以下の図に示します


 冗長部分除去による情報圧縮

「本体の情報」だけにしたときの理論上の情報量は以下の式で求められます。


ただし、Piはデータiの出現確率、Σは全ての事象の和を取ることを意味しています。このHのことをエントロピーといい、キャラクター当たりの符号長はHより小さく出来ないという限界値を意味します。

それでは、ハフマン符号化法で使った例のデータで、エントロピーを求めてみます。

晴れ 晴れ 曇り 晴れ 晴れ 曇り 晴れ 晴れ
00 00 01 00 10 00 01 11 00 00
0 0 10 0 110 0 10 111 0 0


以上のデータでは、晴れ:60%、曇り:20%、雨10%、雪10%の確率になるのでエントロピーは

H=−(0.6×log20.6+0.2×log20.2+0.1×log20.1+0.1×log20.1)=1.57

データが合計10個あるので、圧縮できる限界は
1.57×10=15.7
小数点は切り上げるので、データ全体では16ビットになります。
もし、晴れ、曇り、雨、雪がそれぞれ確率25%ずつだったとすると、キャラクター当たりの限界ビット数は2ビットになりますが、
それと比べるとかなり圧縮できることがわかります。これが冗長部分除去、すなわち圧縮の効果になります。

全体のビット数をデータ個数で割ったものを、平均符号長と呼びます。
上の例の場合、ハフマン符号化する前は、各データに2ビット固定長をを割り当てているので、平均符号長=2ビット/シンボルになります。
ハフマン符号化した場合は、16/10=1.6ビット/シンボルになります。

情報処理技術者試験(2種、1種、高度午前)を受験する予定の人は、エントロピーも出題範囲なので理解しておいて下さい


4.不可逆圧縮離散コサイン変換(DCT)

今までに述べてきたような方法で圧縮は出来ますが、エントロピーと呼ばれる圧縮限界があることがわかりました。
画像などでは、「本来の情報」だけでも大きいので、さらにデータを小さくするために「本来の情報」を削ってしまうということを行います。
「本来の情報」を削る場合は、人間の目をごまかせるような範囲で行います。そして、完全には元に戻らなくなります。
このような、不可逆圧縮を行っている例としては、JPEG静止画像フォーマットやMPEG動画像フォーマットやMP3音声フォーマットなどがあります。以上のフォーマットでは離散コサイン変換(Discrete Cosine Transform)ということを行っています。
これに対して、データを完全に元に戻すことが出来る圧縮方法を可逆圧縮といいます。

離散コサイン変換(DCT)の演算式

画素数Nx×Nyのデジタル画像情報が以下の図のように与えられたとき、DCTの演算式は以下のようになります。
DCT、逆DCTの演算式を見れば気付く人もいると思いますが、DCT、逆DCTは可逆演算です。
DCT係数の量子化を行った時点で始めて不可逆圧縮となります。


逆に、DCT係数F(u,v)が与えられたとき、画素値f(x,y)を求める逆DCTの演算式は以下のようになります





JPEG画像の符号化は以下のような手順になります。
(1)画像を8×8のブロックに分割して、1ブロックの画像を得ます。
(2)0〜255の値をレベルシフトして-128〜127に変換します。
(3)DCTによって、DCT係数を得る
(4)量子化テーブルを用いて、DCT係数を量子化、すなわちデータの省略をする。このとき、視覚に対応して周波数の高い成分(表では右下の部分)の省略を大きくする。
(5)ハフマン符号化を行い、圧縮データが得られる。

JPEGデータを元に戻す場合は、
(1)ハフマン復号化を行う。
(2)量子化テーブルを用いて、逆量子化を行う。
(3)逆DCTを行う
(4)逆レベルシフトを行う。
(5)ブロックの結合を行い、復号画像を得る。
という手順になります。
以下に例を示します。




終わりに
問い合わせは、こちらまで。