Defoult JPEG Encoder/Decoder
OpenCVのJPEGのエンコード/デコード処理はlibjpegを利用して実装されています。
3rdpartyフォルダに外部ライブラリとしてlibjpegを含んでおり、通常このlibjpegをビルドして静的リンクしています。*1
*1 OpenCV 3.1ではlibjpeg ver.9が含まれています。
What is libjpeg-turbo?
libjpeg-turboは、libjpegの内部をSIMD命令で高速化したライブラリです。
通常のlibjpegに比べ2-6倍高速に動作、高度に最適化されているIntel IPP (Integrated Performance Primitives)ともほぼ同等の速度で動作します。
libjpeg-turboのAPIはlibjpeg互換のため、リンクするライブラリをlibjpeg-turboに差し替えるだけで、エンコード/デコード処理の高速化が狙えます。
How to build OpenCV with libjpeg-turbo
OpenCVにlibjpeg-turboを組み込むにはソースコードからビルドする必要があります。
1. How to build libjpeg-turbo
- アセンブラをインストールする
- ソースコードをダウンロードする
- libjpeg-turboのプロジェクトを生成する
- libjpeg-turboをビルドする
- libjpeg-turboをインストールする
libjpeg-turboは最適化されたアセンブリをアセンブルするためにNASMアセンブラを要求します。
以下から最新のNASMをダウンロード、インストールします。
GitHubからlibjpeg-turboの最新リリースのソースコードをダウンロードします。
CMakeでlibjpeg-turboのプロジェクトを生成します。
[Ungrouped Entries]>[NASM]にNASMの実行ファイルのパスを指定します。
(e.g. C:/Users/UserName/AppData/Local/bin/NASM/nasm.exe)
CMakeで生成されたソリューションをVisual Studioで開き、[ALL_BUILD]プロジェクトをReleaseビルドします。
ビルドが成功すると「jpeg-static.lib」が生成されます。
[INSTALL]プロジェクトをビルドします。
「C:/libjpeg-turbo64 (または、C:/libjpeg-turbo)」に必要なファイルがインストールされます。
2. How to build OpenCV with libjpeg-turbo
- ソースコードをダウンロードする
- OpenCVのプロジェクトを生成する
- JPEG_INCLUDE_DIR C:/libjpeg-turbo64/include (または、C:/libjpeg-turbo/include)
- JPEG_LIBRARY C:/libjpeg-turbo64/lib/jpeg-static.lib (または、C:/libjpeg-turbo/lib/jpeg-static.lib)
- BUILD_JPEG ☐(uncheck)
- WITH_JPEG ☑(check)
- OpenCVをビルドする
- OpenCVをインストールする
GitHubからOpenCVのソースコードをダウンロードします。
CMakeでOpenCVのプロジェクトを生成します。
CMakeでは以下の設定をします。
「JPEG_INCLUDE_DIR」「JPEG_LIBRARY」の項目は[Add Entry]ボタンを押して新規に追加します。「JPEG_INCLUDE_DIR」のタイプはPATH、「JPEG_LIBRARY」のタイプはFILEPATHです。
「BUILD_JPEG」は3rdpartyに含まれるlibjpegをビルドして利用するオプションのため、ここではチェックを外します。
「WITH_JPEG」はJPEGのサポートを有効にするオプションのため、チェックを入れます。
CMakeで生成されたソリューションをVisual Studioで開き、[ALL_BUILD]プロジェクトをDebug、Releaseビルドします。
[INSTALL]プロジェクトをビルドします。
Performance Test
OpenCVのJPEGバックエンドをlibjpegからlibjpeg-turboに差し替えることで、どれくらい高速化できるのかテストします。
lena(opencv\samples\data\lena.jpg)の画像を読み込み、メモリ上でJPEG形式にエンコードしたときの1枚あたりの処理速度を計測します。
Test Environment
以下の環境でテストしました。
- Intel Core i7 4790 (3.60GHz)
- DDR3-1600(PC3-12800) SDRAM (4GB*4 Dual-Channel)
- Visual Studio 2015 (x64)
- OpenCV 3.1.0
- libjpeg-turbo 1.4.2
Test Code
#include <iostream> #include <vector> #include <opencv2/opencv.hpp> // opencv-3.1.0/samples/gpu #include "tick_meter.hpp" #define TEST_COUNT 1000 int main( int argc, char *argv[] ) { // Build Information std::cout << cv::getBuildInformation() << std::endl; // Read Image (opencv\samples\data\lena.jpg) cv::Mat img = cv::imread( "lena.jpg", cv::IMREAD_UNCHANGED ); if( img.empty() ){ return -1; } // Destination Buffer and JPEG Encode Parameter std::vector<uchar> buf( img.rows * img.cols ); std::vector<int> params = { cv::IMWRITE_JPEG_QUALITY, 95 }; // Timer TickMeter tm; // Test for( int i = 0; i < TEST_COUNT; i++ ){ tm.start(); cv::imencode( ".jpg", img, buf, params ); tm.stop(); } std::cout << tm.getTimeMilli() / tm.getCounter() << "[ms]" << std::endl; return 0; }
Test Result
libjpeg-turboを組み込んだOpenCVはだいたい3.5倍高速に処理できています。
これは、libjpeg-turboのパフォーマンスレポートからみても妥当な結果だと思います。
今回はcv::imencode()でメモリ上で処理しましたが、cv::imwrite()でファイルに書き出すときも同様に高速化が期待できます。
また、デコード処理も高速化できると思われます。
Backend | Time |
---|---|
libjpeg v9 | 8.27762[ms] |
libjpeg-turbo v1.4.2 | 2.36519[ms] |
Reference
- libjpeg-turbo
- OpenCV – JPEGエンコード・デコード | 福嶋研究室
- OpenCVのJPEG読み書きにlibjpeg turboを使う | dandelion’s laboratory