MacOS 上编译安装 OpenCV 的来龙去脉

本文讲解在 MacOS 上编译安装 OpenCV 源码的来龙去脉, 以对 cmake 在实战上有更多的了解

下载构建

下载 opencv / opencv_contrib 源码

1
2
3
mkdir opencv-tmp && cd opencv-tmp
git clone https://github.com/opencv/opencv_contrib.git aa --depth=1 -b 4.9.0
git clone https://github.com/opencv/opencv.git aa --depth=1 -b 4.9.0

构建 cmake

1
2
3
4
5
6
7
8
9
10
11
# 创建构建目录
mkdir build-opencv-4.9.0 && cd build-opencv-4.9.0

# 构建 cmake
cmake CMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON -DOPENCV_GENERATE_PKGCONFIG=ON -DCMAKE_INSTALL_PREFIX=/usr/local/ -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules ../opencv

# 使用 make 同时开启 8个 job 进行编译
make -j8

# 安装 opencv
make install

对于 cmake 的构建参数有:

  • CMAKE_BUILD_TYPE=Release 构建 release 版本
  • -BDBUILD_EXAMPLES=on 同时构建 exmaples
  • -BOPENCV_GENERATE_PKGCONFIG=ON 生成 pkg-config 相关文件
  • -DCMAKE_INSTALL_PREFIX=/usr/local/ OpenCV 相关库安装在 /usr/local/
  • -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules 同时安装三方扩展库

安装文件分析

OpenCV 和 OpenCV Contrib 相关动态库都会被安装在 /usr/local/lib 路径下:

1
2
3
4
5
6
7
8
9
10
11
/usr/local/lib > tree -L 1
.
├── cmake
├── libopencv_aruco.4.9.0.dylib
├── libopencv_aruco.409.dylib -> libopencv_aruco.4.9.0.dylib
├── libopencv_aruco.dylib -> libopencv_aruco.409.dylib
├── ...
├── ...
├── ...
├── libopencv_xphoto.dylib -> libopencv_xphoto.409.dylib
└── pkgconfig

OpenCV 的 cmake 相关配置文件生成在:

1
2
3
4
5
6
/usr/local/lib/cmake/opencv4 > tree - L 1
.
├── OpenCVConfig-version.cmake
├── OpenCVConfig.cmake
├── OpenCVModules-release.cmake
└── OpenCVModules.cmake

OpenCV 的 pkg-config 配置文件生成在:

1
2
3
/usr/local/lib/pkgconfig > tree -L 1
.
└── opencv4.pc

如何找到 OpenCV 库

下面举个例子, 我们来创建一个 sample 工程, 讲解 sample 工程中的 CMakeLists.txt 是如何找到并引用到 OpenCV 相关库的

创建 opencv-sample 工程, 有以下文件:

1
2
3
4
5
tree -L 1
.
├── CMakeLists.txt
├── main.cpp
└── test.png

配置 CMakeLists.txt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cmake_minimum_required(VERSION 3.25)  
project(demo)

set(CMAKE_CXX_STANDARD 17)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(demo main.cpp)
target_link_libraries(demo ${OpenCV_LIBS})

message(STATUS "OpenCV_DIR: ${OpenCV_DIR}")
message(STATUS "OpenCV_VERSION: ${OpenCV_VERSION}")
message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}")

这里重点解释下 sample 工程怎么找到 OpenCV 相关库的:

  • find_package(OpenCV REQUIRED) 告诉 cmake 在 /usr/local/lib/cmake/opencv4 查找并读取相关 .cmake 文件
  • include_directories(${OpenCV_INCLUDE_DIRS}) 包含 OpenCV 相关头文件
  • target_link_libraries(demo ${OpenCV_LIBS}) 链接 OpenCV 库

OpenCV_INCLUDE_DIRS 和 OpenCV_LIBS 是固定写法:

  • {XXX}_INCLUDE_DIRS
  • {XXX}_LIBS

cmake 在查找并读取相关 .cmake 文件时, 会给以上环境变量赋值:

OpenCVConfig.cmake

main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>  
#include <opencv2/opencv.hpp>
#include <string>
#include <filesystem>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
string testImgPath = std::filesystem::current_path().generic_string() + "/test.png";
Mat image = imread(testImgPath);
imshow("demo", image);
waitKey(0);
return 0;
}

构建执行:

1
2
3
4
cd opencv-sample
cmake . -B build-ninja -GNinja
cmake --build build-ninja
./build-ninja/demo

会出现展示测试图片的弹窗:
test.png