编译opencv4.5.1精简静态库

编译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
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
cmake -DBUILD_DOCS=off \
-DBUILD_SHARED_LIBS=off \
-DBUILD_FAT_JAVA_LIB=off \
-DBUILD_TESTS=off \
-DBUILD_TIFF=on \
-DBUILD_JASPER=on \
-DBUILD_JPEG=on \
-DBUILD_PNG=on \
-DBUILD_ZLIB=on \
-DBUILD_OPENEXR=off \
-DBUILD_opencv_apps=off \
-DBUILD_opencv_calib3d=off \
-DBUILD_opencv_contrib=off \
-DBUILD_opencv_features2d=off \
-DBUILD_opencv_flann=off \
-DBUILD_opencv_gpu=off \
-DBUILD_opencv_java=off \
-DBUILD_opencv_legacy=off \
-DBUILD_opencv_ml=off \
-DBUILD_opencv_nonfree=off \
-DBUILD_opencv_objdetect=off \
-DBUILD_opencv_ocl=off \
-DBUILD_opencv_photo=off \
-DBUILD_opencv_python=off \
-DBUILD_opencv_stitching=off \
-DBUILD_opencv_superres=off \
-DBUILD_opencv_ts=off \
-DBUILD_opencv_video=off \
-DBUILD_opencv_videostab=off \
-DBUILD_opencv_world=off \
-DBUILD_opencv_lengcy=off \
-DBUILD_opencv_lengcy=off \
-DWITH_1394=off \
-DWITH_EIGEN=off \
-DWITH_FFMPEG=off \
-DWITH_GIGEAPI=off \
-DWITH_GSTREAMER=off \
-DWITH_GTK=off \
-DWITH_PVAPI=off \
-DWITH_V4L=off \
-DWITH_LIBV4L=off \
-DWITH_CUDA=off \
-DWITH_CUFFT=off \
-DWITH_OPENCL=off \
-DWITH_OPENCLAMDBLAS=off \
-DWITH_OPENCLAMDFFT=off \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
..
  • -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
2
make
make install

这样编译出来的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
    #include "opencv2/core/core_c.h"
    #include "opencv2/core/core.hpp"
    #include "opencv2/flann/miniflann.hpp"
    #include "opencv2/imgproc/imgproc_c.h"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/photo/photo.hpp"
    #include "opencv2/video/video.hpp"
    #include "opencv2/features2d/features2d.hpp"
    #include "opencv2/objdetect/objdetect.hpp"
    #include "opencv2/calib3d/calib3d.hpp"
    #include "opencv2/ml/ml.hpp"
    #include "opencv2/highgui/highgui_c.h"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/contrib/contrib.hpp"

    改为

    1
    2
    3
    4
    5
    6
    #include "opencv2/core/core_c.h"
    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc_c.h"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui_c.h"
    #include "opencv2/highgui/highgui.hpp"
  • 移动到自定义文件下

    新建了一个3rdparty文件夹存放自定义编译的一些库文件

    • 将/usr/local/lib和/usr/local/share/OpenCV/3rdparty/lib下的 *.a 静态库放到\/3rdparty/opencv/lib下
    • 将/usr/local/include下的 opencv和opencv2文件夹放到\/3rdparty/opencv/include下

##测试

本测试是在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
    #include <stdio.h>
    #include <opencv2/opencv.hpp>
    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
    8
    cmake_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变量,直接将链接写在后方.