编译opencv精简静态库
本示例在ubuntu18.04上编译opencv4.5.1
安装依赖包
1 | sudo apt install cmake gcc gcc-c++ make |
cmake命令直接编译
opencv_highgui库在读写jpeg,png,tiff,jpeg2000图像格式时用到了第三方编解码库,可以根据图像的格式,精简选择需要开启的编译选项
在opencv根目录下创建release文件夹,打开release文件夹,之后编译产生的中文文件和最后编译结果都将存放在该目录下
1 | cmake -DBUILD_DOCS=off \ |
- -DBUILD_SHARED_LIBS=off \ # 指定编译静态库,默认编译动态库(.so,.dll)
- -DBUILD_JASPER=on \ # 编译3rdparty/libjasper项目用于jpeg2000图像编解码
- -DBUILD_JPEG=on \ # 编译3rdparty/libjpeg项目用于jpeg图像编解码
- -DBUILD_PNG=on \ # 编译3rdparty/libpng项目用于png图像编解码
- -DBUILD_TIFF=on \ # 编译3rdparty/libtiff项目用于tiff图像编解码
- -DBUILD_ZLIB=on \ # 编译3rdparty/zlib项目
1 | make |
这样编译出来的opencv只含有opencv_core,opencv_imgproc,opencv_highgui
OPENMP支持需要gcc版本大于4.6以上,否则需要将WITH_OPENMP选项关闭
使用cmake-gui进行编译
设置源代码路径和生成文件存放文件夹路径,按Configure
勾选对应的选项,多余的关闭即可
设置好后Configure ,Generate
然后到生成文件存放文件夹下,make,make install即可
提取生成的静态库和头文件
静态库路径
生成的静态库可以在/usr/local/lib和/usr/local/share/OpenCV/3rdparty/lib下找到(release文件夹下的lib以及3rdparty/lib中存在对应得库文件)
头文件可以在/usr/local/include下找到(opencv根目录的include和modules下也有对应的头文件)
头文件修改
修改
opencv2/opencv.hpp
, opencv.hpp中仍包含其他模块的头文件,将多余的头文件代码删除1
2
3
4
5
6
7
8
9
10
11
12
13
14改为
1
2
3
4
5
6移动到自定义文件下
新建了一个3rdparty文件夹存放自定义编译的一些库文件
- 将/usr/local/lib和/usr/local/share/OpenCV/3rdparty/lib下的 *.a 静态库放到\
/3rdparty/opencv/lib下 - 将/usr/local/include下的 opencv和opencv2文件夹放到\
/3rdparty/opencv/include下
- 将/usr/local/lib和/usr/local/share/OpenCV/3rdparty/lib下的 *.a 静态库放到\
##测试
本测试是在centos6.5上进行的,图像读取只对jpeg和png进行了编译,centos6.5的默认gcc版本为4.4.7,所以取消了对OPENMP的编译
DisplayImage.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using namespace cv;
int main(int argc, char** argv )
{
if ( argc != 2 ){
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
Mat image;
image = imread( argv[1], 1 );
if ( !image.data ){
printf("No image data \n");
return -1;
}
printf("Load image successful!\n");
printf("image size is: < %d x %d>\n",image.cols,image.rows);
for (int row = 0; row < 1; row++) {
uchar* data = image.ptr<uchar>(row);
for (int col = 0; col < 5; col++) {
printf("%d \t", data[col]);
}
printf("\n");
}
return 0;
}CMakeLists.txt
1
2
3
4
5
6
7
8cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
set(OPENCV_PATH /home/heroin/3rdparty/opencv)
add_executable( DisplayImage DisplayImage.cpp )
include_directories(${OPENCV_PATH}/include)
# set(OPENCV_LIBS ${OPENCV_PATH}/lib/libopencv_imgproc.a ${OPENCV_PATH}/lib/libopencv_highgui.a ${OPENCV_PATH}/lib/libopencv_core.a ${OPENCV_PATH}/lib/liblibjpeg.a ${OPENCV_PATH}/lib/liblibpng.a ${OPENCV_PATH}/lib/libzlib.a)
#target_link_libraries( DisplayImage ${OPENCV_LIBS} dl m pthread rt)
target_link_libraries( DisplayImage ${OPENCV_PATH}/lib/libopencv_imgproc.a ${OPENCV_PATH}/lib/libopencv_highgui.a ${OPENCV_PATH}/lib/libopencv_core.a ${OPENCV_PATH}/lib/liblibjpeg.a ${OPENCV_PATH}/lib/liblibpng.a ${OPENCV_PATH}/lib/libzlib.a dl m pthread rt)cmake ,make即可
cmake注意事项
链接库顺序
cmake中要注意链接的顺序,libopencv_imgproc.a,libopencv_core.a对libzlib.a存在依赖,应该把libzlib.a放在后面,libopencv_highgui.a读写图片还需要liblibjpeg.a等图像解码库的支持,liblibjpeg.a也要放在后面。
在项目开发过层中尽量让lib是垂直关系,避免循环依赖;越是底层的库,越是往后面写!例如:
1
2> g++ ... obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib) -o $@
>源文件和链接库顺序
*.cpp文件应该放在链接库前面
所以 以下方式是编译不通过的
1
2
3...
link_libraries(${OPENCV_LIBS} dl m pthread rt)
target_link_libraries( DisplayImage)应该改为如下方式
1
target_link_libraries( DisplayImage ${OPENCV_LIBS} dl m pthread rt)
或者直接不设OPENCV_LIBS变量,直接将链接写在后方.