このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
離散コサイン変換
DCT 定義
離散コサイン変換 (DCT) は、さまざまな大きさと周波数からなる正弦波の和として、イメージを表現します。関数 dct2
は、イメージの 2 次元離散コサイン変換 (DCT) を計算します。DCT は、標準のイメージについて、視覚的に重要な情報のほとんどが、DCT の数個の係数に集中しているという性質をもっています。このため、DCT はイメージ圧縮の用途にしばしば使用されます。たとえば、DCT は、JPEG として知られている国際標準の非可逆イメージ圧縮アルゴリズムで中心的な機能を果たしています (この名前は、この標準を策定したワーキング グループの名前、Joint Photographic Experts Group に因んで付けられています)。
M 行 N 列の行列 A
の 2 次元 DCT は、次のように定義されます。
Bpq の値は A
の "DCT 係数" と呼ばれています (MATLAB® の行列インデックスは、0 からでなく 1 から始まります。このため、MATLAB の行列の要素 A(1,1)
および B(1,1)
は、数学上の量としては A00 および B00 に対応します)。
DCT は、逆変換も可能で、次の式で表せます。
逆 DCT 方程式は、任意の M 行 N 列の行列 A
が、
形式の関数 MN の和として記述できることを意味するものとして解釈できます。
これらの関数は、DCT の "基本関数" と呼ばれます。このため、DCT 係数 Bpq は、各基底関数に適用された "重み" と見なすことができます。8 行 8 列の行列に対して、64 個の基本関数が、このイメージにより示されます。
8 行 8 列の行列の 64 個の基本関数
水平周波数は左から右方向へ増加し、垂直周波数は上から下へ増加します。左上の定数値基底関数は、"DC 基底関数" と呼ばれ、対応する DCT 係数 B00 は、多くの場合 "DC 係数" と呼ばれます。
DCT 変換行列
Image Processing Toolbox™ ソフトウェアを使用して DCT を計算する方法は 2 つあります。最初の方法は、関数 dct2
を使用します。dct2
は、FFT ベースのアルゴリズムを使用して、大きな入力を高速で処理できます。2 番目の方法は、DCT "変換行列" を使う方法です。この行列は、関数 dctmtx
から出力され、小さい正方行列、たとえば、8 行 8 列や 16 行 16 列の行列に対しては、非常に効率的なものです。M 行 M 列の変換行列 T
は、次のように表すことができます。
M 行 M 列の行列 A
に対して、T*A
は、A
の各列の 1 次元の DCT を各列に含む M 行 M 列の行列になります。A
の 2 次元の DCT は、B=T*A*T'
として計算できます。T
が実数直交行列なので、その逆はその転置と同じものになります。そのため、B
の 2 次元逆 DCT は、T'*B*T
で与えられます。
離散コサイン変換を使用したイメージ変換
この例では、離散コサイン変換 (DCT) を使用してイメージを圧縮する方法を説明します。この例は、入力イメージの 8 行 8 列のブロックの 2 次元 DCT を計算し、各ブロックにある 64 の DCT 係数のうち 10 個以外のすべてを 0 に置き換えます。そして、各ブロックの 2 次元逆 DCT を使用して、イメージを再構成します。この例は変換行列の計算法を使用しています。
DCT は JPEG イメージ圧縮アルゴリズムで使用されます。入力イメージは 8 行 8 列または 16 行 16 列のブロックに分割され、各ブロックの 2 次元 DCT が計算されます。DCT 係数は、続いて量子化、暗号化されて送信されます。JPEG レシーバ (または、JPEG ファイル リーダー) は、量子化した DCT 係数を復号し、各ブロックの 2 次元逆 DCT を計算し、その結果を集めて 1 つのイメージを作成します。一般的なイメージでは、DCT 係数の多くは、ほとんどゼロに近い値になります。これらの係数は再構成後のイメージの質に大きな影響を与えないので、切り捨てることができます。
イメージをワークスペースに読み取って double
クラスに変換します。
I = imread('cameraman.tif');
I = im2double(I);
イメージ内にある 8 行 8 列のブロックの 2 次元 DCT を計算します。関数 dctmtx
は N 行 N 列の DCT 変換行列を返します。
T = dctmtx(8); dct = @(block_struct) T * block_struct.data * T'; B = blockproc(I,[8 8],dct);
各ブロックにある 64 の DCT 係数のうち 10 個以外のすべてを切り捨てます。
mask = [1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]; B2 = blockproc(B,[8 8],@(block_struct) mask .* block_struct.data);
各ブロックの 2 次元逆 DCT を使用してイメージを再構成します。
invdct = @(block_struct) T' * block_struct.data * T; I2 = blockproc(B2,[8 8],invdct);
元のイメージと再構成後のイメージを左右に並べて表示します。再構成イメージに質的な低下が見られますが、DCT 係数の約 85% を切り捨てたにもかかわらず、はっきりとイメージを認識できます。
imshow(I)
figure imshow(I2)