引言
这一系列文章总结了常用的计算机视觉算法及其 OpenCV (C++) 实现。
这些文章最初是作者本人学习下边这本书的笔记:
Robert Laganiere. OpenCV 3 Computer Vision Application Programming Cookbook. 2017
然后添加了一些总结,增补了一些理论推导。
发布这些文章的目的是方便作者本人及感兴趣的读者查阅。
文中的示例代码可以在原书作者的 github repo 中查看
https://github.com/laganiere/OpenCV3Cookbook
安装
- 平台: ubuntu18.04 + python 3.6
安装步骤主要参考这篇文章:https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv/
安装过程中如果遇到 cuda 路径的问题,解决方案如下:https://www.cnblogs.com/thmx/p/8565530.html
准备工作
- 安装开发者工具
sudo apt update
sudo apt upgrade
sudo apt install build-essential cmake unzip pkg-config
- 安装 image I/O package,以便 opencv 处理这些图片格式
sudo apt install libjpeg-dev libpng-dev libtiff-dev
- 安装 jasper library,其中包含了多种图像操作库
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt install libjasper1 libjasper-dev
- 安装视频流相关 package
sudo apt install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt install libxvidcore-dev libx264-dev
- 安装 opencv 中 highgui module 的依赖 GTK library
sudo apt install libgtk-3-dev
- 下述 library 可以优化 opencv 的某些操作
sudo apt install libatlas-base-dev gfortran
- 安装 python 3.6 的相关 headers 和 libraries
sudo apt install python3.6-dev
# 如果是其他版本的 python,例如 python 2.7,则可以用如下命令
# sudo apt install python2.7-dev
获取 OpenCV
OpenCV 从 3.0 版本开始分成了两个部分
opencv :包含成熟算法的主源码库
opencv_contrib:最近加入的更先进的算法库或者在活跃更新中的库,也包含一些付费的库
从 github 上可以获取最新的源码:
cd ~
git clone https://github.com/Itseez/opencv.git
git clone https://github.com/Itseez/opencv_contrib.git
或者下载特定版本的压缩包 (以3.2版本为例)
wget https://github.com/opencv/opencv/archive/3.2.0.tar.gz
tar -xvzf 3.2.0.tar.gz
wget https://github.com/opencv/opencv_contrib/archive/3.2.0.zip
unzip 3.2.0.zip
为了方便起见,以上解压的文件夹分别改名为 opencv 和 opencv_contrib
编译与安装
上述下载的是 OpenCV 的源码,我们需要编译成二进制文件才能被其他程序调用。
要区分源码和编译好的二进制文件
要查询源码,就去找刚才下载的文件;
要调用 OpenCV 库函数,目录在编译的目标地址中。
编译时, OpenCV 会根据本机环境,自动设置某些功能是否启用,也可以通过参数配置进行个性化的编译:
cd ~/opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D WITH_CUDA=OFF \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
-D OPENCV_ENABLE_NONFREE=ON \
-D BUILD_EXAMPLES=ON ..
上述 cmake 配置过程中经常如下问题
-
最常遇到的是网络链接的问题,导致
ippicv
,boostdesc
,vgg
等文件无法下载,这里关键是raw.githubusercontent.com
这个地址无法链接。一个解决方案是将该地址替换为代理地址。
具体设置如下:- ippicv 下载:将
opencv/3rdparty/ippicv/downloader.cmake
中的下载地址https://raw.githubusercontent.com/...
替换为https://ghproxy.com/https://raw.githubusercontent.com/
,即在原地址前边添加代理网址https://ghproxy.com/
- boostdesc, vgg 下载:将
opencv_contrib/modules/xfeatures2d/cmake
路径下的两个文件download_boostdesc.cmake
和download_vgg.cmake
中的 raw.githubusercontent.com 网址也修改为添加代理的地址。
- ippicv 下载:将
如果出现
stdlib.h: No such file or directory
这类错误,需要在 cmake 命令中添加参数-D ENABLE_PRECOMPILED_HEADERS=OFF
- 如果出现
opencv2/xfeatures2d/cuda.hpp: No such file or directory
之类的错误,参考这篇文章:https://www.cnblogs.com/thmx/p/8565530.html
实际上这个cuda.hpp
文件在~/opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d
目录下,可以直接在报错的文件中,指明完整的路径,例如:
#include "<YOUR_PATH>/opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d/cuda.hpp"
对于其他类似的问题,也可以用这种直接提供绝对路径的方法,可以避免找不到文件的问题。
- 如果出现
‘CODEC_FLAG_GLOBAL_HEADER’ was not declared in this scope
,‘AVFMT_RAWPICTURE’ was not declared in this scope
之类的错误,可以将下列预处理指令加入文件opencv/modules/highgui/src/cap_ffmpeg_impl.hpp
的头部:
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#define AVFMT_RAWPICTURE 0x0020
上述配置没有问题之后,进行下边的编译和安装:
make -j8 # 多用几个线程提高编译效率,但也可能把机子卡死
sudo make install # 默认安装到 /usr/local/bin 目录中
sudo ldconfig # 更新动态链接库
检查安装是否成功
可用如下命令查看动态链接库中是否有了 opencv :
ldconfig -p | grep opencv # -p = print
或者尝试用 pkg-config 查找 opencv
pkg-config --modversion opencv
结果应为刚刚安装的 opencv 版本号,例如
3.2.x
卸载 opencv
进入前边的 build 文件夹,也就是之前使用 make 命令的文件夹。
刚才用了命令 make install
,卸载只需要 make uninstall
。
然后删掉所有的 opencv 和 opencv_contrib 源码文件夹即可。
OpenCV 结构
文档位置
我们在调用 opencv 时只需要用到相关的头文件和库文件。
编译时可以设置这些文件的存放位置,默认位置如下:
- 头文件存放在 /usr/local/include/opencv2
- 库文件存放在 /usr/local/lib
主要 modules
-
core
:这是必须加载的,包含所有的基本对象类型和基本操作 -
highgui
( 在 opencv 3 版本中拆分成了 imgcodecs, videoio, highgui):如果要显示图像,就必须加载这个,同时也包含了用户交互工具 -
imgproc
:包含基本的图像变换操作,例如图像滤波、图像几何变换等 -
video
:包含读、写视频流的操作,跟踪、背景切割等 -
calib3d
:包含相机校准和三维重建相关的算法,例如基本的多视角几何算法、立体摄像头标定、物体姿态估计、立体相似性算法、3D 信息重建等。 -
features2d
:包含 2D 特征检测、描述、匹配算法 -
objdetect
:包含特定物体检测算法,例如脸、行人,也可以训练检测其他物体。 -
ml
:包含了很多机器学习算法,基本上是统计模型和分类算法。 -
flann
:Fast Library for Approximate Nearest Neighbors. 这个 module 一般不会被直接调用,而是在其他 module 进行最近邻搜索中使用。 -
gpu
(在 opencv 3 中被拆分成多个 cuda* modules):包含了专门为 CUDA GPU 优化的算法实现,涵盖了上述部分 module 中的功能。 -
photo
:包含计算摄影(computational photography)的算法,例如照片修复、去噪之类的 -
stitching
:提供了图像拼接整个流程算法
另外,除了标准的 opencv 库,还有一个 opencv_contrib 库,里面包含了最新的、尚未被集成到标准库中的算法,以及 non-free 的算法。
调用方式
在 c++ 中 include 时可以只写
#include <opencv2/opencv.hpp>
打开 opencv.hpp 源文件可以看到它实际上包含了所有的其他头文件。考虑到 C++ 编译流程,头文件是要被加载到 .cpp 文件中的,因此用这种方式 include 头文件肯定没有问题,但是 more than enough ,编译时间比较长。
更好的办法是指明要添加的具体的头文件,例如
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
这样做的好处一方面是编译时间短,另一方面是强化记忆,迫使编程人员清楚的知道程序中的函数来自哪个 OpenCV 模块。
另外,关于 opencv 具体模块的调用还有两种常见的形式,例如调用 highgui 模块:
- 方式一:
#include <opencv2/highgui/highgui.hpp>
- 方式二:
#include <opencv2/highgui.hpp>
这两种方式涉及到 openv 2.4 和 opencv 3 之间的区别。
这里有 OpenCV 官方的解释
https://docs.opencv.org/3.2.0/db/dfa/tutorial_transition_guide.html
总结来说:
- 在 opencv 2.4 中,所有的头文件都在相应的 module 文件夹下,因此必须要用方式一调用。
- 在 opencv 3 中,与 module 文件夹同级目录中添加了相应的头文件,因此可以直接用方式二调用,而不需要再进入 module 文件夹。如果很重视程序的向后兼容性问题,在 opencv 3 中也要用方式一调用头文件。