上一个教程: 基于 ARM 的 Linux 系统的交叉编译
下一个教程: 使用 CUDA 为 Tegra 构建 OpenCV
| |
| 原始作者 | Kumataro |
| 兼容性 | Ubuntu >=23.04 |
| OpenCV >=4.8.0 |
- 警告
- 本教程可能包含过时信息。
什么是 "MultiArch"
OpenCV 可能会使用许多第三方库来处理视频和图像解码、渲染、加速和复杂的数学算法。这些第三方组件由 CMake 在构建主机上查找。交叉编译允许为异构架构或操作系统构建 OpenCV,但我们会失去庞大的组件支持,必须单独交叉编译每个依赖项并在 OpenCV 构建期间指向它们。
Debian/Ubuntu MultiArch 有助于解决此问题。它允许在宿主机系统上安装多种异构架构库,并在 OpenCV 依赖项解析期间使用它们。
- 警告
- 遵循这些步骤会使您的 Linux 环境变得有些“脏乱”。如果可能,最好使用虚拟机 (VM) 或容器(例如 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 创建
- 在您的主目录下创建工作文件夹。
- 从仓库克隆 OpenCV 和 OpenCV Contrib 到 work 目录。
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 设置
这些步骤在宿主机上执行。
apt 和 dpkg 是 Ubuntu 和 Debian 中使用的包管理系统。
以下是使用 MultiArch 的设置步骤。
步骤 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。
步骤 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_PATH、PKG_CONFIG_LIBDIR 和 PKG_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 进行交叉编译
以下是在宿主机 (x86-64) 上为目标机 (aarch64) 进行编译的步骤。
步骤 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 输出。
Host 是 Linux x86_64。
Target 是 Linux aarch64。
- FFmpeg 可用。
-- General configuration for OpenCV 4.8.0-dev =====================================
-- Version control: 408730b
--
-- Extra modules
-- Location (extra): /home/kmtr/work/opencv_contrib/modules
-- Version control (extra): faa5468
--
-- Platform
-- Timestamp: 2023-12-01T22:02:14Z
-- Host: Linux 6.5.0-13-generic x86_64
-- Target: Linux 1 aarch64
-- CMake: 3.27.4
-- CMake generator: Ninja
-- CMake build tool: /usr/bin/ninja
-- Configuration: Release
--
-- CPU/HW features
-- Baseline: NEON FP16
-- required: NEON
-- disabled: VFPV3
-- Dispatched code generation: NEON_DOTPROD NEON_FP16 NEON_BF16
-- requested: NEON_FP16 NEON_BF16 NEON_DOTPROD
-- NEON_DOTPROD (1 files): + NEON_DOTPROD
-- NEON_FP16 (2 files): + NEON_FP16
-- NEON_BF16 (0 files): + NEON_BF16
--
-- C/C++
-- Built as dynamic libs?: YES
-- C++ standard: 11
-- C++ Compiler: /usr/bin/aarch64-linux-gnu-g++ (ver 13.2.0)
:
:
--
-- Video I/O
-- DC1394: NO
-- FFMPEG: YES
-- avcodec: YES (60.3.100)
-- avformat: YES (60.3.100)
-- avutil: YES (58.2.100)
-- swscale: YES (7.1.100)
-- avresample: NO
-- GStreamer: NO
-- v4l/v4l2: YES (linux/videodev2.h)
--
如果启用 Python 3 封装成功,Python 3: 部分会显示更多信息。
--
-- Python 3
-- Interpreter: /usr/bin/python3.11 (ver 3.11.6)
-- Libraries: /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 仅表示将生成文件复制到 install 文件夹。)
cmake --build build4-full_arm64
sudo cmake --install build4-full_arm64
tar czvf opencv_arm64.tgz -C build4-full_arm64/install .
并将 opencv_arm64.tgz 发送到目标机。
步骤 4. 在目标机上安装依赖库
此步骤在目标系统上执行。
在目标机上为 OpenCV/OpenCV contrib 库安装依赖运行时库。
libavcodec60 \
sudo apt install -y \
libavformat60 \
libavutil58 \
libswscale7 \
libfreetype6 \
libharfbuzz0b
如果运行时库和/或程序的版本增加,apt 包名称可能会更改(例如 Ubuntu 23.04 使用
libswscale6,但 Ubuntu 23.10 使用
libswscale7)。请使用
apt search 命令或
https://packages.ubuntu.com/ 查找。
sudo ldconfig
如果您想启用 Python 3 封装,也请安装这些包。
sudo apt install -y \
python3-minimal \
python3-numpy
- 警告
- 宿主机和目标机之间的外部库版本应相同。请尽可能同时更新到最新版本的库。
- 警告
即使宿主机和目标机之间的操作系统版本相同,由于库的额外更新,版本可能有所不同。这将导致意外问题。
例如)
在宿主机上,OpenCV 已使用外部 libA (v1.0) 为目标机构建。
- libA (v1.1) 可能会更新。
- 在目标机上,libA (v1.1) 已安装以使用 OpenCV。
- 在这种情况下,libA 的版本在编译和运行之间存在差异。
- 如果您忘记/未能正确安装某些必要的库,OpenCV 将无法正常工作。
- 警告
ldd 命令可以检测依赖项。如果有任何“未找到”,请安装必要的库。
ldd /usr/local/lib/libopencv_freetype.so
(不正确)freetype module 需要 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 => not found
libopencv_core.so.408 => /usr/local/lib/libopencv_core.so.408 (0xABCDEF001234567)
(正确)freetype modules 所需的所有库都已安装。
:
libharfbuzz.so.0 => /lib/aarch64-linux-gnu/libharfbuzz.so.0 (0xABCDEF001234567)
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 => not found
(正确)freetype modules 所需的所有库都已安装。
:
此步骤在目标机上执行。
从宿主机接收 opencv_arm64.tgz(在步骤 3 生成),并解压到 /usr/local。
sudo tar zxvf opencv_arm64.tgz -C /usr/local
您可以像自主编译一样使用 OpenCV 库。以下是 OpenCV 示例代码。在目标机上编译并运行它。
sudo ldconfig
Makefile
a.out : main.cpp
g++ main.cpp -o a.out \
-I/usr/local/include/opencv4 \
-lopencv_core
main.cpp
#include <opencv2/core.hpp>
#include <iostream>
{
const String & getBuildInformation()
return 0;
}
执行 make 并运行它。
返回完整的配置时 cmake 输出。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
make a.out
./a.out
如果您想启用 Python 3 封装,请执行以下命令进行确认。
python3 -c "import cv2; print(cv2.getBuildInformation())"
以下是在宿主机 (x86-64) 上为目标机 (armhf) 进行编译的步骤。
为了解决依赖项,linux-libc-dev:armhf 是必需的。
- 为了使用 neon 进行优化,
-DENABLE_NEON=ON 是必需的。
- linux-libc-dev:armhf \
sudo apt install -y \
libavcodec-dev:armhf \
libavformat-dev:armhf \
libavutil-dev:armhf \
libswscale-dev:armhf \
libfreetype-dev:armhf \
libharfbuzz-dev:armhf
-B build4-full_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 \
-DENABLE_NEON=ON \
-DCMAKE_TOOLCHAIN_FILE=/home/kmtr/work/opencv/platforms/linux/arm-gnueabi.toolchain.cmake \
cmake --build build4-full_armhf
-DOPENCV_EXTRA_MODULES_PATH=opencv_contrib/modules \
-GNinja
sudo cmake --install build4-full_armhf
tar czvf opencv_armhf.tgz -C build4-full_armhf/install .
Target 是 Linux arm。
以下是 cmake 输出。
Host 是 Linux x86_64。
- -- Timestamp: 2023-12-02T03:39:58Z
- FFmpeg 可用。
-- General configuration for OpenCV 4.8.0-dev =====================================
-- Version control: 408730b
--
-- Extra modules
-- Location (extra): /home/kmtr/work/opencv_contrib/modules
-- Version control (extra): faa5468
--
-- Platform
-- Target: Linux 1 arm
-- Host: Linux 6.5.0-13-generic x86_64
-- 基线: NEON
-- CMake: 3.27.4
-- CMake generator: Ninja
-- CMake build tool: /usr/bin/ninja
-- Configuration: Release
--
-- CPU/HW features
-- 请求: DETECT
-- C++ Compiler: /usr/bin/arm-linux-gnueabihf-g++ (ver 13.2.0)
-- required: NEON
-- disabled: VFPV3
--
-- C/C++
-- Built as dynamic libs?: YES
-- C++ standard: 11
于 2025 年 7 月 3 日星期四 12:14:35 为 OpenCV 生成,由
1.12.0
:
:
--
-- Video I/O
-- DC1394: NO
-- FFMPEG: YES
-- avcodec: YES (60.3.100)
-- avformat: YES (60.3.100)
-- avutil: YES (58.2.100)
-- swscale: YES (7.1.100)
-- avresample: NO
-- GStreamer: NO
-- v4l/v4l2: YES (linux/videodev2.h)
--