前言

该内容使用 mdBook 构建。

可能使用 OpenCV 的 C++ 或 Python 接口进行图像处理的实践。

OpenCV 介绍

OpenCV 是一个开源的图像处理库。

要开始下边的内容,需要读者了解:

  • 一定的 Python 基础
  • 一定的 C++ 基础
  • 命令行的使用
  • 版本管理系统
  • CMake 的基础使用

章节概览:

如何获得 OpenCV

OpenCV 是一个软件库,因此需要我们通过编程调用其接口,以使用其中的功能。

本节介绍 OpenCV 的安装。关于 OpenCV 的使用参见下一节。

Windows

Windows 用户可以参考下面的教程。

MSYS2

如果用户希望使用 MinGW-w64 GCC 作为编译器,可以安装 MSYS2 来配置开发环境。

MSYS2 的包管理器提供有 ffmpeg、OpenCV 等工具。得益于包管理器,这些软件的安装、使用都比较方便。

关于 MSYS2 的安装这里暂时不再赘述,详情参见 msys2.org

一般来说,在初次安装后可能还需要配置镜像源以便更快速地下载软件包。此外,也建议将 MSYS2 的安装目录及之后的工作目录添加进反病毒软件如 Windows Defender 的“排除项”中,以期在使用时获得更高的运行效率。

首次进入 MSYS2 后,需要先安装 MinGW-w64 64-bit 的工具链:

$ pacman -S mingw-w64-x86_64-toolchain

i686 是 32 位指令集,而 x86_64 是 64 位指令集(有时也称 amd64)。对于 64 位机,自然使用针对 64 位指令集的软件更合适。

之后,等待安装过程完成。

接下来,可以安装对应工具链适用的 OpenCV 了(事实上 MSYS2 也只有这一种).

$ pacman -S mingw-w64-x86_64-opencv

待安装过程结束即可。关于如何使用将在下一节介绍。

vcpkg

如果用户使用的是微软的 MSVC,则建议搭配 CMakevcpkg 使用。

vcpkg 是一款开源的、基于源代码的 C++ 依赖管理器。简单地说,用户可以使用 vcpkg 安装自己需要的 C++ 依赖。

将 vcpkg 的整个仓库克隆在本地,再执行提供的脚本,即可完成 vcpkg 的部署,详情参见 vcpkg 仓库的 README网站上的说明材料

无论是 vcpkg 还是之后 OpenCV 的代码,都是从 GitHub 取得的,因此可能需要用户具有相应的网络访问环境。笔者实验时,vcpkg 会自动使用系统代理(如果进行了相应的配置),但执行 git clone 可能需要在终端中手动设置 HTTP 和 HTTPS 代理服务器地址相关的环境变量

vcpkg 的若干实例是互不影响的。用户可以在计算机上部署多个 vcpkg 的实例。针对其这个特性,用户可以先切换到 vcpkg 的目录下再执行命令,而不是将其添加到 PATH。

由于 vcpkg 是基于源代码的,因此在安装 OpenCV 之前,需要用户先安装微软的编译器 MSVC。

用户在终端中切换到 vcpkg 的安装目录后,执行下面命令即可安装 OpenCV:

笔者在实验时还发现,还需要额外安装 Visual Studio 的英语(English)语言包,才能顺利执行安装操作。

PS> ./vcpkg install opencv

需要注意,对于 OpenCV 以及其他一些包,vcpkg 在安装时有不同的 feature 可供选择。可以在 vcpkg 网站上检索包对应的信息,或者使用 ./vcpkg search <packagename> 进行检索。

比如,我们可以执行下面的命令,选择需要的 feature 并进行安装:

PS> ./vcpkg install opencv[core,dnn,jpeg,png,quirc,tiff,webp]

之后便会开始相对比较漫长的代码编译过程,可能会耗费约数十分钟或更久。同样,建议将 vcpkg 的目录添加进反病毒软件的排除项,可以加快速度。

