目录

安装qemu模拟器

拉取镜像

运行docker镜像

查看docker的运行情况

进入docker

安装基本环境

编译和运行程序

打包

导入使用

实操1(在docker交叉编译OpenCV4.10源码)

实操2(基于arm64 的OpenCV环境去编写OpenCV代码)


安装qemu模拟器

sudo apt install qemu qemu-user-static
# 如果上面那个不行就使用下面这个
sudo apt install qemu-user-static qemu-system-misc binfmt-support -y
# 还是无法拉取的话就执行这个
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

qemu-aarch64-static 是 QEMU 的一个静态版本,能在 x86 主机上执行 ARM64 架构的 ELF 可执行文件。有了它后,Docker 可以通过 Linux 的 binfmt_misc 自动识别 ARM64 可执行文件,并交给 QEMU 执行。

拉取镜像

docker pull --platform=arm64 ubuntu:20.04

这里我说明一下这个指令的参数:

--platform 表示的是架构平台,比如risc64、arm64、arm32

ubuntu:20.04  表示镜像   系统:版本

运行docker镜像

docker run -it  --name ubuntu_arm64   -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static   -v /home/hwj/rknn/arm64_build:/workspace   ubuntu:20.04 /bin/bash
参数 含义 详细说明
docker run 启动一个新的容器 是创建并运行容器的基本命令
-it 交互式终端模式 -i 让容器保持标准输入开启;-t 分配一个伪终端,让你能进入容器后操作命令行
--name ubuntu_arm64 给容器起名字 容器名为 ubuntu_arm64,方便后续用 docker start/exec/stop ubuntu_arm64 管理
-v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static 挂载 QEMU 模拟器到容器 将宿主机上的 qemu-aarch64-static 二进制文件挂载到容器中,以便 x86 主机能在容器内运行 ARM64 程序(模拟 ARM64 环境)
-v /home/hwj/rknn/arm64_build:/workspace 挂载工作目录 把宿主机的 /home/hwj/rknn/arm64_build 文件夹映射到容器内的 /workspace,这样编译的结果可以直接出现在宿主机上(持久化数据)
ubuntu:20.04 指定镜像 选择基础镜像(这里是 Ubuntu 20.04 版本)
/bin/bash 运行的命令 容器启动后执行 /bin/bash,进入交互式 shell 环境

查看docker的运行情况

docker ps

进入docker

docker exec -it ubuntu_arm64 /bin/bash

这里可以看到,我本地的宿主目录成功挂载到了docker里面的。然后查看当前docker的架构,刚刚好是aarch64的架构,那就是正常的。

安装基本环境

目前docker这边是没问题的了,但是我们缺少编译用的环境也就是gcc这些

apt update
apt install -y build-essential cmake g++ make

编译和运行程序

# 编译
gcc main.c -o main

# 执行
./main

下面可以看到程序是正常执行的。

打包

你可以使用 docker export + docker import
把运行中的容器完整打包为一个 .tar 文件发给别人,
对方导入后能获得一个几乎一样的容器环境(不含历史层信息,但系统内容完整)。

docker export ubuntu_arm64 -o ubuntu_arm64.tar

导入使用

紧接上文,上面成功打包了我原本的docker环境,这个docker包包括我私人配置了各方面的环境,现在其他人的电脑可以去导入这个包然后实现使用我个人配置的好的环境,无需另外去配置。

(在此之前我已经把之前那个镜像容器完全删除了,下面是导入测试)

docker import ubuntu_arm64.tar ubuntu_arm64:20.04
docker run -it \
  --name arm64_build \
  -v /path/on/their/pc:/workspace \
  ubuntu_arm64:imported /bin/bash

这里可以看到,我之前安装的gcc环境依然是在的,所以导入后是可以正常使用的。

实操1(在docker交叉编译OpenCV4.10源码)

拉取源码指令

wget https://github.com/opencv/opencv/archive/refs/tags/4.10.0.zip

解压源码

unzip 4.10.0.zip
# 进入OpenCV源码
cd opencv-4.10.0

这里先创建一个install目录,用于存放编译好的头文件和库文件

mkdir install 

mkdir indluce

mkdir lib

# 创建build文件夹
mkdir build

cd build

执行cmake 、make

如果是用来单纯测试的话使用下面这个cmake去编译(编译速度快,简单上手使用)

cmake \
  -D CMAKE_BUILD_TYPE=Release \
  -D CMAKE_INSTALL_PREFIX=/workspace/opencv-4.10.0/install \
  ..

如果是要用来开发的话建议使用下面这个cmake去编译

执行cmake之前先安装相关的依赖。

