OpenCV 3.x/4.x编译

OpenCV除了提供源码编译外,还提供了预编译版本,包含Linux/macOS/Windows的Python/C++版本:Get Started

OpenCV 3.x vs. OpenCV 4.x

简单地说,除了更多的算法增加和性能增强以外,OpenCV 4.x对C++有更好的支持(减少对C的支持)。

Linux编译

环境搭建

CMake配置/编译/安装

执行如下脚本build.sh,指定构建类型和其他配置选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/bash

# 设置工具链(可根据需要修改)
export CC=gcc
export CXX=g++

# 打印系统信息
# 使用 printf 命令打印50个星号
printf '*%.0s' {1..50}
echo # 打印换行符
echo "当前系统信息:"
echo " - 发行版信息:$(lsb_release -ds)"
echo " - 处理器核心数:$(nproc)"
echo " - 系统架构:$(uname -m)"
# 使用 printf 命令打印50个星号
printf '*%.0s' {1..50}
echo # 打印换行符

# 创建并进入build目录
mkdir -p build
cd build

# 打印当前路径
pwd

# 设置编译类型(Debug或Release)
# BUILD_TYPE=Debug # 设置为Release则编译Release版本
BUILD_TYPE=Release # 设置为Release则编译Release版本
# 定义Python库根路径变量
PYTHON_ROOT=/home/zj/anaconda3/envs/py38

# 执行CMake编译OpenCV库
cmake \
-D CMAKE_C_COMPILER=${CC} \
-D CMAKE_CXX_COMPILER=${CXX} \
-D CMAKE_BUILD_TYPE=${BUILD_TYPE} \
-D CMAKE_INSTALL_PREFIX=../install_${BUILD_TYPE} \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.9.0/modules/ \
-D BUILD_opencv_python2=OFF \
-D BUILD_opencv_python3=ON \
-D PYTHON3_EXECUTABLE=${PYTHON_ROOT}/bin/python \
-D PYTHON3_LIBRARY=${PYTHON_ROOT}/lib \
-D PYTHON3_INCLUDE_DIR=${PYTHON_ROOT}/include/python3.8 \
-D PYTHON3_NUMPY_INCLUDE_DIRS=${PYTHON_ROOT}/lib/python3.8/site-packages/numpy/core/include/ \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D WITH_FREETYPE=ON \
../

# 编译OpenCV库
make -j$(nproc)

# 安装OpenCV库
make install

关于CMake配置选项的解释如下:

交叉编译

一般来说,指定交叉编译工具链的C 编译器和 C++ 编译器的路径进行编译,就可以生成适用于目标平台的可执行文件或库。

1
2
CC=/path/to/cross-compiler-cc
CXX=/path/to/cross-compiler-cxx

比如在Ubuntu环境下使用gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu交叉编译aarch64架构,设置编译器路径如下:

1
2
CC=/path/to/aarch64-linux-gnu-gcc
CXX=/path/to/aarch64-linux-gnu-g++

Windows编译

环境搭建

在Windows环境下编译OpenCV,通常使用cmake-guiMSVC工具链;

CMake配置/编译/安装

注意:在cmake-gui配置OpenCV选项的时候,还可以开启BUILD_opencv_world

常见编译问题

  1. 没有Python.h文件
1
opencv-4.6.0/modules/python/src2/cv2.hpp:20:10: fatal error: Python.h: No such file or directory

指定OpenCV Python头文件路径的时候需要注意Python.h位于该路径下:

1
-D PYTHON3_INCLUDE_DIR=${PYTHON_ROOT}/include/python3.8 \
  1. File too big

在Windows环境下使用MingGW编译OpenCV的过程中出现如下错误:

1
Fatal error: can't close CMakeFiles\opencv_perf_core.dir\perf\opencl\perf_arithm.cpp.obj: File too big

相关解决方案参考Error to build OpenCV 4.0.1 in Debug mode from source #13546。采用MSVC工具链编译没有出现这个问题。

  1. 在线下载文件

在源码编译OpenCV的过程中需要下载部分第三方文件(opencv-cache.tar),这部分文件会存放在

1
2
3
/path/to/opencv-4.9.0/.cache
/path/to/opencv-4.9.0/build/3rdparty
/path/to/opencv-4.9.0/build/downloads

使用示例

创建示例工程:OpenCVDemo,配置CMakeLists.txt,适配Windows环境和Linux环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cmake_minimum_required(VERSION 3.24)
project(OpenCVDemo)

set(CMAKE_CXX_STANDARD 17)

# set opencv
get_filename_component(ABSOLUTE_OpenCV_DIR ./3rdparty/opencv ABSOLUTE)
IF (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(OpenCV_DIR ${ABSOLUTE_OpenCV_DIR}/lib/cmake/opencv4)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows")
set(OpenCV_DIR ${ABSOLUTE_OpenCV_DIR})
ENDIF ()
find_package(OpenCV REQUIRED)

MESSAGE("OpenCV version: ${OpenCV_VERSION}")
MESSAGE("OpenCV OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")
MESSAGE("OpenCV OpenCV_LIBS: ${OpenCV_LIBS}")


add_executable(OpenCVDemo main.cpp)
target_link_libraries(OpenCVDemo ${OpenCV_LIBS})

注意:将OpenCV安装路径链接到./3rdparty/opencv

1
2
3
4
5
# Linux
ln -s /path/to/opencv/opencv-4.9.0/install_Release ./3rdparty/opencv
# Windows 管理员方式打开cmd
C:\zj\repos\deploy\3rdparty>mklink /d opencv C:\software\opencv\build\install_Debug
symbolic link created for opencv <<===>> C:\software\opencv\build\install_Debug

边写示例程序,读取图像,裁剪中心区域,显示并保存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

#include "opencv2/opencv.hpp"

int main() {
// 读取图片
cv::Mat image = cv::imread("../lena.jpg");
if (image.empty()) {
std::cout << "无法读取图片,请确保文件路径正确" << std::endl;
return -1;
}

// 获取图片的尺寸
int width = image.cols;
int height = image.rows;

// 计算中心裁剪的区域
int x = width / 4; // 裁剪区域的左上角 x 坐标
int y = height / 4; // 裁剪区域的左上角 y 坐标
int cropWidth = width / 2; // 裁剪区域的宽度
int cropHeight = height / 2;// 裁剪区域的高度

// 裁剪图片
cv::Rect cropRegion(x, y, cropWidth, cropHeight);
cv::Mat croppedImage = image(cropRegion);

// 显示原始图片和裁剪后的图片
cv::imshow("原始图片", image);
cv::imshow("裁剪后的图片", croppedImage);
cv::waitKey(0);

// 保存裁剪后的图片
cv::imwrite("../cropped_lena.jpg", croppedImage);

std::cout << "Hello, World!" << std::endl;
return 0;
}