文章目录
- 前言
- 编译环境
- 下载opencv和jpeg-turbo源码
- 编译jpeg-turbo
- 编译opencv
- 失败?那就直接调用jpeg-turbo库进行编解码
前言
opencv默认自带第三方jpeg编解码库,但其性能一般,对高性能需求的程序来说是不适合的,因此我们可以把jpeg-turbo编译进opencv里,这样opencv编解码就调用的是jpeg-turbo库了。
编解码效率对比:(尺寸3000*3000的图片)
- | 编码 | 解码 |
---|---|---|
opencv | 292ms | 124ms |
jpeg-turbo | 68ms | 80ms |
编译环境
:
系统:win10 x64
编译器:visual studio 2015
make工具:cmake 3.15.0
opencv:3.4.0
jpeg-turbo:libjpeg-turbo-master
下载opencv和jpeg-turbo源码
:
opencv:https://opencv.org/releases/page/5/
jpeg-turbo:https://gitcode.net/mirrors/libjpeg-turbo/libjpeg-turbo
编译jpeg-turbo
下载jepg-turbo源码并解压后得到libjpeg-turbo-master文件夹,在libjpeg-turbo-master根目录创建用于构建的目录build_turbo,打开cmake,填写信息如图所示:
点击finish后,会执行第一次Configuring,Configuring完后勾选WITH_JPEG8选项,CMAKE_INSTALL_PREFIX表示用编译器编译INSTALL的时候将库文件和头文件打包的目录。
再分别点击Configure和Generate按钮。此时构建好了,然后vs2015打开.sln文件,右键ALL_BUILD点击生成,生成成功后再右键INSTALL点击生成,成功后上面CMAKE_INSTALL_PREFIX指定的目录应该就有文件了(比如我生成的路径是:C:\libjpeg-turbo64),分别编译Debug和Release版本。(注意:INSTALL会覆盖上一次编译的lib和dll目录,每次INSTALL后最好新建Debug或Release目录把lib和dll文件夹放进去)
编译opencv
同理,在根目录新建build目录,同上配置cmake后执行第一次Configue,执行成功后如图所示:
接下来,点击右上角Add Entry按钮,添加JPEG_INCLUDE_DIR字段,type为PATH,Value为我们编译好的jpeg-turbo库头文件路径,然后点击OK,如图所示:
再点击Add Entry按钮,添加JPEG_LIBRARY字段,type为FILEPATH,Value为turbojpeg-static.lib静态库文件路径(包含文件名),然后点击OK,如图所示:
添加后如图所示:
将BUILD_JPEG字段勾选去掉,这一步是让其不要构建自带的jpeg库,而用我们添加的jpeg-turbo库。
WITH_JPEG字段是默认勾选上的,如果没有,请勾选上。
BUILD_opencv_world字段勾选后最后会集中编译成一个opencv_world340.dll库,方便调用。
此时都配好了,再次点击Configure,Configure完后点击Generate生成.sln文件,然后用vs打开工程,右键BUILD_ALL点击生成。接下来就是漫长的编译过程了,编译完后,再右键INSTALL生成。
失败?那就直接调用jpeg-turbo库进行编解码
下面给出封装好的编解码函数和调用方法,工程中导入头文件和库就不阐述了。
/*编码*/
void tj_compress_jpeg_to_mem(
/*IN*/BYTE *src, int width, int height, int pixelFormat, int subsamp, int quality, int flags,
/*OUT*/BYTE **dst, unsigned long *dstLen
)
{
tjhandle handle = tjInitCompress();
tjCompress2(
handle, src, width, 0/*pitch*/, height, pixelFormat,
dst, dstLen, subsamp, quality, flags
);
tjDestroy(handle);
}
/*解码*/
void tj_decompress_jpeg_from_mem(
/*IN*/BYTE *src, unsigned long srcLen, int tjPixelFormat, int flags,
/*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *jpegSubsamp, int *jpegColorspace)
{
tjhandle handle = tjInitDecompress();
tjDecompressHeader3(handle, src, srcLen, width, height, jpegSubsamp, jpegColorspace);
int components = tjPixelSize[(TJPF)tjPixelFormat]; // 1 for GRAY,3 for RGB
(*dstLen) = (*width) * (*height) * components;
BYTE *tmp_dst = tjAlloc(*dstLen);
tjDecompress2(
handle, src, srcLen,
tmp_dst, *width, 0/*pitch*/, *height, tjPixelFormat, flags
);
tjDestroy(handle);
(*dst) = tmp_dst;
}
调用方法:
//编码
cv::Mat mt= cv::imread("test.jpg");//默认三通道
BYTE* dst = NULL;
unsigned long dstLen = 0;
tj_compress_jpeg_to_mem(pic.data, pic.cols, pic.rows, TJPF::TJPF_BGR, TJSAMP::TJSAMP_411, 95, TJFLAG_FASTDCT, &dst, &dstLen);
//解码
BYTE *src = NULL;
unsigned long srcLen;
int w, h, jpegSubsamp, jpegColorspace;
tj_decompress_jpeg_from_mem(dst,dstLen,TJPF::TJPF_BGR, TJFLAG_FASTDCT,&src,&srcLen,&w,&h,&jpegSubsamp, &jpegColorspace);
cv::Mat mt2 = cv::Mat(h, w, CV_8UC3);
memcpy(mt2.data, src, srcLen);
tjFree(dst);
tjFree(src);
如果是灰度图,TJPF::TJPF_BGR改成TJPF::TJPF_GRAY, TJSAMP::TJSAMP_411改成TJSAMP_GRAY