6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenCVAdvent Calendar 2024

Day 16

OpenCVのzlib-ng連携で高速化を図る

Last updated at Posted at 2024-12-15

この記事はOpenCV Advent Calendar 2024の16日目の記事です。

はじめに

OpenCV 4.10.0以降からzlib-ng連携機能が使用できるようになりました。本記事ではOpenCVのzlib-ng連携の紹介および効果計測を行っていきます。

zlib-ngとは

zlib-ng(https://github.com/zlib-ng/zlib-ng)は、zlib(https://zlib.net/)とAPI互換を保ちつつ、モダンなCPU命令を使用した実装により高速化を図ったライブラリです。
https://github.com/zlib-ng/zlib-ngにて"ng"はnext generationを意味することが書かれています。

OpenCVにおけるzlib-ng連携の歴史

2024/12/16時点におけるOpenCVのzlib-ng連携の歴史を以下にまとめます。

  1. https://github.com/opencv/opencv/issues/22573でzlibからzlib-ngへの置き換え提案が行われました
  2. https://github.com/opencv/opencv/pull/24782でzlib-ng対応が行われました(zlib-ng 2.1.6)
  3. https://github.com/opencv/opencv/pull/26113でzlib-ngバージョンアップが行われました(zlib-ng 2.2.1)

そのため、stableバージョンの場合、OpenCV 4.10.0以降であればzlib-ng連携の機能が使用できます。また、今後リリースが計画されているOpenCV 4.11.0でzlib-ngバージョンアップが適用される見込みです。

OpenCVのzlib-ng連携有効化

OpenCVのcoreモジュールでzlib-ngを有効にする場合、CMakeオプションでWITH_ZLIB_NG=ONを指定します。WITH_ZLIB_NG=ONとしてCMakeを実行したときのメッセージ例は以下の通りです。このメッセージからzlib-ngが参照されるようになっていることがわかります。

  Media I/O: 
    ZLib-Ng:                     build (zlib ver 1.3.1.zlib-ng, zlib-ng ver 2.2.1)

さらにOpenCVのimgcodecsモジュールでもzlib-ngを有効にする場合は以下のオプションも追加します。

  • PNG
    • WITH_ZLIB_NG=ONWITH_PNG=ONBUILD_PNG=ON(libpng)
      • BUILD_PNG=ONは、opencv/3rdparty以下のlibpngがzlib-ngをリンクするため必要
    • WITH_ZLIB_NG=ONWITH_SPNG=ONBUILD_SPNG=ON(libspng)
      • BUILD_SPNG=ONは、opencv/3rdparty以下のlibspngがzlib-ngをリンクするため必要
  • TIFF
    • WITH_ZLIB_NG=ONWITH_TIFF=ONBUILD_TIFF=ON
      • BUILD_TIFF=ONは、opencv/3rdparty以下のlibtiffがzlib-ngをリンクするため必要
  • OpenEXR
    • WITH_ZLIB_NG=ONWITH_OPENEXR=ONBUILD_OPENEXR=ON
      • BUILD_OPENEXR=ONは、opencv/3rdparty以下のopenexrがzlib-ngをリンクするため必要

zlib-ng連携の仕組み

ここではOpenCVがzlibの代わりにzlib-ngとどのように連携しているかの仕組みについて解説します。

OpenCVにおけるzlib-ng格納場所

zlib-ngのソースコードはopencv/3rdparty以下(https://github.com/opencv/opencv/tree/4.10.0/3rdparty/zlib-ng)に格納されています。

zlib-ng切り替え

OpenCVでzlib、zlib-ngどちらを使うかはどのように切り替えているのでしょうか?OpenCVのhttps://github.com/opencv/opencv/blob/4.10.0/cmake/OpenCVFindLibsGrfmt.cmakeに以下の記述があります。

if(WITH_ZLIB_NG)
  ocv_clear_vars(ZLIB_LIBRARY ZLIB_LIBRARIES ZLIB_INCLUDE_DIR)
  set(ZLIB_LIBRARY zlib CACHE INTERNAL "")
  add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/zlib-ng")
  set(ZLIB_INCLUDE_DIR "${${ZLIB_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "")
  set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
  set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})

  ocv_parse_header_version(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h.in" ZLIB_VERSION)
  ocv_parse_header_version(ZLIBNG "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h.in" ZLIBNG_VERSION)

  set(HAVE_ZLIB_NG YES)

上記のコードでWITH_ZLIB_NG=ONの場合にopencv/3rdparty/zlib-ngを参照するようになっていることがわかります。冒頭で書いたようにzlib-ngはzlibとAPI互換があるため基本的にはこれだけでOKです。

効果計測

ここでは、zlib-ng対応の効果を検証するために以下の環境で処理速度の計測を行います。

計測環境、計測条件

計測環境を下表にまとめます。

名称 スペック、バージョン
CPU Intel Core i7-9800X CPU @ 3.80GHz
メモリ 32GB
OS Ubuntu 22.04 64bit
コンパイラ g++ 11.4.0
OpenCVバージョン OpenCVリポジトリの4.xブランチでzlib-ngバージョンアップ適用時点(https://github.com/opencv/opencv/commit/85923c8f3054bc52c9c30c2a8e932dbd96cc26fc
zlib 1.3.1
zlib-ng 2.2.1

本記事ではWITH_ZLIB_NG=ONWITH_ZLIB_NG=OFFそれぞれで以下の処理を実行し、処理時間を計測します。入力データは3チャンネルかつ、1080p(1920 x 1080)、4K(3840 x 2160)のデータを用います。

  • cv::imencode、cv::imdecode
    • 今回は利用ケースが多いであろうPNGのみ
  • cv::imwrite、cv::imread
    • 今回は利用ケースが多いであろうPNGのみ
  • cv::FileStorage

計測結果

cv::imencode、cv::imdecode

エンコードのコードは以下の通りです。

std::vector<int> params = std::vector<int>(2);
params[0] = cv::IMWRITE_PNG_COMPRESSION;
params[1] = 1;
std::vector<uchar> buf;
cv::imencode(".png", img, buf, params);

そして、デコードのコードは以下の通りです。

cv::Mat dst = cv::imdecode(cv::Mat(buf), cv::IMREAD_COLOR);

処理時間を下表に示します。この結果からimencodeはzlib-ngの方が大幅に高速に処理できており、imdecodeもわずかにzlib-ngの方が高速に処理できていることがわかります。

条件 処理時間(ms)
(zlib利用)
処理時間(ms)
(zlib-ng利用)
1080p(1920, 1080), imencode 136.82 88.75
4K(3840, 2160), imencode 517.71 309.792
1080p(1920, 1080), imdecode 38.33 36.90
4K(3840, 2160), imdecode 133.65 118.09

cv::imwrite、cv::imread

画像書き込みのコードは以下の通りです。

std::vector<int> params = std::vector<int>(2);
params[0] = cv::IMWRITE_PNG_COMPRESSION;
params[1] = 1;
cv::imwrite("img.png", img, params);

そして、画像読み込みのコードは以下の通りです。

cv::imread("img.png", cv::IMREAD_COLOR);

処理時間を下表に示します。この結果からimwriteはzlib-ngの方が大幅に高速に処理できており、imreadもわずかにzlib-ngの方が高速に処理できていることがわかります。

条件 処理時間(ms)
(zlib利用)
処理時間(ms)
(zlib-ng利用)
1080p(1920, 1080), imwrite 157.59 103.65
4K(3840, 2160), imwrite 607.81 385.32
1080p(1920, 1080), imread 39.43 37.82
4K(3840, 2160), imread 134.12 117.34

cv::FileStorage

https://docs.opencv.org/4.10.0/da/d56/classcv_1_1FileStorage.html#a587b4f5793a894fbe245e95cb30d6bc7

Name of the file to open or the text string to read the data from. Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz.

という説明があり、実はcv::FileStorageで圧縮形式を扱う場合にzlib、zlib-ngを使用します。
書き込みのコードは以下の通りです。

cv::FileStorage fs("img.xml.gz", cv::FileStorage::WRITE);
fs << "img" << img; 

そして、読み込みのコードは以下の通りです。

cv::FileStorage fs("img.xml.gz", cv::FileStorage::READ);
cv::Mat img;
fs["img"] >> img;

処理時間を下表に示します。この結果からwriteはzlib-ngの方が大幅に高速に処理できており、readもわずかにzlib-ngの方が高速に処理できていることがわかります。

条件 処理時間(ms)
(zlib利用)
処理時間(ms)
(zlib-ng利用)
1080p(1920, 1080), cv::FileStorage write 838.87 394.33
4K(3840, 2160), cv::FileStorage write 3100.47 1528.96
1080p(1920, 1080), cv::FileStorage read 698.78 664.40
4K(3840, 2160), cv::FileStorage read 2731.44 2595.08

おわりに

本記事ではOpenCVのzlib-ng連携の紹介および効果計測について述べました。この記事が読者のよりよいOpenCVライフに繋がれば幸いです。明日、12/17は@Kazuhitoさんの担当です、お楽しみに。

6
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?