OpenCV  4.10.0
开源计算机视觉
正在加载...
正在搜索...
无匹配内容
在 Ubuntu/Debian 上进行多架构交叉编译

上一教程: 基于 ARM 的 Linux 系统交叉编译
下一教程: 为支持 CUDA 的 Tegra 构建 OpenCV

原作者Kumataro
兼容性Ubuntu >=23.04
OpenCV >=4.8.0
警告
本教程可能包含过时信息。

什么是“多架构”

OpenCV 可能会使用大量用于视频和图像解码、渲染、加速和复杂数学算法的第三方库。CMake 会在构建主机上找到第三方组件,交叉编译允许为其他体系结构或操作系统构建 OpenCV,但我们会丢失大量的组件,并且在构建 OpenCV 时必须分别交叉编译每个依赖项并指向它。

Debian/Ubuntu 多架构有助于解决此问题。它允许在主机系统上安装多个外部体系结构库,并在解析 OpenCV 依赖项时使用它们。

警告
  • 按照以下步骤操作会使你的 Linux 环境稍微有点乱。如果可能,最好使用虚拟机或容器(例如 Docker)。
  • 本教程预计主机和目标使用相同的 Ubuntu 版本。请不要对外部库依赖项使用/混合不同的版本。
    • 良好:主机和目标为 23.04。
    • 良好:主机和目标为 23.10。
    • 不好:主机为 23.04,目标为 23.10。
    • 不好:主机为 23.10,目标为 23.04。
  • 本教程可用于 Debian 及其衍生版(如 Raspberry Pi OS)。请根据需要进行任何必要的修改。

下载工具

为交叉编译安装必要的工具和工具链。

  • 基本需要 git、cmake、pkgconf 和 build-essential。
  • ninja-build 用于减少编译时间(可选)。
  • crossbuild-essential-armhf 是针对 armv7 目标的工具链包。
  • crossbuild-essential-arm64 是针对 aarch64 目标的工具链包。
sudo apt update -y
sudo apt install -y \
git \
cmake \
pkgconf \
build-essential \
ninja-build \
crossbuild-essential-armhf \
crossbuild-essential-arm64

如果您要启用 Python 3 封装器,也安装以下软件包。

sudo apt install -y \
python3-minimal \
python3-numpy

工作文件夹结构

在本教程中,使用以下工作文件夹结构。

/home
+ kmtr - 请替换您的帐户名称。
+ work
+ opencv - 从 github 克隆的源代码
+ opencv_contrib - 从 github 克隆的源代码
+ build4-full_arm64 - 构件文件 (用于 aarch64 目标),由 cmake 创建
+ build4-full_armhf - 构件文件 (用于 armhf 目标),由 cmake 创建
  1. 在您的主目录下创建工作文件夹。
  2. 将 OpenCV 和 OpenCV Contrib 从存储库克隆到工作目录。
cd ~
mkdir work
cd work
git clone --depth=1 https://github.com/opencv/opencv.git
git clone --depth=1 https://github.com/opencv/opencv_contrib.git

更新 apt 和 dpkg 设置

这些步骤在主机上进行。

aptdpkg 是 Ubuntu 和 Debian 中使用的软件包管理系统。

以下是使用 MultiArch 的设置步骤。

步骤 1. 添加 arm64 和 armhf 的 apt 源

执行 sudo apt edit-sources 为文件末尾添加外部 arch 库。

示例 1:适用于 Ubuntu 23.04 的 arm64 和 armv7

deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-updates main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-updates universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-updates multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-backports main restricted universe multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-security main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-security universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports lunar-security multiverse

示例 2:适用于 Ubuntu 23.10 的 arm64 和 armv7

deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-updates main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-updates universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-updates multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-backports main restricted universe multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-security main restricted
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-security universe
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports mantic-security multiverse

步骤 2. 更新 apt 数据库

更新 apt 数据库以应用新的 apt 源。

执行 sudo apt update

sudo apt update

步骤 3. 更新 dpkg 设置

更新 dpkg 设置以支持外来架构。

执行 sudo dpkg --add-architecture arm64 和/或 sudo dpkg --add-architecture armhf

sudo dpkg --add-architecture arm64
sudo dpkg --add-architecture armhf

sudo dpkg --print-architecture 显示的是主机架构。

