掲示板お問い合わせランダムジャンプ

トップスペース

2009年11月21日
JPEGの仕組み簡単な解説
 だいぶ前になりますが、いつものページにAviUtlのプラグインとして「JPEG3点セット」なるものをアップしました。動画のワンシーンをワンクリックで保存できるのが欲しかったので作ったしだいです。

 AviUtl プラグイン フィルタ by うえぽん



 さてせっかくだからJPEGの仕組みについて簡単に解説してみようと思います。あくまでも「概要」なので、詳しくはどこか他のサイトを見るか本を買ってください。動画圧縮(mpegやh.264)の基礎にもなっているので、エンコの腕を上げたい人は覚えておくと良いかもしれません。

 まずは圧縮の工程を大雑把に分けると次の三段階に分かれます。

 (1) RGBをYCbCrへ変換。色差を間引く
 (2) 離散コサイン変換。量子化で間引く
 (3) ハフマン圧縮

 ポイントは扱いやすい形に変換し、それから情報を間引くということです。


(1) RGBをYCbCrへ変換。色差を間引く
 RGBとYCbCrの変換は可逆です(※精度が十分なら)。その後に色差をダウンサンプリングすることで情報量を減らします。

 YCbCrのYは輝度でCbとCrは色差です。RGB(範囲0.0〜1.0)から輝度Y(範囲0.0〜1.0)を求める計算式はこんな感じです。
 Y = 0.299*R + 0.587*G + 0.114*B
 そして色差CbとCrはそれぞれはBとRの輝度との差分となります。
 Cb = (B - Y) * 0.564
 Cr = (R - Y) * 0.713
 この係数 0.564 と 0.713 は CbとCrの範囲を -0.5から0.5 にするためのものです。

 次にダウンサンプリングですが、簡単に言うと色差の解像度を下げます。人間の目は輝度の変化には敏感だが色差には鈍感という性質を利用しています。下の画はYUV420の場合のイメージです。情報量が1/2に減っているのが分かるかと思います。
RGB→YUV420

 JPEGではYUV420以外にもYUV444やYUV422などのダウンサンプリングができます。広く使われているのはYUV420のようです。

 さてこのダウンサンプリングには欠点があります。例えば下のように背景が黒で赤い文字の画像があったとします。
ダウンサンプリング前

 これをYUV420とYUV444のjpegに変換したのが下です。(左:YUV420、右:YUV444)
YUV420のjpegYUV444のjpeg

 jpeg変換時の圧縮品質はどちらも80%です。左の画像は色がかなり変わってます。圧縮品質をいくら上げても改善しません。劣化が気になる場合はYUV444やYUV422で保存すると良いです。



(2) 離散コサイン変換。量子化で間引く
 離散コサイン変換(DCT)はそれだけでは可逆です。圧縮はそのあとの量子化で行います。

 離散コサイン変換を乱暴に説明すると、どんな離散データでも正弦波の重ね合わせで表現できるよ、というものです。jpegでは8x8ピクセルを一つのブロックとして離散コサイン変換しますが、変換によって下の画像のような64種類の波に分解されます。左上の方が低周波成分で、右下の方が高周波成分です。
wikipediaからパクってきた画像


 さてここからが量子化の話。それぞれの波の高さを記録(量子化)するわけですが、人間の目で違いが分かりにくい周波数成分は精度を下げて記録することで情報量を削減します。量子化テーブルというのはその精度の一覧表です。例えば、jpegの仕様書に書かれている量子化テーブルの推奨値はこうなってます。
[輝度]
 16, 11, 10, 16, 24, 40, 51, 61,
 12, 12, 14, 19, 26, 58, 60, 55,
 14, 13, 16, 24, 40, 57, 69, 56,
 14, 17, 22, 29, 51, 87, 80, 62,
 18, 22, 37, 56, 68,109,103, 77,
 24, 35, 55, 64, 81,104,113, 92,
 49, 64, 78, 87,103,121,120,101,
 72, 92, 95, 98,112,100,103, 99

[色差]
 17, 18, 24, 47, 99, 99, 99, 99,
 18, 21, 26, 66, 99, 99, 99, 99,
 24, 26, 56, 99, 99, 99, 99, 99,
 47, 66, 99, 99, 99, 99, 99, 99,
 99, 99, 99, 99, 99, 99, 99, 99,
 99, 99, 99, 99, 99, 99, 99, 99,
 99, 99, 99, 99, 99, 99, 99, 99,
 99, 99, 99, 99, 99, 99, 99, 99

 この各数値は、ものさしで言えば目盛りの細かさです。圧縮率を上げるなら各数値を大きくし、高品質にしたいなら各数値を小さくします。
量子化の精度について

 推奨値では左上(低周波成分)の方が小さく、右下(高周波成分)の方が大きくなってます。これは低周波成分は全体像を作るのに重要な場合が多く、高周波成分は劣化しても分かりにくいためです。
 そこで簡単な実験をしてみます。量子化テーブルを全部255にし、一番左上の数値だけ16にした場合と、一番右下の数値だけ16にした場合を比べて見ます。

[一番左上のみ16(他255)]
 一番左上のみ16(他255)
