お絵描き研究室:JPEG(原理編2)

JPEG 圧縮の根幹である DCT と量子化について解説しています。

4. DCT

 前章で解説した YCbCr 色空間とダウンサンプリングは圧縮率を稼ぐための重要なテクニックですが、JPEG における圧縮の本質と直接の関係はありません。JPEG 圧縮に使われている最も重要な技術が、ここで解説する DCT(Discrate Cosine Transform;離散コサイン変換)です。
 DCT はフーリエ変換の一種です。フーリエ変換とは任意の波形を有限個の正弦波を合成した式に変換する操作ですが、DCT は (N x N) の二次元行列に数学的操作を施し、(N x N) の周波数成分行列に展開するものです。入力行列を pixel(N, N), 出力行列を dct(N, N) とすると、DCT 変換は次のように表現されます。

DCT basic(5.0K)
式4−1 DCT 基本公式

 あ…ここで引かないでくださいいぃ(^_^;)。式4−1は一見難しそうですが、原理は確かに難しいです(ぉぃぉぃ)。でも、計算そのものは掛け算と足し算の連続なのでそれほど複雑ではないんですよ。原理や導入過程は専門書に任せて、ここでは結果だけ述べましょう。
 ちょっとわかりにくいと思うので、N=8 の場合について周波数成分のグラフを示します。右に示してある表は対応するコサイン値の一覧です。
Cos table 8x8(9.2K)
x=0x=1x=2x=3x=4x=5x=6x=7
i=0 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
i=1 0.981 0.831 0.556 0.195-0.195-0.556-0.831-0.981
i=2 0.924 0.383-0.383-0.924-0.924-0.383 0.383 0.924
i=3 0.831-0.195-0.981-0.556 0.556 0.981 0.195-0.831
i=4 0.707-0.707-0.707 0.707 0.707-0.707-0.707 0.707
i=5 0.556-0.981 0.195 0.831-0.831-0.195 0.981-0.556
i=6 0.383-0.924 0.924-0.383-0.383 0.924-0.924 0.383
i=7 0.195-0.556 0.831-0.981 0.981-0.831 0.556-0.195

図/表4−1 周波数成分とコサイン値

 表4−1のコサインテーブルを ct(x,i) とすると、式2のΣ{ }の内側は

pixel(x, y) * ct(x, i) * ct(y, j)

 と書き換えることができます。そして表4−1を見るとコサイン値がすべて左右対称性をもち、i=0 つまり DC 成分以外は左右の波形が打ち消し合っていることがわかりますね?これが DCT において重要な意味を持つのです。もし入力のピクセル行列が全て同じ値なら X 方向と Y 方向は全て打ち消し合い、DC 成分 dct(0,0) だけに意味のある値が残ります。ピクセル行列に変動のあった場合は、変動の幅に応じて dct(i,j) の値が決定します。これがすなわち、「周波数成分を抽出する」という操作に他ならないのです。

 DCT 行列から元の行列を再現するには、逆 DCT 変換という操作を行います。逆 DCT 変換は次の式で表わされます。
Reverse DCT(4.1K)
式4−2 逆 DCT 基本公式

 式4−1とよく似ていますが、x,y と i,j の関係が逆転していることに注意してください。コサインの式は同じですから表4−1に示されたコサイン行列はそのまま使えます。ですがΣの値が (x,y) から (i,j) に変っているので、DCT 変換時は表を横に足していった(空間軸 (x or y) に沿う)のに対し、逆 DCT 変換時は縦に足してゆく(周波数軸 (i or j) に沿う)こともわかります。
 本当に DCT が難しいのは実はここからで、どうしてこれで波形←→周波数変換ができるのかという数学的証明ですが、これは私にはわかりません(断言)!どうしても理解したい人は、その筋の解説書を読んでください(^_^;)。少なくともここで理解しておいていただきたいのは、DCT 変換によって出力された行列が、もとのピクセル行列の変化率を周波数成分ごとにあらわしたものだ、ということです。これが後の量子化・圧縮プロセスと失われる情報との関連を理解する鍵になりますので…。


5. 量子化

 ここまでの操作を復習しましょう。まず、画像を Y, Cb, Cr に分離します。必要に応じてダウンサンプリングを施したあと、画像を 8x8 のブロックごとに区切り DCT 操作をかけます。DCT 係数がどんな分布になるのか、例として彩華の右目のあたりに DCT 操作を行った結果を表5−1に示します。表を見やすくするため、DCT 係数は小数点以下一桁に丸めてあります。

表5−1 ピクセル値と DCT 係数

