OpenCVで画像をPNGファイル、すなわち可逆な形式で圧縮し、ファイルで出力することなくデータを取得したいとき、 cv::imencode
というエンコード関数を使う。原理的には以下のように記述する。(そのままでは動かないよ)
vector<int> params = vector<int>(2); params[0] = CV_IMWRITE_PNG_COMPRESSION; params[1] = 3; //level std::vector<uchar> buf; cv::imencode(".png", img, buf, params);
ここで、paramsの中身について色々と調べてみた。一種の使い方でもある。以下、CV_IMWRITE_PNG_
は略す。
params[0] | params[1] | 説明 |
---|---|---|
COMPRESSION=16 | 0-9 | 圧縮する。レベルは0-9まで可変 |
STRATEGY=17 | STRATEGY_DEFAULT=0 | ノーマルデータ |
STRATEGY_FILTERED=1 | フィルターされた? | |
STRATEGY_HUFFMAN_ONLY=2 | ハフマン符号化 | |
STRATEGY_RLE=3 | 一致距離を1つに制限 | |
STRATEGY_FIXED=4 | 単純なデコーダーが可能になる? | |
BILEVEL=18 | 0 | 2値化=Bilevelなし |
0以外 | 2値化=Bilevelあり |
COMPRESSION
では、ストラテジーは STRATEGY_RLE
が使われ、圧縮は必ず行われる。
STRATEGY
か BILEVEL
を使うと、圧縮レベルは内部的に-1
がアサインされ、圧縮されない。
paramsを与えない場合、STRATEGY
のSTRATEGY_RLE
と同じになる。
画像とビデオの読み込みと書き込み — opencv v2.1 documentation
利用可能な上記のテーブルのパラメータについて、圧縮後のデータサイズと処理時間を測定してみた。圧縮レベルは0-3のみ試した。 条件は、ピクセルサイズは2048×1088で、Sizeは出力ファイルサイズ[byte]、Timeは320回の平均の処理時間[msec]である。
2値画像
輝度値、すなわち要素の値が0または1の二値画像(元は原子核乾板の顕微鏡画像)に対して行った。
params[0] | params[1] | Size | Time |
---|---|---|---|
16 | 0 | 118,938 | 26.3 |
16 | 1 | 49,204 | 24.5 |
16 | 2 | 49,204 | 23.8 |
16 | 3 | 49,204 | 23.6 |
17 | 0 | 95,730 | 8.35 |
17 | 1 | 95,730 | 8.77 |
17 | 2 | 290,162 | 18.2 |
17 | 3 | 61,402 | 7.43 |
17 | 4 | 115,524 | 8.29 |
18 | 0 | 61,402 | 7.72 |
18 | 1 | 64,694 | 6.44 |
bmp | bmp | 2,229,302 | 1.17 |
Timeが3倍変わるのはおいしくないので、 CV_IMWRITE_PNG_STRATEGY
の CV_IMWRITE_PNG_STRATEGY_RLE
あたりがバランスが良いだろうか。
通常のモノクロ画像
輝度値、すなわち要素の値が0から255までの256階調のモノクロ画像(原子核乾板の顕微鏡画像)に対して行った。
params[0] | params[1] | Size | Time |
---|---|---|---|
16 | 0 | 2,233,319 | 48.8 |
16 | 1 | 1,141,548 | 53.0 |
16 | 2 | 1,141,548 | 52.4 |
16 | 3 | 1,141,548 | 53.4 |
17 | 0 | 1,371,852 | 47.2 |
17 | 1 | 1,371,852 | 47.5 |
17 | 2 | 1,212,549 | 25.1 |
17 | 3 | 1,212,854 | 27.8 |
17 | 4 | 1,925,222 | 49.6 |
18 | 0 | 1,212,854 | 27.2 |
18 | 1 | エラー | エラー |
bmp | bmp | 2,229,302 | 1.03 |
CV_IMWRITE_PNG_STRATEGY
の CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY
あたりがバランスが良いだろうか。
カラー画像は用途外なので試していない。
乱数で生成したモノクロ画像
ピクセルサイズ2048×1088の画像に、全てのピクセルに乱数で適当な輝度値を与えた。
params[0] | params[1] | Size | Time |
---|---|---|---|
16 | 0 | 2,233,324 | 49.1 |
16 | 1 | 2,233,324 | 52.3 |
16 | 2 | 2,233,324 | 52.6 |
16 | 3 | 2,233,324 | 53.5 |
17 | 0 | 2,233,319 | 70.6 |
17 | 1 | 2,233,319 | 67.8 |
17 | 2 | 2,233,324 | 24.3 |
17 | 3 | 2,233,324 | 27.6 |
17 | 4 | 2,233,319 | 76.1 |
18 | 0 | 2,233,324 | 26.1 |
18 | 1 | エラー | エラー |
bmp | bmp | 2,229,302 | 1.17 |
ランダムな輝度値の画像は、想像通りほぼ圧縮されていない。こういうケースでは、bmpをそのまま出力するべきだろう。
パラメータ名の変更
OpenCV3系列から、 CV_IMWRITE_PNG_STRATEGY_DEFAULT
等のグローバル変数は、名前空間 cv内の変数に変わっています。なので、以下のパラメータ名を使ってください。
cv::IMWRITE_PNG_COMPRESSION cv::IMWRITE_PNG_STRATEGY cv::IMWRITE_PNG_BILEVEL cv::IMWRITE_PNG_STRATEGY_DEFAULT cv::IMWRITE_PNG_STRATEGY_FILTERED cv::IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY cv::IMWRITE_PNG_STRATEGY_RLE cv::IMWRITE_PNG_STRATEGY_FIXED