编译OpenCV源码
之前写过几篇关于OpenCV的博客,都是基于openCV 3.14写的,10月份OpenCV发布了4.0的bate版本,我就切换到4.0版本上来。之后的博客都会是基于4.0版本的。本文主要介绍一下三个方面的内容:
- OpenCV 4.0的改进
- 编译OpenCV 4.0源码的方法
- 源码编译中遇到的问题及解决方法
这三方面的问题都是比较基础的,但是对于新手可能有些复杂。本文是在Ubuntu 18.04系统上进行编译,如果熟悉cmake可能会更好。
OpenCV 4.0的更新
4.0版本的改进主要集中在深度学习和高性能计算方面,一下包含4.0 alpha版本以来的改进:
-
深度学习方面:
- 将ONNX解析器添加到OpenCV DNN模块中,它能够支持AlexNet、Incepiton v2、Reset、VGG等分类网络。同时改进其导入器,能够支持更多拓扑
- 屏蔽RCNN支持和示例
- 修复了OpenCL后端的几个稳定性问题
- 添加了Intel的开源工具OpenVINO,该工具包可以实现高性能计算机视觉和深度学习推理,并可跨多种类型的英特尔平台轻松实现异构执行。
-
高性能计算方面:
- 使用AVX2对60个kernels进行了加速优化,涉及18个功能
- 针对iGPU加速了Kinect Fusion算法,在高高分辨率(512×521×512)上可达到并行CPU版本的3倍。
- 使用C++ 11库,需要符合C++ 11标准的编译器,默认情况下可以使用一些更好的功能,例如parallel_for和lambda函数,方便迭代cv::Mat,通过列出他的元素初始化cv::Mat等。另外,parallel_for可以使用std::threads池作为后端。
- 使用标准的std::string和std::shared_ptr代替cv::String和cv::ptr。
- 添加了FP16支持(CV_16F)
- 该版本中OpenCV 1.x的C API部分的被排除,在接下来的4.0 gold版本中将完成清理.
OpenCV 4.0 源码编译
OpenCV本身依赖很多库,所以首先要搭建编译环境。注意编译器需要支持c++ 11,例如g++。
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
复制代码
这其中包含了cmake和git,如果安装过就不需要重新安装了。
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
复制代码
这些库都很好安装,如果安装过程遇到什么问题,可以直接把报错信息粘贴出来百度或者Google,很容易找到解决办法,毕竟已经有很多前辈踩过这些问题了。另外就是对于新手用好下面两个命令:
sudo apt-get update
sudo apt-get upgrade
复制代码
安装库的过程中,很多问题更新以后就可以解决。
做好前戏之后,就要直奔主题了。 OpenCV编译非常方便,毕竟cmake已经写的很好了。编译命令很容易在网上找到,这里就再贴一下:
cmake ../ -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local
复制代码
简单解释一下:
- OpenCV是不让在源文件目录下编译的,所以在编译之前可以在opencv目录下创建build或者release等目录,然后进入该目录执行以上代码。
../
表示上一级目录,这里需要是CMakeLists.txt所在的目录。 - 选择程序构建的类型,release版本 or debug版本
- 编译后安装的目录,注意这里可以自己指定安装的目录,默认情况下会安装到/usr/local目录下。
简单看一下cmake文件,
-
第一段:
9 # Disable in-source builds to prevent source tree corruption. 10 if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}") 11 message(FATAL_ERROR " 12 FATAL: In-source builds are not allowed. 13 You should create a separate directory for build files. 14 ") 15 endif() 复制代码
可以看到,是不允许进行内部编译。
-
第二段:
38 if(NOT DEFINED CMAKE_INSTALL_PREFIX) #如果没有指定安装目录 39 if(NOT CMAKE_TOOLCHAIN_FILE) #并且没有指定架构 40 # it _must_ go before project(OpenCV) in order to work 41 if(WIN32) 42 set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") 43 else() 44 set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory") 45 endif() 46 else() 47 #Android: set output folder to ${CMAKE_BINARY_DIR} 48 set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are compiled to" ) 49 # any cross-compiling 50 set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") 51 endif() 52 endif() 复制代码
这是关于安装目录的代码,可以看出,默认情况下在Linux系统中是安装在
/usr/local/
目录下的。
另外还有很多选项,可以在CMake文件中去编辑也可以使用编译选项-D
去指定,用户可以根据需求修改。
以上仅仅是使用cmake生成了makefile,接下来是编译安装的命令:
make -j8
make install
复制代码
make -j8
是编译,j8只是根据处理器不同编译速度不同,例如4核8线程的机器-j8速度是最快的。
到此为止就完成了OpenCV 4.0的源码编译安装。
最后一步是设置环境变量,命令如下:
vi ~/.bashrc
复制代码
在文件最后增加下面两行代码:
注意这里的路径是我的安装路径,需要修改为你自己前文执行cmake的时候配置的安装路径
export PKG_CONFIG_PATH=~/study/usr/local/lib/pkgconfig
export LD_LIBRARY_PATH=~/study/usr/local/lib
复制代码
测试一下:
在准备工作中我们安装过一个工具叫做pkg-config, 运行如下命令:
pkg-config --help
复制代码
Usage:
pkg-config [OPTION?]
Help Options:
-h, --help Show help options
Application Options:
--version output version of pkg-config
--modversion output version for package
--atleast-pkgconfig-version=VERSION require given version of pkg-config
--libs output all linker flags
--static output linker flags for static linking
--short-errors print short errors
--libs-only-l output -l flags
--libs-only-other output other libs (e.g. -pthread)
--libs-only-L output -L flags
...
复制代码
仅仅截取了一部分,能够看到使用--modversion
命令可以查看opencv的版本号。
执行如下代码:
pkg-config --modversion opencv4
复制代码
显示如下:
4.0.0
复制代码
测试代码
直接上代码:
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
cout << "Hello OpenCV " << CV_VERSION << endl;
// 载入图像
Mat myMat = imread("timg.jpeg", 1);
// 创建一个窗口
namedWindow("Opencv Image", WINDOW_AUTOSIZE);
// 显示图像
imshow("Opencv Image", myMat);
// 等待按键延时 ms
waitKey(5000);
return 0;
}
复制代码
编译命令:
g++ test.cpp `pkg-config --libs --cflags opencv4`
复制代码
注意使用的是反引号,关于pkg-config命令的含义可以使用--help
查看;主要是输出链接OpenCV的库,这里只是为了方便,正确使用的时候,可以自己写cmake去设置。
编译完以后直接执行a.out
文件就可以看到效果了。需要字节下载一张.jpeg的图片放到test.cpp所在的目录。