原画像(8x8)ピクセル値DCT 係数
0.2K
236237176107163158108238
236197059191255255171137
238078072050231255255145
203054178048153255255253
131040090029113255255254
239039044043150255255251
237123016055232255255247
237238204174229219202238
1406.4 -244.8 212.9 291.6 29.4 -29.2 85.1 60.2
-30.5 107.5 -52.0 -9.7 3.4 -23.2 -5.8 -17.1
119.4 207.3 -48.0 -62.4 56.6 -107.3 -86.9 -60.3
-80.6 -45.5 83.6 -28.9 19.0 -13.2 25.0 -35.1
26.1 42.3 20.2 -184.2 -58.9 -23.0 67.3 10.7
-9.5 -23.3 70.6 5.1 3.5 -10.2 32.1 56.9
-12.0 22.9 32.3 -16.3 -8.1 22.1 32.5 39.5
-52.1 -37.9 11.0 27.3 -17.2 -19.3 -25.2 13.6

 さて、DCT 変換を行っただけでは、まだ「不可逆」でもないし圧縮したことにもなりません。もとの画素行列と DCT 係数行列に含まれる情報量は、数学的に見れば同じです(コンピュータ上では桁落誤差による欠落が発生しますが)。ここからどうやって情報を間引き圧縮するか、ここからが JPEG の本領発揮です。

 JPEG では DCT 行列に対して「量子化(Quantization)」という処理を行います。DCT 行列 dct(i,j) に対して量子化パラメータ行列 q(i,j) を用意し、qd(i,j)=round(dct(i,j)/q(i,j)) という式を用いて量子化行列 qd(i,j) を求めます(round() は整数丸め処理)。q の値を小さく取れば欠落情報は増えますが圧縮率が上がり、q の値を大きく取れば圧縮率は下がりますが情報の欠落は押さえることができます。q(i,j)=1 とすれば画質は最高になりますが、それでも小数点以下の情報は切り捨てられるため、何らかの欠落が発生することに注意してください。JPEG の画質をどんなに高く設定しても、保存時に情報が失われる(画質劣化が起きる)理由の一つがここにもあります。
 JPEG では量子化パラメータ(Q 行列)の内容について 8bit(0〜255) という以外特に規定はしておらず、画像フォーマット中に圧縮時に使用した Q 行列を埋め込むことを規定しています。つまりどんな Q 行列で圧縮するかはファイル生成時に任意に選択でき、画像再生時には圧縮に用いた Q 行列をファイルから読み取って使用する訳です。
 それでは、試しに適当な Q 行列を見繕って上のデータを量子化してみましょう。表5−1に示した DCT 係数に対し、量子化と逆量子化を行った結果を表5−2に示します。

表5−2 量子化と逆量子化

量子化行列(Q)量子化した DCT 係数(QD)再生した DCT 係数
1611101624405161
1212141926586055
1413162440576956
1417222951878062
182237566810910377
243555648110411392
49647887103121120101
7292959811210010399
88-2121181021
-29-300000
916-2-21-100
-5-2400000
121-20010
00100001
00000000
00000000
1408-23121028824010261
-24108-4200000
126208-32-4840-5700
-70-348800000
184437-112001030
0055000092
00000000
00000000

 かなりスカスカになってしまいましたが、大丈夫でしょうか?それではこの再生 DCT 係数をもとに逆 DCT 変換して画像を再生してみましょう。表5−3がその結果です。

表5−3 画像の再生

再生ピクセル値再生画像(8x8)原画像(8x8)実サイズでの比較
25518520493170171136208
23217196155216253180142
20711285106228255244159
1975512846157235249240
163507162106255234255
186771440163251255232
2451288954223224255232
255184202168210255171251
0.2K 0.2K
0.2K0.2K

 かなり荒れてはいますが、画像は充分識別可能です。しかも画像を実サイズで見れば、細かなノイズはほとんど目立ちません。表5−2のスカスカな量子化 DCT 行列からこの画像が再生できるとは驚きですね。

 実際の JPEG エンコーダでは、指定した圧縮率に従って Q 行列を生成します。圧縮率を下げれば全体的に小さな値の Q 行列(切り捨てられる情報が少ない)が生成され、圧縮率を上げれば大きな値の Q 行列(多くの情報を切り捨てる)が生成されます。また JPEG カラー画像の場合、Y と Cb・Cr に対する Q 行列は異なるものが用いられます。
 一般的に Q 行列は左上から右下に向かって大きくなってゆく系列…すなわち低周波成分を保存し高周波成分を切り捨てるよう生成するのが普通です。これが画質にどう反映するか直感的には理解しにくいのですが、
 という傾向があります。コントラストの低下は AC 成分の切り捨てによりブロック内における DC 成分の影響力が高まるためで、画像全体で見ると 8x8 のブロック単位で平均値のバラツキが顕著になります。これを俗に「ブロックノイズ」と呼び、原画に微妙なグラディエーションがかかっていた場合などに目立ちます。

 なお、ここで実験に使った DCT テストプログラム DCTTEST.LZHダウンロードの部屋に公開してありますので、再実験・追実験してみたい方は使ってみてください。

[JPEG(原理編3)]へ続く…

[研究室] [目次]
Copyright by 'Crazy' Y.Sasaki
Web Hostingweb hostingdedicated serversSSL Certificatedomain namesweb hosting