[一番右下のみ16(他255)]
 一番左上のみ16(他255)
 両者ともモザイクのような画質ですが、前者(左上のみ16にした画像)の方が全体像が分かりますね。
 ちなみに元画像はこちら(セガサターンソフト『エアーズアドベンチャー』より)。
[元画像]
 元画像(エアーズアドベンチャー)

 ところでjpegの量子化テーブルは圧縮時にカスタマイズできます。しかし多くのソフトでは推奨値を圧縮品質のパラメータで大小させているのがほとんどです。試しに適当なソフトで圧縮品質50%で保存し、JPEGsnoopなどのソフトで量子化テーブルを覗くとそのままの値が出てくると思います。



(3)ハフマン圧縮
 圧縮よりも先に展開から考えれば理解しやすいかと思います。
 a,b,c,d四つの文字を出力するとして、下の二分木を見てください。
二分木

 展開はrootからスタートします。1ビット読み込みこんで、0なら右の枝へ、1なら左の枝へというように進んでいきます。末端に到達したらそこの文字を出力します。そして再びrootへ戻り繰り返します。これが展開です。
 a, b, c, dそれぞれの出力に必要なビット長が違いますね。これがポイントです。よく使う文字ほど短いビット長を割り振ることで圧縮するというわけです。
 jpeg保存のオプションに「ハフマンテーブル最適化」というのがありますが、この二分木の最適化を行うというものです。この最適化は難しいことではないのですが、安い機器でも素早く圧縮できるように高速化(簡略化)していた名残です。

【余談】
 久々に昔のネタ帳をみたら「布団圧縮袋は意外と非可逆圧縮」と書いてあった。
 ネタ帳で一人Twitterやってたんだな。

[ 投稿者:うえぽん at 21:03 | AviUtlや画像処理 | コメント(8) | トラックバック(1) ]

この記事へのコメント
プログレッシブが保存されません
すばらしいプラグインで重宝させて頂いています
ですが一点バグ報告を
jpeg_print.cppにおいてconfig.progressiの保存読み込みの行がないため
プログレッシブのON,OFFが保存できなくなっています

以上もし次リリースがあれば修正項目に入れて頂ければと思います
投稿者: ありや at 2009-12-17 14:04:44
無題
ありやさんはじめまして。
プラグインが役立っているようで何よりです。
ご指摘のバグは後で直しておこうと思います。ありがとうございます。
投稿者: うえぽん at 2009-12-17 21:04:20
無題
ごく些細なtypo指摘ですが、0.1.5の設定欄の「AviUtl内部の色空間」で、
BT.601の横の文が「わらないなら」になっています。
投稿者: 通りすがり at 2012-01-28 18:39:59
ご指摘ありがとうございます
恥ずかしいミスですね。
次のバージョンアップで直しておきます。
投稿者: うえぽん at 2012-01-28 19:12:59
無題
「JPEGワンクリック保存」への要望はこちらでよろしいでしょうか。
普段量子化テーブルの標準で保存していて、高画質で保存したい時にはフォトショ風に
切り替えて使用しているのですが、戻し忘れたりする事があって不便さを感じています。
Ctrl等を押しながらショートカットキーを押すと自動でフォトショ風で保存される機能、もしくは
「JPEGワンクリック保存」自体を複製して複数の設定をショトカに登録できるような機能を
追加して頂ければ問題が解決すると思うのですが、ご検討願えないでしょうか?
投稿者: 無題 at 2012-02-23 08:28:44
「JPEGワンクリック保存」
>「JPEGワンクリック保存」自体を複製して複数の設定をショトカに登録できるような機能を
>追加して頂ければ問題が解決すると思うのですが、ご検討願えないでしょうか?

jpeg_print.aufを別名で複製するとフィルタ名が変わるようにすれば解決できそうなのでそうしてみようと思います。
(aviutl.iniに保存されている設定は[フィルタ名]で管理されているため、同じフィルタ名だと設定が共有されてしまうので)

ついでに恥ずかしいtypoも直します。
投稿者: うえぽん at 2012-02-23 17:32:55
無題
「RGB からYUV411へのイメージ」ですが、色差成分解像度が水平方向垂直方向とも
半分になっていますので、正しくはYUV420ではないでしょうか?
投稿者: 通りすがり at 2014-03-08 19:00:55
通りすがりさん
ご指摘ありがとうございます。
YUV411とYUV420の違いをよくわかっていませんでした。
修正をしておきます。
投稿者: うえぽん at 2014-03-09 07:16:07

この記事へのトラックバック
クリップイメージゲットの終焉
本日ClipImgGetの開発を終了しました。
気がつかなかったのですが、AviUtlの出力イメージをJPEG保存するプラグインが作られていたのです。
...
投稿者: キャプバカありやのうっちゃかちゃー at 2009-12-17 13:55:42

この記事へのトラックバックURL
http://shinshu.fm/MHz/14.30/a13493/0000304718.trackback

この記事の固定URL
http://shinshu.fm/MHz/14.30/archives/0000304718.html

記事へのコメント
 
簡単演算認証: 2 x 5 + 5 =
計算の答えを半角英数字で入力して下さい。
名前: [必須]
URL/Email:
タイトル:
コメント:
※記事・コメントなどの削除要請はこちら