除此之外,在 Windows 上,上述命令默认将会构建针对 x86-windows 平台的 OpenCV,我们还需要手动指定构建安装针对 x64-windows 平台的 OpenCV。

opencv[core,dnn,eigen,ffmpeg,ipp,jpeg,openmp,png,qt,quirc,tiff,webp]:x64-windows

编译过程中会产生很多文件(如 vcpkg 目录下的 buildtrees 目录,存放构建过程中产生的文件,如果保留可能会减少下次更新时花费的时间),可能会占用十数 GB 的磁盘空间。可以根据需要删除这些中间文件。

预构建版本(Windows-MSVC)

也可以在 OpenCV GitHub 仓库的 Release 页 下载 OpenCV 提供的预构建版本。目前为 Windows 提供的预构建版本是针对 MSVC 的,文件名类似 opencv-<version>-vc14_vc15.exe

下载好 OpenCV 预构建版本后,安装在指定的目录即可,这里假设安装目录为 D:\softwares\opencv\

同样,推荐使用 CMake 作为构建管理工具,具体使用方法在下一节介绍。

Python

上述为 C++ 的安装使用。如果使用 Python,可以使用 pip 安装 OpenCV。

在配置好 Python 以及 pip 的情况下,只需要在终端中执行:

pip install opencv-python

或者

python -m pip install opencv-python

Ubuntu

关于 Ubuntu 的软件源配置这里不作赘述。

大多数的桌面 Ubuntu 版本都可以从软件仓库获得 OpenCV。

更新软件源:

$ sudo apt update 

安装用于开发的 OpenCV:

$ sudo apt install libopencv-dev 

其他平台如 NVIDIA Jetson,虽然搭载 Ubuntu 操作系统,但是 OpenCV 的安装与此不同。可以参见其他关于 NVIDIA Jetson 的配置记录。

macOS

先安装 XCode 命令行工具。在终端中执行:

xcode-select --install

之后可以安装 Homebrew,并使用 Homebrew 安装 OpenCV。

由于笔者未持有运行 macOS 的设备,因而有关 macOS 的记录尚不完善。

从源码编译 OpenCV

除了使用 vcpkg,用户也可以自行下载 OpenCV 的源代码,并且编译 OpenCV。这往往是在用户需要使用 opencv_contrib 中的代码时进行的工作。一般情况下,使用上述的安装方式会更为轻松。

(未完待续)

使用 OpenCV 的 C++ 接口

之前说到,推荐使用 CMake 进行 C++ 项目的构建管理工具。

在使用时可能还需要为 CMake 传入正确的参数,比如,使用 vcpkg 需要指定工具链文件的路径,使用 Windows 上的预构建版本则需要指定 OpenCV 的路径。具体操作将会在下文介绍。

不同工具链需要进行的配置

vcpkg

在 CMake 配置过程中,需要将 vcpkg 目录下的 scripts/buildsystems/vcpkg.cmake 文件路径,作为 CMAKE_TOOLCHAIN_FILE 变量传入,这样 CMake 就可以识别到该 vcpkg 实例中安装的包了。

比如,假设 vcpkg 的目录位于 C:/dev/vcpkg/, 则需要在 IDE 中 CMake 相关设置的 "Configure Args" 中添加下列命令行参数选项:

-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake

如果使用命令行界面,则可以采用类似如下的命令:

cmake \
    -B [build directory] \
    -S . \
    -DCMAKE_TOOLCHAIN_FILE="[path to vcpkg]/scripts/buildsystems/vcpkg.cmake"

预构建版本 (Windows)

可以在 OpenCV 对应 GitHub 仓库的 Release 中, 下载到适用于 64 位 Windows 的 OpenCV 预构建版本.

本文写作时, 最新的预构建版本发布为 opencv-4.7.0-windows.exe, 为一个可执行的自解压程序.

之前的发布中, 适用于 Windows 平台的文件名后缀为 vc14_vc15, 提示该发布构建时使用的 Visual Studio 版本为 vc14vc15 (另, 目前的最新发布中已经仅包含 vc16), 但由于 Visual Studio 2015 以及之后的版本均保证二进制兼容性 (参见 C++ binary compatibility between Visual Studio versions - Microsoft Learn), 因此仍能搭配新版本的 Visual Studio 工具链使用.