sudo dpkg --print-architecture
amd64

并且 sudo dpkg --print-foreign-architectures 显示的是受支持的外来架构。

sudo dpkg --print-foreign-architectures
arm64
armhf

确认有效的 pkg-config

使用 MultiArch,每个架构的多个共享库和 pkg-config 信息都存储在 /usr/lib 中。

/usr
+ lib
+ aarch64-linux-gnu - arm64 的共享库
+ pkgconfig - arm64 库的 pkg-config 文件
+ arm-linux-gnueabihf - armhf 的共享库
+ pkgconfig - armhf 库的 pkg-config 文件
+ share
+ pkgconfig - pkg-config 文件(用于头文件)

确认通过 PKG_CONFIG_PATHPKG_CONFIG_LIBDIRPKG_CONFIG_SYSROOT_DIR 选项工作 pkg-config

对于 aarch64

PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/ \
pkg-config --list-all

对于 armv7

PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf \
PKG_CONFIG_SYSROOT_DIR=/ \
pkg-config --list-all

交叉编译 aarch64

以下是为目标(aarch64)在主机(x86-64)上进行编译。

步骤 1. 安装外部库以备目标安装在主机

此步骤在主机上执行。

在主机(x86-64)中安装目标(arm64)的 libfreetype-dev、libharfbuzz-dev 和 FFmpeg 包。

sudo apt install -y \
libavcodec-dev:arm64 \
libavformat-dev:arm64 \
libavutil-dev:arm64 \
libswscale-dev:arm64 \
libfreetype-dev:arm64 \
libharfbuzz-dev:arm64

如果您要启用 Python 3 封装器,也安装以下软件包。

sudo apt install -y \
libpython3-dev:arm64

如果成功,pkg-config 可以显示有关这些软件包的信息。

对于 Freetype2 和 Harfbuzz

PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/ \
pkg-config freetype2 harfbuzz --cflags --libs
-I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -L/usr/lib/aarch64-linux-gnu -lfreetype -lharfbuzz

对于 FFmpeg

PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/ \
pkg-config libavcodec libavformat libavutil libswscale --cflags --libs
-I/usr/include/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -lavcodec -lavformat -lavutil -lswscale

步骤 2. 配置 OpenCV 设置

此步骤在主机上执行。

执行 cmake 为 aarch64 进行交叉编译配置。

注意
-DCMAKE_TOOLCHAIN_FILE 应是绝对/实际文件路径,而不是相对路径。
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/ \
cmake -S opencv \
-B build4-full_arm64 \
-DCMAKE_TOOLCHAIN_FILE=/home/kmtr/work/opencv/platforms/linux/aarch64-gnu.toolchain.cmake \
-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules \
-GNinja

如果您想要启用 Python 3 封装器,需要额外的选项。

PYTHON3_REALPATH=`realpath /usr/bin/python3`
PYTHON3_BASENAME=`basename ${PYTHON3_REALPATH}`
PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/ \
cmake -S opencv \
-B build4-full_arm64 \
-DCMAKE_TOOLCHAIN_FILE=/home/kmtr/work/opencv/platforms/linux/aarch64-gnu.toolchain.cmake \
-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules \
-DPYTHON3_NUMPY_INCLUDE_DIRS="/usr/local/lib/${PYTHON3_BASENAME}/dist-packages/numpy/core/include/" \
-DPYTHON3_INCLUDE_PATH="/usr/include/${PYTHON3_BASENAME};/usr/include/" \
-DPYTHON3_LIBRARIES=`find /usr/lib/aarch64-linux-gnu/ -name libpython*.so` \
-DPYTHON3_EXECUTABLE="/usr/bin/${PYTHON3_BASENAME}" \
-DPYTHON3_CVPY_SUFFIX=".so" \
-GNinja
注意
最后,需要“python3.XX”字符串。因此,此脚本会生成它。
  • 从“/usr/bin/python3”获取到“/usr/bin/python3.xx”的真实路径。
  • 从“/usr/bin/python3.xx”获取到基本名称“pyhton3.xx”。

以下是 cmake 输出。

  • 主机Linux x86_64
  • 目标Linux aarch64
  • FFmpeg 可用。
