2. 开发环境搭建:RKNN Toolkit2安装、交叉编译环境配置、Python与C++ SDK选择

好,咱们正式开始动手了。这一章我带你搭环境。别小看这一步,我见过太多人卡在环境上,一卡就是两三天。说白了,环境搭不好,后面全是白搭。

咱们的目标很明确:让你的电脑能跑RKNN模型转换,能让NPU跑起来。我会把Python和C++两条路都讲清楚,你根据自己的项目选就行。

2.1 RKNN Toolkit2 安装——这是第一步

RKNN Toolkit2 是瑞芯微官方出的模型转换工具。它的作用,就是把PyTorch、TensorFlow、ONNX这些框架训练好的模型,转成NPU能识别的.rknn格式。

我个人习惯用Python虚拟环境来装,干净、好管理。你想想看,万一你电脑上同时有好几个项目,依赖版本打架,那多头疼。

2.1.1 环境要求

先看看你的电脑够不够格。我列个表,你对照一下:

项目 最低要求 推荐配置
操作系统 Ubuntu 18.04 / 20.04 Ubuntu 20.04 / 22.04
Python版本 3.6 3.8 或 3.10
内存 8GB 16GB以上
硬盘空间 10GB 20GB以上(模型文件很占地方)
CPU 4核 8核以上(转换大模型时快很多)
注意: 别在Windows上直接装。虽然能折腾,但坑太多。我建议你装个Ubuntu双系统,或者用Docker。我在项目中吃过Windows的亏,后来老老实实换了Ubuntu。

2.1.2 安装步骤

好,咱们开始装。我习惯用conda管理环境,你也可以用venv,看个人喜好。

# 1. 创建虚拟环境(Python 3.8 最稳)
conda create -n rknn_env python=3.8
conda activate rknn_env

# 2. 安装依赖
pip install numpy opencv-python pillow matplotlib

# 3. 下载RKNN Toolkit2
# 从瑞芯微官方GitHub或百度网盘下载
# 我一般用git clone
git clone https://github.com/rockchip-linux/rknn-toolkit2.git

# 4. 进入目录,安装
cd rknn-toolkit2
pip install -r requirements_cp38.txt
pip install packages/rknn_toolkit2-1.5.0-cp38-cp38-linux_x86_64.whl

# 5. 验证安装
python -c "from rknn.api import RKNN; print('安装成功')"
小技巧: 如果你下载慢,可以用国内镜像源。我常用清华源:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名

嗯,这里要注意。不同版本的RKNN Toolkit2对Python版本有要求。比如1.5.0版本支持3.8,1.6.0版本支持3.10。你下载前先看清楚文档,别装错了。

2.2 交叉编译环境配置——让代码在开发板上跑起来

你想想看,咱们的代码是在x86电脑上写的,但最终要跑到ARM架构的开发板上。这就需要一个叫「交叉编译器」的东西。

交叉编译,说白了就是在电脑上编译出能在开发板上运行的二进制文件。我刚开始做嵌入式时,总觉得这步很玄乎,后来发现其实就是装个工具链的事。

2.2.1 安装交叉编译工具链

瑞芯微官方提供了完整的交叉编译工具链。我以RK3588为例,其他芯片类似。

# 1. 下载工具链
# 从瑞芯微官网下载 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz

# 2. 解压到指定目录
tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt/

# 3. 配置环境变量(加到 ~/.bashrc 里)
export PATH=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH
export CC=aarch64-none-linux-gnu-gcc
export CXX=aarch64-none-linux-gnu-g++

# 4. 验证
aarch64-none-linux-gnu-gcc --version
核心要点: 交叉编译工具链的版本要和开发板上的系统匹配。比如你的开发板是Ubuntu 20.04,那工具链的glibc版本就不能太高。我曾经因为版本不匹配,编译出来的程序在板子上跑不起来,排查了半天。

2.2.2 配置CMake交叉编译

实际项目中,我们一般用CMake来管理工程。你需要写一个交叉编译的toolchain文件。

# toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER aarch64-none-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-none-linux-gnu-g++)

