画像圧縮の仕組み(離散コサイン変換の直感)
少数のコサイン波の足し算だけで、画像の明るさの並びを近似する数学
- 1
- 離散コサイン変換(DCT)は、一列に並んだ数値データ(画素の明るさなど)を、周波数の異なる複数のコサイン波の重ね合わせとして表現する変換である
- 2
- 低周波(なだらかな変化)の少数の係数だけを使っても元のデータをかなり良く近似でき、高周波の細かい成分ほど視覚的な影響が小さいため間引きやすい
- 3
- JPEG画像圧縮は、この「少ない係数で十分近似できる」性質を利用し、視覚的に重要度の低い高周波成分の係数を大胆に丸める(量子化する)ことでデータ量を大幅に削減している
なぜこれを学ぶのか? — 現実社会とテクノロジーでの価値
なぜ生まれたのか?
離散コサイン変換(DCT)は、一列に並んだ数値データ(画素の明るさなど)を、周波数の異なる複数のコサイン波の重ね合わせとして表現する変換である
身につく武器・思考力
低周波(なだらかな変化)の少数の係数だけを使っても元のデータをかなり良く近似でき、高周波の細かい成分ほど視覚的な影響が小さいため間引きやすい
実社会・ITでの活躍現場
- •JPEG画像圧縮における8×8ブロックDCTと量子化
- •ITシステム・アルゴリズム実装における論理設計
- •データ分析やシミュレーションにおける数理モデリング
Layer 1 — 直感・シミュレーター
上部のスライダーで8個の「画素の明るさ」を自由に調整できる(初期値はサンプル画像の1行分を模したデータ)。下の「使用する係数の数 N」スライダーを 1 から 8 まで動かすと、少数のコサイン基底関数の重ね合わせ(オレンジの近似曲線)が、元のデータ(グレーの棒グラフ)に少しずつ近づいていく様子と、その誤差(RMSE)が減っていく様子を確認できる。
↑ グレーの棒グラフが元の画素データ、オレンジの折れ線が「上位 N 個のコサイン係数だけ」で再構成した近似データです。N を減らすほど保存するデータ量は減りますが誤差(RMSE)は増え、JPEG圧縮はこのトレードオフを利用して視覚的に気づきにくい高周波成分から間引いています。
DCTを用いた画像圧縮において、係数の数 N を増やしていくと何が起こるか?
Layer 2 — 定義・受験・証明
定義
長さ の実数列 (画素の明るさの並びなど)に対し、離散コサイン変換(DCT-II)は次式で周波数成分の係数 を求める変換である。
逆変換(IDCT)により、係数 から元の信号を「異なる周波数のコサイン波の重ね合わせ」として再構成できる。
は信号の平均的な明るさ(直流成分, DC)、 が大きいほど細かく振動する高周波成分(交流成分, AC)を表す。
公式・数理モデル
証明・導出
DCTが「少数の係数でよく近似できる」理由の直感的説明: コサイン関数の集合 は、離散信号の空間において互いに直交する基底(直交基底)をなす。すなわち
これはフーリエ級数の直交性()の離散版である。直交基底であるがゆえに、任意の係数 は他の係数と独立に、元の信号との「内積」だけで一意に決定できる。
自然画像・音声などの現実のデータは、隣接する値同士が滑らかに変化する(急激なノイズが少ない)傾向を持つ。滑らかな信号は低周波成分( が小さいコサイン波)への射影が大きく、高周波成分( が大きいコサイン波)への射影は相対的に小さくなる。 したがって係数 の絶対値は一般に が大きくなるほど急速に小さくなる傾向を持ち、上位のごく少数の だけを残して他を 0 とみなしても、逆変換の和 の値は元の信号に近い値へ収束する。これがDCT係数を間引く(圧縮する)ことの数学的根拠である。
押さえておきたいポイント
- DCTはフーリエ変換の一種であり、実数のみを扱い信号を偶関数拡張することで、複素数(虚部)を使わずに済む点が画像・音声圧縮での採用理由
- JPEGでは画像を8×8ピクセルのブロックに分割し、各ブロックに2次元DCTを適用したのち、人間の視覚が鈍感な高周波成分ほど粗く量子化(丸め)することでデータを削減する
- 係数を大きい順(低周波から)に並べて必要な分だけ保存する考え方は「エネルギー圧縮(energy compaction)」と呼ばれ、DCT・フーリエ変換・特異値分解(SVD)に共通する圧縮の基本原理
- 近似誤差は通常、二乗平均平方根誤差(RMSE) で評価され、使用する係数 の数とトレードオフの関係にある
本トピックの内容・数理モデルは、文部科学省学習指導要領(算数・数学・情報)および国際標準カリキュラムに準拠し、エンジニアリング現場の実装事例と照らし合わせてMath World Lab編集部により検証・作成されています。
Layer 3 — 工学応用・現場実装
JPEG画像圧縮における8×8ブロックDCTと量子化
画像を8×8ピクセルのブロックに分割し、各ブロックに離散コサイン変換(DCT)を適用して周波数成分に変換したのち、視覚的に重要度の低い高周波成分を粗く量子化してデータ量を削減する、JPEG圧縮の中核処理を簡略化したTypeScript実装。
1// 1次元の離散コサイン変換(DCT-II): 信号を周波数係数に変換2function dct1D(signal: number[]): number[] {3 const N = signal.length;4 const coefficients: number[] = new Array(N).fill(0);56 for (let k = 0; k < N; k++) {7 let sum = 0;8 for (let n = 0; n < N; n++) {9 sum += signal[n] * Math.cos((Math.PI / N) * (n + 0.5) * k);10 }11 coefficients[k] = sum;12 }13 return coefficients;14}1516// 逆離散コサイン変換: 上位 M 個の係数だけを使って信号を近似復元17function idct1DApprox(coefficients: number[], useCount: number): number[] {18 const N = coefficients.length;19 const reconstructed: number[] = new Array(N).fill(0);2021 for (let n = 0; n < N; n++) {22 let sum = coefficients[0] / 2; // DC成分(平均値)23 for (let k = 1; k < useCount; k++) {24 sum += coefficients[k] * Math.cos((Math.PI / N) * (n + 0.5) * k);25 }26 reconstructed[n] = (2 / N) * sum;27 }28 return reconstructed;29}3031// JPEG風の量子化: 高周波成分ほど粗く丸めてデータ量を削減32function quantize(coefficients: number[], quantizationTable: number[]): number[] {33 return coefficients.map((c, i) => Math.round(c / quantizationTable[i]));34}3536// 例: 8画素分の明るさデータを圧縮してみる37const pixelRow = [52, 55, 61, 66, 70, 61, 64, 73];38const dctCoeffs = dct1D(pixelRow);3940// 上位4係数だけで再構成(圧縮率50%相当)41const approx = idct1DApprox(dctCoeffs, 4);42console.log("元のデータ:", pixelRow);43console.log("4係数での近似:", approx.map((v) => Math.round(v)));
次に学ぶならコレ!おすすめトピック
この単元と深い繋がりを持つ、あわせて学ぶと理解が深まるおすすめ単元