この記事はOpenCV Advent Calendar 2022の17日目の記事(代打ち)です。
他の記事は目次にまとめられています。
TL;DR
- JPEG圧縮するときにはサンプリングに気を付けよう!
- OpenCV 4.7.0から、JPEGのサブサンプリング指定ができるようになりますよ!
自己紹介
はい、どこにでもいる普通の画像処理エンジニアでした。
今回は今年contributeしたJPEGのサンプリング指定パッチについて簡単に説明します。
「OpenCVでJPEG形式で画像を保存したら、なんか色が変だなあ?」というときにご利用ください。
どういう問題だったのか?
切っ掛けとなったissueはこちらである。
紫色の細線の色がおかしい、というissue。
JPEGのサブサンプリングの振り返り
- JPEGのサブサンプリング指定は、デフォルトが420形式である。
- 420形式だと、Y chが4x2に対して、CrCbが2x1しか含まれない
- CrCbプレーンの情報が大幅に欠落する。
もうちょっと詳しく、ただしざっくり概念をまとめていくとこうなる。まず、オリジナルのRGB画像を、4x2単位に分割する
RGB00 | RGB10 | RGB20 | RGB30 |
---|---|---|---|
RGB01 | RGB11 | RGB21 | RGB31 |
↓ RGBからYCrCb色空間に変換する
YCbCr00 | YCbCr10 | YCbCr20 | YCbCr30 |
---|---|---|---|
YCbCr01 | YCbCr11 | YCbCr21 | YCbCr31 |
この、Y,Cr,Cb Planeごとに分離する。Yが「輝度」、Cr,Cbが「赤っぽさ」「青っぽさ」である。
Y00 | Y10 | Y20 | Y30 |
---|---|---|---|
Y01 | Y11 | Y21 | Y30 |
+
Cb00 | Cb10 | Cb20 | Cb30 |
---|---|---|---|
Cb01 | Cb11 | Cb21 | Cb31 |
+
Cr00 | Cr10 | Cr20 | Cr30 |
---|---|---|---|
Cr01 | Cr11 | Cr21 | Cr31 |
人間の眼には、Yが重要、ということで、情報量削減のためCbプレーンとCrプレーンで、情報を間引く=平均を取る。
CbA = (Cb00 + Cb10 + Cb01 + Cb11) / 4 \\
CbB = (Cb20 + Cb30 + Cb21 + Cb31) / 4 \\
CrA = (Cr00 + Cr10 + Cr01 + Cr11) / 4 \\
CrB = (Cr20 + Cr30 + Cr21 + Cr31) / 4
CbA | CbB |
---|
CrA | CrB |
---|
CbA/CbB, CrA/CrBの色情報があれば、YCbCr -> RGB変換の時には「平均」を利用して、大体 同じ画像を復元できる事になる。これで情報量削減するのが「サブサンプリング」のざっくり説明となる。
CbA | (CbA) | CbB | (CbB) |
---|---|---|---|
(CbA) | (CbA) | (CbB) | (CbB) |
CrA | (CrA) | CrB | (CrB) |
---|---|---|---|
(CrA) | (CrA) | (CrB) | (CrB) |
どんな問題が起きるのか?
困ったことに、紫色(RGB(255,0,255)) の細線を描画しようとすると、青・赤の成分が周囲に滲んでしまう。その結果、元々よりもくすんだ色となり、かつ、色が無かったところにも色がのってしまう。下がサンプル画像ですが、いやもう、縮小画像の時点で「なんか色へーん」ってわかりますよね?
拡大もしてみましょう。例えば、左がSubsampling = 420(JPEGデフォルト)、右がSubsampling = 444(サンプリング指定なし)である。これくらい違う。だめだこりゃ!
OpenCV 4.7.0からJPEGのSubsampling指定ができるようになります。
「じゃあ、JPEG形式で保存すると、画像が汚くなっちゃうの・・・」と心配された方、ご安心下さい!! OpenCV 4.7.0からは、サブサンプリング指定もできますよ!
https://docs.opencv.org/4.x/d8/d6a/group__imgcodecs__flags.html#ga292d81be8d76901bff7988d18d2b42ac
https://docs.opencv.org/4.x/d8/d6a/group__imgcodecs__flags.html#ga4b97ca569a53587801257896d79656e1
「どれだけ色成分を犠牲にして、ファイルサイズを小さくするのか」を指定し放題になりました!
これで、OpenCVの後ろに何かのライブラリを繋いだりするときも、色変換によるくすみなんかを回避できるようになりますね!!
まとめ
- JPEG圧縮するときにはサンプリングに気を付けよう!
- OpenCV 4.7.0から、JPEGのサブサンプリング指定ができるようになりますよ!
それではみなさん、楽しいクリスマスイブをお過ごしくださいませ、メリークリスマス!!