set(CMAKE_FIND_ROOT_PATH /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

使用时,这样编译:

mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake
make -j4
我的经验: 第一次交叉编译时,先写个hello world测试一下。能跑通,再上复杂代码。别一上来就编译整个项目,出了问题都不知道是工具链的问题还是代码的问题。

2.3 Python与C++ SDK选择——两条路,看你走哪条

瑞芯微NPU的SDK分Python和C++两套。怎么选?我直接说结论:

  • Python SDK:适合快速验证、原型开发、模型转换。开发效率高,但推理性能稍差。
  • C++ SDK:适合产品落地、性能要求高的场景。推理速度快,但开发周期长。

你想想看,如果你只是做个demo,用Python就够了。但如果你要做量产产品,比如智能摄像头、边缘计算盒子,那必须上C++。

2.3.1 Python SDK 使用示例

Python SDK的安装其实我们在2.1节已经搞定了。这里我直接给个推理的示例:

import cv2
from rknn.api import RKNN

# 创建RKNN对象
rknn = RKNN()

# 加载模型(之前转换好的.rknn文件)
ret = rknn.load_rknn('./model.rknn')
if ret != 0:
    print('加载模型失败')
    exit(-1)

# 初始化运行时环境
ret = rknn.init_runtime(target='rk3588')
if ret != 0:
    print('初始化运行时失败')
    exit(-1)

# 读取图片并预处理
img = cv2.imread('./test.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (224, 224))

# 推理
outputs = rknn.inference(inputs=[img])
print('推理结果:', outputs)

# 释放资源
rknn.release()
注意: Python SDK的推理接口虽然简单,但每次调用都有Python解释器的开销。如果你需要高帧率推理,比如视频流处理,建议用C++。

2.3.2 C++ SDK 使用示例

C++ SDK需要你手动编译。瑞芯微提供了librknn_api.so这个动态库。我一般这样用:

#include <stdio.h>
#include <rknn_api.h>

int main() {
    rknn_context ctx;
    int ret;

    // 1. 初始化
    ret = rknn_init(&ctx, "./model.rknn", 0, 0, NULL);
    if (ret < 0) {
        printf("rknn_init fail! ret=%d\n", ret);
        return -1;
    }

    // 2. 获取输入输出信息
    rknn_input_output_num io_num;
    rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));

    // 3. 设置输入
    rknn_input inputs[1];
    inputs[0].index = 0;
    inputs[0].buf = img_data;  // 你的图像数据
    inputs[0].size = img_size;
    inputs[0].pass_through = 0;
    inputs[0].type = RKNN_TENSOR_UINT8;
    inputs[0].fmt = RKNN_TENSOR_NHWC;

    ret = rknn_inputs_set(ctx, 1, inputs);

    // 4. 运行推理
    ret = rknn_run(ctx, NULL);

    // 5. 获取输出
    rknn_output outputs[1];
    outputs[0].want_float = 1;
    ret = rknn_outputs_get(ctx, 1, outputs, NULL);

    // 6. 处理结果
    float* result = (float*)outputs[0].buf;
    printf("推理结果: %f\n", result[0]);

    // 7. 释放
    rknn_outputs_release(ctx, 1, outputs);
    rknn_destroy(ctx);

    return 0;
}

编译命令:

aarch64-none-linux-gnu-g++ main.cpp -o rknn_infer -lrknn_api -lpthread
避坑指南: 我曾经在C++ SDK上踩过一个坑——内存泄漏。rknn_outputs_get获取的输出缓冲区,用完一定要调用rknn_outputs_release释放。不然跑几个小时,板子就卡死了。

2.4 如何选择——我的建议

好,最后我总结一下我的建议:

  1. 如果你是做算法验证、模型调优:用Python SDK。开发快,调试方便。我平时在电脑上做模型转换和精度验证,都用Python。
  2. 如果你是做产品落地、性能优化:用C++ SDK。虽然开发慢,但推理速度快,资源占用低。我做的几个量产项目,全部用的C++。
  3. 如果你不确定:先用Python跑通流程,再逐步迁移到C++。这是最稳妥的做法。

嗯,环境搭建这部分就到这里。下一章咱们开始讲模型转换,那才是真正有意思的地方。