-- OpenCV 4.8.0-dev 的常规配置 =====================================
-- 版本控制:408730b
--
-- 额外的模块
-- 位置(额外):/home/kmtr/work/opencv_contrib/modules
-- 版本控制(额外):faa5468
--
-- 平台
-- 时间戳:2023-12-01T22:02:14Z
-- 主机:Linux 6.5.0-13-generic x86_64
-- 目标:Linux 1 aarch64
-- CMake:3.27.4
-- CMake 生成器:Ninja
-- CMake 构建工具:/usr/bin/ninja
-- 配置:发布
--
-- CPU/硬件功能
-- 基准:NEON FP16
-- 必需:NEON
-- 已禁用:VFPV3
-- 调度代码生成:NEON_DOTPROD NEON_FP16 NEON_BF16
-- 请求:NEON_FP16 NEON_BF16 NEON_DOTPROD
-- NEON_DOTPROD(1 个文件):+ NEON_DOTPROD
-- NEON_FP16(2 个文件):+ NEON_FP16
-- NEON_BF16(0 个文件):+ NEON_BF16
--
-- C/C++
-- 作为动态库构建?是
-- C++ 标准:11
-- C++ 编译器:/usr/bin/aarch64-linux-gnu-g++(版本 13.2.0)
:
:
--
-- 视频输入/输出
-- DC1394:否
-- FFMPEG:是
-- avcodec:是(60.3.100)
-- avformat:是(60.3.100)
-- avutil:是(58.2.100)
-- swscale:是(7.1.100)
-- avresample:否
-- GStreamer:否
-- v4l/v4l2:是(linux/videodev2.h)
--

如果能够启用 Python 3 封装器,Python 3:部分会显示更多信息。

--
-- Python 3
-- 解释器:/usr/bin/python3.11(版本 3.11.6)
-- 库:/usr/lib/aarch64-linux-gnu/libpython3.11.so
-- numpy:/usr/local/lib/python3.11/dist-packages/numpy/core/include/(版本未定义——无法探测,因为是交叉编译)
-- 安装路径:lib/python3.11/dist-packages/cv2/python-3.11
--
-- Python(用于构建):/usr/bin/python3.11
--

步骤 3. 构建并归档 OpenCV 库和头文件

此步骤位于主机中。

构建并安装。(此 安装仅意味着将项目复制到 安装文件夹中。)

cmake --build build4-full_arm64
sudo cmake --install build4-full_arm64

使用 tar 命令将项目(构建的库和头文件)归档到 opencv_arm64.tgz 中。

tar czvf opencv_arm64.tgz -C build4-full_arm64/install .

并将 opencv_arm64.tgz 发送到目标。

步骤 4. 在目标安装依赖库

此步骤在目标系统上执行。

在目标安装依赖运行时库以用于 OpenCV/OpenCV 附加库。

sudo apt install -y \
libavcodec60 \
libavformat60 \
libavutil58 \
libswscale7 \
libfreetype6 \
libharfbuzz0b
sudo ldconfig

如果您要启用 Python 3 封装器,也安装以下软件包。

sudo apt install -y \
python3-minimal \
python3-numpy
警告
如果运行时库和/或程序的版本增加,apt package 名称可能会更改(例如,Ubuntu 23.04 使用 libswscale6,但 Ubuntu 23.10 使用 libswscale7)。使用 apt search 命令或 https://packages.ubuntu.com/ 查找它。
警告

主机和目标之间的外部库版本应该相同。请尽可能同时更新至最新版本库。

即使主机和目标之间的操作系统版本相同,由于对库进行了另外更新,其版本也可能不同。这会导致意外问题。

例如)

  • 在主机上,OpenCV 已使用外部 libA (v1.0) 为目标构建。
  • libA (v1.1) 可能已更新。
  • 在目标上,已安装 libA (v1.1) 以使用 OpenCV。
  • 在这种情况下,libA 的版本在编译和运行之间不同。
警告

如果您忘记/不匹配安装某些必需库,OpenCV 将无法正常工作。

ldd 命令可以检测依存关系。如果有任何“未找到”,请安装必需的库。

ldd /usr/local/lib/libopencv_freetype.so

(不好)freetype 模块需要 libharfbuzz.so.0,但它尚未安装。