# 安装ffmpeg,GStreamer依赖
apt install -y libjpeg-dev libpng-dev libtiff-dev libwebp-dev libopenexr-dev
apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev
apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
apt install libv4l-dev v4l-utils
# 安装GUI依赖支持
apt install libgtk-3-dev
apt install libgl1-mesa-dev libglu1-mesa-dev
cmake \
    -D CMAKE_BUILD_TYPE=RELEASE \
    -D OPENCV_GENERATE_PKGCONFIG=ON \
    -D CMAKE_INSTALL_PREFIX=/workspace/opencv-4.10.0/install \
    -D WITH_V4L=ON \
    -D WITH_GSTREAMER=ON \
    -DWITH_GTK=ON \
    -D WITH_FFMPEG=ON \
    -D BUILD_OPENJPEG:BOOL=ON \
    -D BUILD_opencv_python=OFF \
    -D BUILD_EXAMPLES=OFF \
    ..
  • CMAKE_BUILD_TYPE=Release: 指定编译类型为Release
  • CMAKE_INSTALL_PREFIX=/workspace/opencv-4.10.0/instal: 指定安装路径,头文件和库文件这些,这里我是收集到install这个目录下。
# -j后面跟的数字表示你启用多少cpu核数去进行编译,我这里用16核
make -j16

然后执行

make install

这里我们可以看到生成的库文件(lib)和头文件(include)的都会存放到install这个目录下

实操2(基于arm64 的OpenCV环境去编写OpenCV代码)

上面说到这里成功编译出了OpenCV的库文件和头文件,现在就通过这个库文件和头文件去测试一份OpenCV环境是否可以使用

这里先回到宿主目录去创建文件夹,执行

mkdir test_demo

然后在VSCode打开这个文件夹,把刚刚生成的lib文件夹和includ文件夹粘贴到test_demo文件夹下面,然后创建一个src文件夹和build文件夹,以及CMakeLists.txt 文件,src文件夹下面创建一个main.cc 文件,文件结构如下:

main.cc 文件的内容如下:

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

int main() {
    // 打印 OpenCV 版本
    std::cout << "OpenCV version: " << CV_VERSION << std::endl;

    // 创建一张 400x400 的蓝色图片
    cv::Mat img(400, 400, CV_8UC3, cv::Scalar(255, 0, 0));

    // 在图片上写字
    cv::putText(img, "OpenCV OK!", cv::Point(50, 200),
                cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255, 255), 2);

    // 显示图像(如果没有 GUI 环境,可以注释掉这行)
    // cv::imshow("Test", img);
    // cv::waitKey(0);

    // 保存图片
    cv::imwrite("opencv_test_output.jpg", img);

    std::cout << "Image saved as opencv_test_output.jpg" << std::endl;
    return 0;
}

CMakeLists.txt的内容如下:

cmake_minimum_required(VERSION 3.10)
project(OpenCV_Test)
 
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "-pthread")


# 设置opencv的lib
file(GLOB OpenCV_LIBS "${CMAKE_SOURCE_DIR}/lib/libopencv_*")
 
# 打印找到的 OpenCV 信息
message(STATUS "OpenCV include path: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
 
# 包含头文件
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${CMAKE_SOURCE_DIR}/include/opencv4)

# 查找全部源文件
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
 
# 添加可执行文件
add_executable(main ${SRC})
 
# 链接 OpenCV 库
target_link_libraries(main ${OpenCV_LIBS})
 
 

然后在docker环境下进入到build文件夹,执行cmake ..

然后执行 make 编译,可以看到下面生成了一个可执行文件,在arm64 的docker执行是没问题的

执行

file main

这里可以看到这个可执行文件是属于arm64的。现在把这个可执行文件移植到arm64的开发板去执行试试看。

假如出现了有些库无法找的情况就执行以下下面那个语句 (这里执行压缩指令,因为我这里是使用动态库去连接,也就是说当执行main这个可执行文件的时候库文件才会去链接过去的,所以实际上我们需要打包的也就是库文件和这个可执行文件。)

sudo tar -czvf opencv.tar.gz ./build/ ./lib/

然后把这个压缩包用sftp等等传输方式去传到arm64开发板上,然后去执行下面这个解压缩指令

tar -zxf opencv.tar.gz 

在此执行可执行文件之前,应该去把当前的库目录进行临时设置 LD_LIBRARY_PATH,只在当前的终端有效。(下次开启新的终端还想执行这个可执行文件的话,记得执行下面这个语句)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/你的路径/test_demo/lib

然后进入到build文件夹去执行这个可执行文件。可以看到在arm64开发板也是正常执行的。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