3、开发环境搭建:交叉编译工具链安装、OpenCV与TensorFlow Lite库移植、SSH远程调试配置

好,咱们正式开始动手了。

这一章,说白了就是给你的电脑装上「翻译官」和「搬运工」。你想想看,我们写代码是在 x86 的电脑上,但最终要跑在 ARM 的板子上。这两个架构的指令集完全不同,就像中文和英文。交叉编译工具链,就是那个能把你的 C/C++ 代码翻译成 ARM 能听懂的语言的翻译官。

而 OpenCV 和 TensorFlow Lite 的移植,就是把我们常用的视觉和推理库,提前编译成 ARM 能用的版本,然后搬到板子上。至于 SSH 远程调试,嗯,这个最实用——让你不用每次都插屏幕、插键盘,躺在沙发上就能调试板子。

3.1 交叉编译工具链的安装与配置

我个人习惯,先把工具链装好,再谈别的。没有它,后面全是空中楼阁。

3.1.1 什么是交叉编译?

简单说,就是在你的 PC 上(x86 架构),编译出能在 ARM 架构上运行的程序。我在项目中遇到过不少新手,直接在板子上用 gcc 编译,那个速度慢得让人抓狂。一个稍微大点的 OpenCV 项目,在树莓派上编译可能要两三个小时,但在 PC 上交叉编译,十分钟搞定。

3.1.2 安装步骤(以 ARM Cortex-A 系列为例)

我推荐使用 Linaro 提供的工具链,稳定且社区活跃。当然,如果你用的是厂家提供的 SDK,比如 Rockchip 或 NXP 的,直接用他们的也行。

# 下载 ARM 交叉编译工具链(64位)
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz

# 解压到 /opt 目录
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz -C /opt/

# 配置环境变量(建议写入 ~/.bashrc)
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin
export CROSS_COMPILE=aarch64-linux-gnu-
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
小提示: 配置完环境变量后,记得执行 source ~/.bashrc 或者重新打开终端。我曾经忘了这一步,折腾了半小时才发现路径没生效。

3.1.3 验证安装

aarch64-linux-gnu-gcc --version

如果能看到版本信息,恭喜你,翻译官就位了。

3.2 OpenCV 库的交叉编译与移植

OpenCV 的交叉编译,是很多人的噩梦。为什么?因为依赖太多。我刚开始做的时候,也是被各种 undefined reference 折磨得够呛。

3.2.1 准备工作

先下载 OpenCV 源码,我建议用 4.5.x 版本,稳定且对嵌入式友好。

git clone -b 4.5.5 https://github.com/opencv/opencv.git
cd opencv
mkdir build_arm && cd build_arm

3.2.2 配置 CMake

这里要注意,一定要关掉那些不必要的模块,比如 GUI、OpenCL 等,否则编译时间会很长,而且板子上也跑不起来。

cmake -DCMAKE_SYSTEM_NAME=Linux \
      -DCMAKE_SYSTEM_PROCESSOR=aarch64 \
      -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
      -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
      -DCMAKE_INSTALL_PREFIX=/opt/opencv_arm \
      -DWITH_GTK=OFF \
      -DWITH_QT=OFF \
      -DWITH_OPENCL=OFF \
      -DWITH_V4L=ON \
      -DBUILD_opencv_python3=OFF \
      -DBUILD_opencv_java=OFF \
      -DBUILD_EXAMPLES=OFF \
      -DBUILD_TESTS=OFF \
      -DBUILD_PERF_TESTS=OFF \
      ..
避坑指南: 我曾经因为忘记设置 CMAKE_INSTALL_PREFIX,结果编译出来的库散落在系统目录里,移植的时候找都找不到。一定要指定一个干净的输出目录。

3.2.3 编译与安装

make -j4
sudo make install

编译完成后,你会在 /opt/opencv_arm 目录下看到 include、lib、bin 等文件夹。把这些文件夹整个拷贝到板子上,比如放到 /usr/local/opencv 下。

3.2.4 板子上验证

写一个简单的测试程序,交叉编译后传到板子上运行。

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

