Ubuntu16.04源码编译安装opencv4.1.2+opencv_contrib的C++接口

0. 安装一些必要的包

sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

1. 下载opencv/opencv_contrib源代码

这里直接从opencv的github仓库clone最新的opencv源代码到本地:

cd /home/yan/
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git

在本地目录home/yan/下面将会得到两个文件夹:

yan@yanubuntu:~$ ll | grep opencv
drwxrwxr-x 15 yan  yan    4096 9月  14 14:09 opencv/
drwxrwxr-x  7 yan  yan    4096 9月  14 09:38 opencv_contrib/

2. cmake生成MakeFile文件

依次执行以下命令:

cd /home/yan/opencv/
mkdir build
cd build

接下来是cmake命令:

cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=/home/yan/opencv_contrib/modules -D PYTHON_DEFAULT_EXECUTABLE=/usr/bin/python3 -D BUILD_opencv_python3=ON -D BUILD_opencv_python2=OFF -D PYTHON3_EXCUTABLE=/usr/bin/python3 -D PYTHON3_INCLUDE_DIR=/usr/include/python3.5m -D WITH_CUDA=OFF -D OPENCV_GENERATE_PKGCONFIG=ON ..

对cmake的某些参数作解释:

cmake 
-D CMAKE_BUILD_TYPE=Release 
-D CMAKE_INSTALL_PREFIX=/usr/local 
# 如果要安装opencv_contrib模块,需要指定对应的modules文件夹位置
-D OPENCV_EXTRA_MODULES_PATH=/home/yan/opencv_contrib/modules
# 基本用不到python2,因此这里只编译python3的opencv版本 
-D PYTHON_DEFAULT_EXECUTABLE=/usr/bin/python3 
-D BUILD_opencv_python3=ON 
-D BUILD_opencv_python2=OFF 
-D PYTHON3_EXCUTABLE=/usr/bin/python3 
-D PYTHON3_INCLUDE_DIR=/usr/include/python3.5m
# 不需要使用opencv的GPU加速,将CUDA选项关掉 
-D WITH_CUDA=OFF 
# 这个选项非常重要,会生成一个被pkg-config模块使用的opencv4.pc文件,编译opencv的c++项目时可能会用到
-D OPENCV_GENERATE_PKGCONFIG=ON 

cmake过程中会下载某些文件,比较慢,请耐心等待。

3. make & make install

cmake完成后,依次执行:

make -j8
sudo make install

make编译过程也比较慢,通过 -j8 实现多线程加速。

4. 后处理

打开home目录下的.bashrc文件:

sudo vim ~/.bashrc

在最后添加如下环境变量:

export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

该目录下面有一个opencv4.pc文件,查看一下里面有哪些内容:

yan@yanubuntu:~$ ls /usr/local/lib/pkgconfig/
libspatialindex.pc  opencv4.pc
yan@yanubuntu:~$ cat /usr/local/lib/pkgconfig/opencv4.pc 
# Package Information for pkg-config

prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir_old=${prefix}/include/opencv4/opencv
includedir_new=${prefix}/include/opencv4

Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.1.2
Libs: -L${exec_prefix}/lib -lopencv_stitching -lopencv_gapi -lopencv_bgsegm -lopencv_img_hash -lopencv_xfeatures2d -lopencv_shape -lopencv_superres -lopencv_freetype -lopencv_aruco -lopencv_dnn_objdetect -lopencv_ccalib -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_stereo -lopencv_tracking -lopencv_datasets -lopencv_plot -lopencv_rgbd -lopencv_fuzzy -lopencv_line_descriptor -lopencv_reg -lopencv_hfs -lopencv_bioinspired -lopencv_surface_matching -lopencv_optflow -lopencv_ximgproc -lopencv_quality -lopencv_dpm -lopencv_highgui -lopencv_xobjdetect -lopencv_saliency -lopencv_hdf -lopencv_text -lopencv_dnn -lopencv_ml -lopencv_face -lopencv_objdetect -lopencv_videostab -lopencv_video -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir_old} -I${includedir_new}

opencv4.pc文件(貌似opencv3.x之前是生成名为opencv.pc的文件,这里编译的是opencv4.1.2,因此变成了opencv4.pc)是在前面cmake时通过添加-D OPENCV_GENERATE_PKGCONFIG=ON选项自动生成的。

该文件实际上也就是指定了安装opencv生成的 Include/包含目录Libs/库目录 的路径,以便在使用g++编译包含opencv函数的c++代码时,就可以使用 pkg-config 选项指定opencv库的搜索路径。

有了 opencv4.pc 文件,以及将该文件路径添加到 PKG_CONFIG_PATH 环境变量之后。就可以通过pkg-config命令来查看安装的opencv的一些信息了,比如:

# 查看opencv的版本号
yan@yanubuntu:~$ pkg-config --modversion opencv4
4.1.2
# 查看opencv的Include目录/头文件路径
yan@yanubuntu:~$ pkg-config --cflags opencv4
-I/usr/local/include/opencv4/opencv -I/usr/local/include/opencv4
# 查看opencv的Libs目录/库目录
yan@yanubuntu:~$ pkg-config --libs opencv4
-L/usr/local/lib -lopencv_stitching -lopencv_gapi -lopencv_bgsegm -lopencv_img_hash -lopencv_xfeatures2d -lopencv_shape -lopencv_superres -lopencv_freetype -lopencv_aruco -lopencv_dnn_objdetect -lopencv_ccalib -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_stereo -lopencv_tracking -lopencv_datasets -lopencv_plot -lopencv_rgbd -lopencv_fuzzy -lopencv_line_descriptor -lopencv_reg -lopencv_hfs -lopencv_bioinspired -lopencv_surface_matching -lopencv_optflow -lopencv_ximgproc -lopencv_quality -lopencv_dpm -lopencv_highgui -lopencv_xobjdetect -lopencv_saliency -lopencv_hdf -lopencv_text -lopencv_dnn -lopencv_ml -lopencv_face -lopencv_objdetect -lopencv_videostab -lopencv_video -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core

5. 测试: 使用opencv显示图像

下面测试opencv的c++接口,新建如下的DisplayImage.cpp文件:

// DisplayImage.cpp -- my first c++/opencv code in linux system

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
    string img_path = "img.png";
    Mat image;
    image = imread(img_path);

    if(image.data == NULL)
    {
        cout<<"No image data \n";
        return -1;
    }
    namedWindow("DisplayImage", WINDOW_AUTOSIZE);
    imshow("DisplayImage", image);
    waitKey(0);

    return 0;
}

假设cpp文件所在的文件夹下包含一个名为 img.png 的图片文件。
下面介绍如何编译cpp文件到可执行文件。有几种方式:

5.1 g++带pkg-config参数

命令如下:

yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ ls
DisplayImage.cpp  img.png
yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ g++ DisplayImage.cpp -o DisplayImage.out $(pkg-config --cflags --libs opencv4) --std=c++11
yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ ls
DisplayImage.cpp  DisplayImage.out  img.png

可以看到,编译成功后,生成了可执行文件DisplayImage.out。
运行可执行文件DisplayImage.out:

yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ ./DisplayImage.out

不出意外的话,图片就显示成功了:


这里是直接使用g++编译cpp文件,解释一下用到的编译选项:

g++ DisplayImage.cpp 
# 通过 -o 选项,指定生成的可执行文件的文件名,如果不指定的话,默认会生成一个 *a.out*的可执行文件
-o DisplayImage.out 
# 使用pkg-config选项指定cpp代码中用到的所有opencv的包含文件以及库文件,前面提到,opencv4.pc中提供了这些路径信息。
$(pkg-config --cflags --libs opencv4) 
# 使g++编译器支持c++11特性
# 如果没有这个选项,会出现类似error信息: error: #error "OpenCV 4.x+ requires enabled C++11 support"
--std=c++11

关于pkg-config工具的介绍请参考官网
以上面的cpp代码为例,由于代码中用到了opencv的两个头文件中定义的函数:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

因此,在g++编译链接过程中,我们需要给编译器提供opencv相关的包含文件路径以及库文件路径,这样g++才能生成完整的可执行文件。
而pkg-config工具就是专门管理gcc/g++编译过程中需要用到的依赖模块路径的:

  • 前面我们编译opencv时生成了一个opencv4.pc文件,该文件包含了所有opencv的包含文件/库文件路径。
  • 通过将opencv4.pc文件的路径添加到PKG_CONFIG_PATH 环境变量,pkg-config工具就掌握了opencv相关文件的所有路径信息。
  • g++ 编译时,通过提供 $(pkg-config --cflags --libs opencv4) 选项,pkg-config工具会提供g++所需的opencv相关依赖文件的路径。

不仅是opencv,其他所有的库的路径都可以通过pkg-config来统一管理。

2. 通过cmake + make生成可执行文件

典型的c++项目的编译方式应该是使用cmake + make的方式。需要编写一个 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 2.8)
project(DisplayImage)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(DisplayImage DisplayImage.cpp)
target_link_libraries(DisplayImage ${OpenCV_LIBS})
SET( CMAKE_CXX_FLAGS "-std=c++11")

保存后执行cmake生成MakeFIle文件,然后执行make得到可执行文件:

yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ cmake .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenCV: /usr/local (found version "4.1.2") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/yan/Desktop/c_plus_opencv_sample
yan@yanubuntu:~/Desktop/c_plus_opencv_sample$ make
Scanning dependencies of target DisplayImage
[ 50%] Building CXX object CMakeFiles/DisplayImage.dir/DisplayImage.cpp.o
[100%] Linking CXX executable DisplayImage
[100%] Built target DisplayImage
yan@yanubuntu:~/Desktop/c_plus_opencv_sample$

5.3 使用IDE

之前在Windows系统中用过VS,在ubuntu系统中还没有使用过集成开发环境(Integrated Development Environment,IDE),不过应该和VS差不多,这应该是最简单的编译方式了,点击 run 按钮,所有的编译链接执行过程自动完成。

目前对在linux系统的c++开发基本不懂,以上内容纯属搬砖。仅供参考。

6. 参考资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容