linux-vdso.so.1 (0xABCDEFG01234567)
libopencv_imgproc.so.408 => /usr/local/lib/libopencv_imgproc.so.408 (0xABCDEF001234567)
libfreetype.so.6 => /lib/aarch64-linux-gnu/libfreetype.so.6 (0xABCDEF001234567)
libharfbuzz.so.0 => 未找到
libopencv_core.so.408 => /usr/local/lib/libopencv_core.so.408 (0xABCDEF001234567)
:

(好)从 freetype 模块需要的所有库均已安装。

linux-vdso.so.1 (0xABCDEFG01234567)
libopencv_imgproc.so.408 => /usr/local/lib/libopencv_imgproc.so.408 (0xABCDEF001234567)
libfreetype.so.6 => /lib/aarch64-linux-gnu/libfreetype.so.6 (0xABCDEF001234567)
libharfbuzz.so.0 => /lib/aarch64-linux-gnu/libharfbuzz.so.0 (0xABCDEF001234567)
libopencv_core.so.408 => /usr/local/lib/libopencv_core.so.408 (0xABCDEF001234567)
:

第 5 步。将 OpenCV 库安装到目标

此步骤在目标上。

从主机接收 opencv_arm64.tgz(在步骤 3 中生成),并提取到 /usr/local

sudo tar zxvf opencv_arm64.tgz -C /usr/local
sudo ldconfig

您可以像自编译一样使用 OpenCV 库。以下是以 OpenCV 样例代码。在目标上编译并运行它。

Makefile

a.out : main.cpp
g++ main.cpp -o a.out \
-I/usr/local/include/opencv4 \
-lopencv_core

main.cpp

#include <iostream>
#include <opencv2/core.hpp>
int main(void)
{
std::cout << cv::getBuildInformation() << std::endl;
return 0;
}
const String & getBuildInformation()
返回完整配置时间 CMake 输出。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3

执行 make 并运行它。

make a.out
./a.out

如果您希望启用 Python 3 封装器,执行以下命令以确认。

python3 -c "import cv2; print(cv2.getBuildInformation())"

交叉编译到 armv7

下面是为目标(armhf)在主机(x86-64)上编译。

  • 为了解决依赖项,需要 linux-libc-dev:armhf
  • 为了使用 neon 优化,需要 -DENABLE_NEON=ON
sudo apt install -y \
linux-libc-dev:armhf \
libavcodec-dev:armhf \
libavformat-dev:armhf \
libavutil-dev:armhf \
libswscale-dev:armhf \
libfreetype-dev:armhf \
libharfbuzz-dev:armhf
PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig \
PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf \
PKG_CONFIG_SYSROOT_DIR=/ \
cmake -S opencv \
-B build4-full_armhf \
-DENABLE_NEON=ON \
-DCMAKE_TOOLCHAIN_FILE=/home/kmtr/work/opencv/platforms/linux/arm-gnueabi.toolchain.cmake \
-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules \
-GNinja
cmake --build build4-full_armhf
sudo cmake --install build4-full_armhf
tar czvf opencv_armhf.tgz -C build4-full_armhf/install .

以下是 cmake 输出。

  • 主机Linux x86_64
  • 目标Linux arm
  • FFmpeg 可用。
-- OpenCV 4.8.0-dev 的常规配置 =====================================
-- 版本控制:408730b
--
-- 额外的模块
-- 位置(额外):/home/kmtr/work/opencv_contrib/modules
-- 版本控制(额外):faa5468
--
-- 平台
-- 时间戳: 2023-12-02T03:39:58Z
-- 主机:Linux 6.5.0-13-generic x86_64
-- 目标: Linux 1 arm
-- CMake:3.27.4
-- CMake 生成器:Ninja
-- CMake 构建工具:/usr/bin/ninja
-- 配置:发布
--
-- CPU/硬件功能
-- 基线: NEON
-- 请求: DETECT
-- 必需:NEON
-- 已禁用:VFPV3
--
-- C/C++
-- 作为动态库构建?是
-- C++ 标准:11
-- C++ 编译器: /usr/bin/arm-linux-gnueabihf-g++ (版本 13.2.0)
:
:
--
-- 视频输入/输出
-- DC1394:否
-- FFMPEG:是
-- avcodec:是(60.3.100)
-- avformat:是(60.3.100)
-- avutil:是(58.2.100)
-- swscale:是(7.1.100)
-- avresample:否
-- GStreamer:否
-- v4l/v4l2:是(linux/videodev2.h)
--