int main() {
    cv::Mat img = cv::Mat::zeros(100, 100, CV_8UC3);
    std::cout << "OpenCV version: " << CV_VERSION << std::endl;
    std::cout << "Image size: " << img.size() << std::endl;
    return 0;
}
# 交叉编译
aarch64-linux-gnu-g++ test_opencv.cpp -o test_opencv \
    -I /opt/opencv_arm/include/opencv4 \
    -L /opt/opencv_arm/lib \
    -lopencv_core -lopencv_imgproc -lopencv_highgui

# 传到板子上运行
scp test_opencv root@板子IP:/root/
ssh root@板子IP "./test_opencv"

3.3 TensorFlow Lite 库的移植

TFLite 的移植比 OpenCV 简单一些,因为它本身就是为嵌入式设计的。但要注意,它有两种部署方式:一是用 C++ API 直接调用,二是用 Delegate 加速(比如 GPU、NPU)。

3.3.1 下载预编译库(推荐)

如果你不想从源码编译,可以直接下载官方预编译的 ARM64 版本。

# 下载 TFLite C++ 库
wget https://github.com/nicktaj/tensorflow-lite-arm64/releases/download/v2.9.0/libtensorflow_lite_c.so
wget https://github.com/nicktaj/tensorflow-lite-arm64/releases/download/v2.9.0/tensorflow_lite_c_api.h

3.3.2 从源码编译(如果需要自定义)

如果你需要开启 XNNPACK 或 GPU Delegate,建议从源码编译。

git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./tensorflow/lite/tools/make/download_dependencies.sh
./tensorflow/lite/tools/make/build_aarch64_lib.sh

编译完成后,生成的静态库在 tensorflow/lite/tools/make/gen/linux_aarch64/lib/ 下,头文件在 tensorflow/lite/tools/make/downloads/flatbuffers/include/tensorflow/lite/ 下。

个人经验: 我建议用静态库(.a)而不是动态库(.so)。虽然文件大一点,但部署时少了很多依赖问题。你想想看,在板子上缺个 .so 文件,排查起来多头疼。

3.3.3 验证推理

// test_tflite.cpp
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/kernels/register.h"

int main() {
    std::unique_ptr<tflite::FlatBufferModel> model =
        tflite::FlatBufferModel::BuildFromFile("model.tflite");
    if (!model) {
        std::cerr << "Failed to load model" << std::endl;
        return -1;
    }
    std::cout << "Model loaded successfully!" << std::endl;
    return 0;
}

3.4 SSH 远程调试配置

终于到了最爽的部分。SSH 远程调试,说白了就是让你不用再抱着屏幕和键盘到处跑。

3.4.1 板子上开启 SSH 服务

# 安装 SSH 服务(如果没装)
apt-get update
apt-get install openssh-server

# 启动并设置开机自启
systemctl start sshd
systemctl enable sshd

3.4.2 PC 端配置 SSH 免密登录

每次输密码太烦了,我建议配置密钥登录。

# 生成密钥(如果还没有)
ssh-keygen -t rsa -b 4096

# 将公钥拷贝到板子上
ssh-copy-id root@板子IP

3.4.3 使用 VS Code 进行远程开发

我个人强烈推荐 VS Code 的 Remote-SSH 插件。装上之后,你可以在本地写代码,自动同步到板子上编译运行。

  1. 安装 Remote-SSH 插件
  2. 点击左下角绿色按钮,选择 "Connect to Host"
  3. 输入 ssh root@板子IP
  4. 打开板子上的工程目录,开始写代码
核心要点: 远程调试的关键是「本地编辑 + 远程编译 + 远程运行」。你可以在 VS Code 里配置好交叉编译的 task,一键编译并上传到板子执行。效率提升不是一点半点。

3.4.4 文件传输小技巧

除了 scp,我建议用 rsync 来同步文件,它只传输变化的部分,速度更快。

# 同步本地 build 目录到板子
rsync -avz --delete ./build_arm/ root@板子IP:/root/project/build/

3.5 本章小结

嗯,这一章内容不少,但都是实打实的硬功夫。工具链装好了,库移植过去了,SSH 也配通了。接下来,你就可以舒舒服服地坐在电脑前,远程调试你的 AI 模型了。

记住,环境搭建是基础中的基础。我在项目里见过太多人,模型选得再好,算法调得再优,结果环境没搭好,白白浪费了几天时间。所以,别急,一步步来,把地基打牢。

下一章,我们就要开始真正的模型部署了。到时候,你会感谢今天认真搭环境的自己。