OpenCV 4.11.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中使用的包管理系统。

以下是使用多架构的设置步骤。

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

执行sudo apt edit-sources以在文件末尾添加外部架构库。

示例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工作正常

使用多架构,每个架构的多个共享库和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. 将目标平台的外部库安装到宿主机

此步骤在宿主机上执行。

将 libfreetype-dev、libharfbuzz-dev 和 FFmpeg 包(arm64 版)安装到宿主机 (x86-64) 上。

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" 到 "python3.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
-- 配置: Release
--
-- CPU/HW 特性
-- 基线: 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)
:
:
--
-- 视频 I/O
-- 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 库和头文件

此步骤在宿主机上执行。

构建和安装。(此处的“安装”仅指将构件复制到 `install` 文件夹。)

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 contrib 库的依赖运行时库。

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

如果您想启用Python 3包装器,也请安装这些包。

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

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

即使宿主机和目标平台的操作系统版本相同,由于对库的额外更新,版本也可能不同。这将导致意外问题。

例如:

  • 在宿主机上,OpenCV 已使用目标平台的外部库 A (v1.0) 构建。
  • 库 A (v1.1) 可能已更新。
  • 在目标平台上,安装了库 A (v1.1) 用于 OpenCV。
  • 在这种情况下,库 A 的版本在编译和运行之间存在差异。
警告

如果忘记/错配安装某些必要的库,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; 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
-- 配置: Release
--
-- CPU/HW 特性
-- 基线:NEON
-- 请求:DETECT
-- 需要: NEON
-- 已禁用: VFPV3
--
-- C/C++
-- 构建为动态库?: 是
-- C++ 标准: 11
-- C++ 编译器:/usr/bin/arm-linux-gnueabihf-g++ (版本 13.2.0)
:
:
--
-- 视频 I/O
-- 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)
--