OpenCV 是流行的计算机视觉库。 最近因项目需要,要在树莓派上编译构建 OpenCV C++ 项目。踩了不少坑,分享出来。
编译 OpenCV 源码
OpenCV 目前的最新版本是 4.5.1,但项目使用版本 3.4.12。
在树莓派 Home 目录下,新建 opencv-project 文件夹
cd ~
mkdir opencv-project
下载 3.4.12 版本 opencv 源码,然后解压到当前目录
cd opencv-project
wget https://github.com/opencv/opencv/archive/3.4.12.tar.gz
tar xvzf 3.4.12.tar.gz
注:OpenCV 的所有版本可以从 Releases · opencv/opencv 找到
进入解压后的 opencv 源码目录,新建 _build、_output 两个目录(_build 用于暂存编译中间产物,_output 用于存放编译结果)
cd opencv-3.4.12
mkdir \_build \_output
进入 _build 目录,执行 cmake 以生成 makefile 文件
cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/home/pi/opencv-project/opencv-3.4.12/\_output ..
-D 是 cmake 的构建参数。CMAKE_BUILD_TYPE=RELEASE 表示构建成正式版(还有一个取值是 DEBUG,表示构建成调试版,产物里会添加调试代码);CMAKE_INSTALL_PREFIX 是构建产物安装目录,这里指定到上一步的 _output 目录,方便获取所有构建产物。最后的 .. 指向 OpenCV 源码路径,也就是 _build 目录的上一层。
cmake 执行完后,会在 _build 目录下生成一系列的缓存文件和 Makefile 文件。
还在 _build 目录下,执行 make -j4,开始编译 OpenCV 源码。-j4 表示并发执行 4 个编译任务,一般有几个 CPU 核心就指定几个并发任务。
等到进度走到 100% 的时候,就表示编译结束。
继续执行 make install。执行完成后,构建产物即输出到 _output 目录。
bin 目录里是一些 OpenCV 自带的可执行程序,一般用不到。include 目录里是 C++ 头文件。lib 目录里是编译出来的 OpenCV 动态链接库。share 目录里是一些文档和模型文件。
编译 OpenCV 应用程序示例
上一步,我们已经得到了 OpenCV 最重要的头文件和动态链接库。这里用一个简单的“打开图片”的示例来说明如何基于这些头文件的库,编译一个 OpenCV 应用程序。
新建 display-a-pic 目录,然后在这个文件夹下新建 main.cpp 文件
#include <opencv2/opencv.hpp>
int main(int argc, char \*\*argv)
{
cv::Mat img = cv::imread(argv[1], -1);
if (img.empty()) return -1;
cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE);
cv::imshow("Example1", img);
cv::waitKey(0);
cv::destroyWindow("Example1");
return 0;
}
注:cv:: 是 OpenCV 的命名空间
cv::imread
从指定路径读取图片,并赋值给 cv::Mat img
。cv::namedWindow
打开一个视窗,cv::imshow
在视窗中显示图片。cv::waitKey
等待按键事件,0 表示任意按键都会退出等待。cv::destroyWindow
销毁视窗。
接着在当前目录下新建 CMake 配置文件 CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required(VERSION 3.10.2)
project(demo)
set(OpenCV_DIR "/home/concefly/Project/opencv-exp/opencv-3.4.12/\_output/share/OpenCV")
find_package( OpenCV REQUIRED )
message("WARNING" "OpenCV_INCLUDE_DIRS:" ${OpenCV_INCLUDE_DIRS})
message("WARNING" "OpenCV_LIBS:" ${OpenCV_LIBS})
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(demo main.cpp)
target_link_libraries(demo ${OpenCV_LIBS})
由于上一节将 OpenCV 编译生成至了 _output 目录,所以必须要在编译 main.cpp 的时候指定 OpenCV 库路径,也就是 set(OpenCV_DIR "/home/concefly/Project/opencv-exp/opencv-3.4.12/\_output/share/OpenCV")
。
find_package( OpenCV REQUIRED )
这一步执行完后,会设置 OpenCV_INCLUDE_DIRS 和 OpenCV_LIBS 两个全局变量,分别表示头文件路径和动态链接库路径。这时需要调用 include_directories 和 target_link_libraries 把它们加入到编译参数里。
add_executable(demo main.cpp)
则指示把 main.cpp 编译成 demo 可执行文件。
此时在当前目录下执行:
cmake . && make
则得到了文件名为 demo 的可执行文件。
执行 ./demo a.jpg,就可以看到 OpenCV 打开的图片展示窗口了。
当然这只是个 demo 演示,用于展示 OpenCV 编译和构建应用程序的一些环节,真正的项目会比这复杂的多,但基本原理是相通的。