下载后完成后运行该程序, 选择解压路径, 程序会将文件解压到选择路径的 opencv 目录下. 比如指定提取路径为 D:/softwares/, 则提取完成后文件将位于 D:/softwares/opencv/ 目录下.

该目录下有 buildsources 两个目录, 分别存放构建产物和源代码. 下文将 D:/softwares/opencv/build/ 称作 OPENCV_DIR.

由于预构建版本中提供的 OpenCVConfig.cmake 文件链接动态库时使用的是相对路径, 为了构建出的程序能够寻找到对应的动态库, 进而正常执行, 我们还需要将对应库文件的路径添加到 PATH 环境变量中, 或者把文件复制到构建出的可执行文件所在的目录下.

这里我们使用 vc15 的构建版本, 则二进制文件所在的目录为 ${OPENCV_DIR}/x64/vc16/bin (即 D:/softwares/opencv/build/x64/vc16/bin 目录).

预构建版本中将所有的库打包成了一个后缀为 world 的 DLL, 即 opencv_world470.dllopencv_world470d.dll. 除此之外还有一些其它的 DLL 库文件, 这里暂不介绍. 文件名中的数字表示版本号, 末尾的 d 表示为 Debug 版本, 否则则为 Relase 版本. 文件名后缀为 .pdb 的文件为对应的调试信息文件. 文件后缀为 .exe 的文件为实用程序.

如果是在开发机器上, 则将上述提到的 bin 目录添加进 PATH 环境变量即可 (如果更新 OpenCV 则需要记得更新环境变量).

如果是将构建好的程序分享给别人使用, 则建议将对应的 .dll.pdb 文件一同打包 (如果是 Debug 版本, 记得使用文件名带 d 的文件).

如前文所说, 在开发过程中建议使用 CMake, 则在 CMake 的配置阶段将 OpenCV 的安装路径 (即前述的 OPENCV_DIR) 作为 OpenCV_DIR 变量传入, CMake 就可以识别到安装的 OpenCV 了.

可以将参数写入 IDE 的构建工具选项:

-DOpenCV_DIR=D:/softwares/opencv/build

或者:

-DOpenCV_DIR=D:/softwares/opencv/build/x64/vc16/lib

也可以使用命令行界面进行 CMake 的 Configure 过程:

cmake \
    -B [build directory] \
    -S . \
    -DOpenCV_DIR="D:/softwares/opencv/build/x64/vc16/lib"

除此之外,也可以使用 set() 命令在 CMakeLists.txt 文件中显式指明路径,或者让 CMake 的 find_package 命令在指定目录下查找。

CMakeLists.txt

在如上述配置好 OpenCV 后,只需要在 CMakeLists.txt 中使用 find_package(OpenCV REQUIRED) 即可引入需要的安装包。

一个完整的 CMakeLists.txt 文件类似如下:

project(CMAKE_OPENCV_TEST)
cmake_minimum_required(VERSION 3.13)

find_package(OpenCV REQUIRED)
message("${OpenCV_DIR}")

add_executable(main "hello.cpp")
target_link_libraries(main ${OpenCV_LIBS})

使用 OpenCV

矩阵相乘

下面的 C++ 代码可以进行两个矩阵的相乘。关于接口的详细使用方式会在之后章节介绍。

代码文件:code/mat-multiply.cpp

#include <opencv2/opencv.hpp>
#include <iostream>

int main()
{
    double data_a[] = { 3, 2, 1, 5, 9, 1, 3, 0 };
    double data_b[] = { 2, 9, 0, 1, 3, 5, 2, 4, 7, 8, 1, 5 };

    cv::Mat a(2, 4, CV_64F, data_a);
    cv::Mat b(4, 3, CV_64F, data_b);
    std::cout << a << '\n' << b << '\n' << a * b;
}

代码展示:Python

Python 是一个解释性的语言。