Speed-Up JPEG Encode/Decode Processing for OpenCV using libjpeg-turbo

Defoult JPEG Encoder/Decoder

OpenCV’s JPEG encoding/decoding processing has been implemented using libjpeg library.
OpenCV includes libjpeg library into 3rdparty directory as external library.
Usually, It has been static link to OpenCV.*1

*1 OpenCV includes libjpeg ver.9.

What is libjpeg-turbo?

libjpeg-turbo is library that was speed-up libjpeg library using SIMD instructions.
libjpeg-turbo will work 2-6 times faster than libjpeg.
libjpeg-turbo will work nearly same speed as Intel IPP (Integrated Performance Primitives) which is highly optimized.
In addition, libjpeg-turbo APIs have compatible with libjpeg.
Therefore, OpenCV will be able speed-up the encode/decode processing by replacing link library to libjpeg-turbo.

How to build OpenCV with libjpeg-turbo

You will need to build OpenCV from source code to incorporate libjpeg-turbo to OpenCV.

1. How to build libjpeg-turbo

  1. Install Assembler
  2. libjpeg-turbo will request NASM assembler to assemble the optimized assembly.
    You need to download and install latest NASM from following.

  3. Download Source Code
  4. You will download source code of libjpeg-turbo latest release from GitHub.

  5. Create Project using CMake
  6. You will generate libjpeg-turbo project using CMake.
    You will specify executable file path of NASM in [Ungrouped Entries]>[NASM].
    (e.g. C:/Users/UserName/AppData/Local/bin/NASM/nasm.exe)

  7. Build libjpeg-turbo
  8. You open solution that has been generated by CMake using Visual Studio.
    Then, You will build [ALL_BUILD] project with Release configuration.
    If build is successful, “jpeg-static.lib” will be generated.

  9. Install libjpeg-turbo
  10. You will build [INSTALL] project with Release configuration.
    The libjpeg-turbo necessary files will be installed in “C:\libjpeg-turbo64” (or “C:\libjpeg-turbo”).

2. How to build OpenCV with libjpeg-turbo

  1. Download Source Code
  2. You will download source code of OpenCV from GitHub.

  3. Create Project using CMake
  4. You will generate OpenCV project using CMake.
    You will following settings in CMake.

    You will add new “JPEG_INCLUDE_DIR”, “JPEG_LIBRARY” items by press [Add Entry] button.
    “JPEG_INCLUDE_DIR” item’s type is PATH, “JPEG_LIBRARY” item’s type is FILEPATH.
    You will uncheck the “BUILD_JPEG” checkbox, because it is option to use libjpeg that is included in 3rdparty directory.
    You will check the “WITH_JPEG” checkbox, because it is option to enable JPEG support in OpenCV.

    • JPEG_INCLUDE_DIR C:/libjpeg-turbo64/include (or C:/libjpeg-turbo/include)
    • JPEG_LIBRARY C:/libjpeg-turbo64/lib/jpeg-static.lib (or C:/libjpeg-turbo/lib/jpeg-static.lib)
    • BUILD_JPEG ☐(uncheck)
    • WITH_JPEG ☑(check)
  5. Build OpenCV
  6. You open solution that has been generated by CMake using Visual Studio.
    Then, You will build [ALL_BUILD] project with Debug and Release configuration.

  7. Install OpenCV
  8. You will build [INSTALL] project with Debug and Release configuration.

Performance Test

I will test how was able to speed up encoding process by replacing OpenCV JPEG-backend to libjpeg-turbo from libjpeg.
It reads lena image (opencv/samples/data/lena.jpg).
Then, It will measure processing time of encoding to JPEG format on the memory.

Test Environment

I was tested it on following environments.

  • 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

OpenCV with libjpeg-turbo is able to faster processing about 3.5 times.
I think this is reasonable result by also compared with libjpeg-turbo performance reports.
In here, I was tested encoding speed on memory using cv::imencvode().
I think that similarly to speed-up when writing file using cv::imwrite() too.
In addition, It seems that decoding process can be speeded up.

Backend Time
libjpeg v9 8.27762[ms]
libjpeg-turbo v1.4.2 2.36519[ms]

Reference


Leave a Reply

Your email address will not be published. Required fields are marked *