跳到主要内容
YOLOv8 模型移植到高通机器人 RB5 平台指南 | 极客日志
Python AI 算法
YOLOv8 模型移植到高通机器人 RB5 平台指南 YOLOv8 目标检测模型在高通机器人 RB5 平台的完整部署流程。涵盖 PyTorch 转 ONNX、ONNX 转 QNN 格式、INT8 量化优化及 HTP 加速器配置。包含环境搭建、模型转换命令、C++ 推理应用开发示例及常见问题解决方案。通过 qnn-onnx-converter 和 qnn-model-lib-generator 工具链实现从训练模型到嵌入式设备的高效推理,提供性能优化建议与预期 FPS 参考。
云朵棉花糖 发布于 2026/4/9 更新于 2026/4/23 3 浏览前言
随着边缘端 AI 推理需求的增长,将深度学习模型部署到嵌入式平台成为许多开发者的关注焦点。本文将详细介绍如何将 Ultralytics YOLOv8 训练后的目标检测模型移植到高通机器人 RB5 平台上运行,涵盖从 PyTorch 模型到最终部署的完整流程,并提供常见问题的解决方案和性能优化建议。
1. 概述
1.1 背景介绍
本文档详细介绍如何将 Ultralytics YOLOv8 训练后的目标检测模型移植到高通机器人 RB5 平台(Robotics RB5)上运行。RB5 平台是一款强大的机器人开发平台,搭载 Qualcomm QRB5165 处理器,支持 AI 加速和 5G 连接,非常适合边缘端 AI 推理任务。
1.2 模型移植流程
模型移植的完整流程如下:
YOLOv8 PyTorch 模型 (.pt) → ONNX 格式 (.onnx)
ONNX 模型 → QNN 模型(通过 qnn-onnx-converter 转换并可选量化)
QNN 模型 → 模型库 (.so)(通过 qnn-model-lib-generator 编译)
模型库 → 上下文二进制 (.bin)(通过 qnn-context-binary-generator 生成缓存)
部署到 RB5 设备运行推理
1.3 硬件加速器选择
高通机器人 RB5 平台支持多种硬件加速器:
加速器 说明 适用场景 CPU Kryo 585 八核处理器 通用计算,调试验证 GPU Adreno 650 GPU FP16/FP32 推理,图形处理 HTP/DSP Hexagon Tensor Processor INT8 量化推理,最佳性能功耗比
2. 环境准备
2.1 主机开发环境要求
开发主机需满足以下要求:
操作系统:Ubuntu 22.04 LTS(推荐)或 Ubuntu 20.04 LTS
Python 版本:Python 3.8 或 3.10
内存:建议 16GB 或以上
存储空间:至少 50GB 可用空间
2.2 安装 QNN SDK
从高通开发者网站下载高通® 神经处理 SDK(QNN SDK)。
解压 SDK 并初始化环境:
unzip qairt_sdk_v2.x.x.zip -d ~/qnn
export QNN_SDK_ROOT=~/qnn/qairt/v2.x.x
source $QNN_SDK_ROOT /bin/envsetup.sh
2.3 配置 QNN 环境变量
在 ~/.bashrc 文件中添加以下配置:
export QNN_SDK_ROOT=/path/to/qnn/qairt/v2.x.x
export PATH=$QNN_SDK_ROOT /bin/x86_64-linux-clang:$PATH
export LD_LIBRARY_PATH=$QNN_SDK_ROOT /lib/x86_64-linux-clang:$LD_LIBRARY_PATH
PYTHONPATH= /lib/python:
export
$QNN_SDK_ROOT
$PYTHONPATH
2.4 安装 Python 依赖 python3 -m venv qnn_env
source qnn_env/bin/activate
pip install ultralytics
pip install onnx==1.17.0
pip install onnxruntime==1.22.0
pip install numpy opencv-python
3. YOLOv8 模型导出为 ONNX
3.1 导出命令 使用 Ultralytics 提供的导出功能将 PyTorch 模型转换为 ONNX 格式:
from ultralytics import YOLO
model = YOLO("path/to/your/best.pt" )
model.export(format ="onnx" , imgsz=[640 ,640 ],
opset=12 ,
simplify=True ,
dynamic=False
3.2 关键导出参数说明 参数 说明 format 导出格式,设为 'onnx' imgsz 输入图像尺寸,如 [640,640],需与训练时保持一致 opset ONNX opset 版本,推荐 11 或 12 以获得最佳 QNN 兼容性 simplify 是否简化模型图,建议设为 True dynamic 动态输入大小,QNN 不支持,必须设为 False
3.3 验证 ONNX 模型 import onnx
import onnxruntime as ort
import numpy as np
model = onnx.load("best.onnx" )
onnx.checker.check_model(model)
print ("ONNX 模型验证通过" )
print (f"输入:{[i.name for i in model.graph.input ]} " )
print (f"输出:{[o.name for o in model.graph.output]} " )
session = ort.InferenceSession("best.onnx" )
input_name = session.get_inputs()[0 ].name
test_input = np.random.rand(1 ,3 ,640 ,640 ).astype(np.float32)
outputs = session.run(None ,{input_name: test_input})
print (f"输出形状:{outputs[0 ].shape} " )
4. ONNX 模型转换为 QNN 模型
4.1 使用 qnn-onnx-converter 转换 QNN SDK 提供了 qnn-onnx-converter 工具将 ONNX 模型转换为 QNN C++ 模型格式:
qnn-onnx-converter \
--input_network best.onnx \
--output_path best.cpp \
--input_dim "images" 1,3,640,640
qnn-onnx-converter \
--input_network best.onnx \
--output_path best.cpp \
--input_dim "images" 1,3,640,640 \
--out_name output0
4.2 转换参数详解 参数 说明 --input_network输入 ONNX 模型文件路径 --output_path输出 QNN C++ 模型文件路径 --input_dim输入层名称和维度,格式:'name' N,C,H,W --out_name指定输出节点名称(可选) --input_list校准数据列表文件,提供后将在转换时同时完成量化
4.3 验证转换结果 转换完成后会生成 .cpp 和 .bin 文件,可通过编译生成模型库来验证:
qnn-model-lib-generator \
-c best.cpp \
-b best.bin \
-o model_libs/
5. 模型量化
5.1 量化概述 要在 Hexagon Tensor Processor (HTP) 上运行模型,必须将模型量化为 INT8 或 INT16 格式。在 QNN SDK 中,量化可以在模型转换阶段通过 qnn-onnx-converter 的 --input_list 参数一步完成,也可以单独进行。量化过程包括两个步骤:权重和偏置量化(静态)以及激活层量化(需要校准数据)。
5.2 准备校准数据 量化需要一组代表性的输入数据作为校准集。创建 Python 脚本生成 .raw 格式的校准数据:
import numpy as np
import cv2
import os
def preprocess_image (image_path, input_size=(640 ,640 ) ):
"""预处理图像为 QNN 所需格式"""
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, input_size)
img = img.astype(np.float32)/255.0
return img
calib_images = ["image1.jpg" ,"image2.jpg" ,...]
for i, img_path in enumerate (calib_images):
data = preprocess_image(img_path)
raw_path = f"calib_data/input_{i} .raw"
data.tofile(raw_path)
with open ("input_list.txt" ,"w" ) as f:
for i in range (len (calib_images)):
f.write(f"calib_data/input_{i} .raw\n" )
5.3 执行量化 在 QNN SDK 中,量化集成在 qnn-onnx-converter 转换步骤中。通过提供 --input_list 参数指定校准数据,即可在转换时完成 INT8 量化:
qnn-onnx-converter \
--input_network best.onnx \
--output_path best_quantized.cpp \
--input_dim "images" 1,3,640,640 \
--input_list input_list.txt \
--act_bw8 \
--weight_bw8
5.4 量化参数说明 参数 说明 --input_list校准数据列表文件路径,提供后启用量化 --act_bw激活值位宽,默认 8,可选 16 --weight_bw权重位宽,默认 8,可选 16 --float_bw浮点位宽,可选 16 或 32
6. 模型库生成与上下文二进制缓存
6.1 概述 QNN SDK 采用两步流程将转换后的模型编译为设备可执行格式:先通过 qnn-model-lib-generator 生成目标平台的模型库(.so),再通过 qnn-context-binary-generator 生成上下文二进制缓存(.bin),这可以显著减少运行时的初始化时间。
6.2 生成模型库 将量化后的 QNN 模型编译为目标平台(aarch64)的模型库:
qnn-model-lib-generator \
-c best_quantized.cpp \
-b best_quantized.bin \
-o model_libs/ \
-t aarch64-ubuntu-gcc7.5
6.3 生成上下文二进制缓存 针对 RB5 平台(QRB5165 SoC)生成 HTP 上下文二进制缓存:
qnn-context-binary-generator \
--model model_libs/aarch64-ubuntu-gcc7.5/libmodel.so \
--backend libQnnHtp.so \
--output_dir context_binary/
qnn-context-binary-generator \
--model model_libs/aarch64-ubuntu-gcc7.5/libmodel.so \
--backend libQnnHtp.so \
--output_dir context_binary/ \
--config_file htp_config.json
6.4 验证生成结果
7. 模型部署到 RB5 设备
7.1 连接设备
7.2 部署 QNN 运行时库 adb push $QNN_SDK_ROOT /lib/aarch64-ubuntu-gcc7.5/* /data/qnn/
adb push $QNN_SDK_ROOT /lib/hexagon-v68/unsigned/* /data/qnn/
在设备上配置环境变量(添加到 ~/.bashrc):
export PATH=$PATH :/data/qnn/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH :/data/qnn/
export ADSP_LIBRARY_PATH="/data/qnn:/system/lib/rfsa/adsp:/system/vendor/lib/rfsa/adsp:/dsp"
7.3 部署模型文件 adb shell mkdir -p /data/models/yolov8
adb push context_binary/model.bin /data/models/yolov8/
adb push test_images/ /data/models/yolov8/test_images/
7.4 使用 qnn-net-run 测试 echo "/data/models/yolov8/test_images/test.raw" > /data/models/yolov8/test_list.txt
qnn-net-run \
--backend libQnnHtp.so \
--retrieve_context /data/models/yolov8/model.bin \
--input_list /data/models/yolov8/test_list.txt
8. 推理应用开发
8.1 C++ 应用开发 以下是使用 QNN C API 进行推理的示例代码框架:
#include "QNN/QNNInterface.h"
#include "QNN/QNNCommon.h"
#include "QNN/QNNTypes.h"
#include "QNN/QNNContext.h"
#include "QNN/QNNGraph.h"
#include "QNN/QNNTensor.h"
#include "QNN/HTP/QNNHtpDevice.h"
#include <dlfcn.h>
#include <vector>
#include <string>
#include <cstring>
typedef QNN_ErrorHandle_t (*QNNInterfaceGetProvidersFn_t) (const QNNInterface_t*** providerList,uint32_t * numProviders) ;
struct QNNRuntime {
void * backendHandle = nullptr ;
QNNInterface_t qnnInterface;
QNN_BackendHandle_t backendH = nullptr ;
QNN_ContextHandle_t contextH = nullptr ;
QNN_GraphHandle_t graphH = nullptr ;
};
bool initQNN (QNNRuntime& rt,const std::string& contextBinPath) {
rt.backendHandle = dlopen ("libQnnHtp.so" , RTLD_NOW | RTLD_LOCAL);
if (!rt.backendHandle) return false ;
auto getProviders = (QNNInterfaceGetProvidersFn_t)dlsym (rt.backendHandle,"QNNInterface_getProviders" );
const QNNInterface_t** providerList = nullptr ;
uint32_t numProviders = 0 ;
getProviders (&providerList,&numProviders);
rt.qnnInterface = *providerList[0 ];
rt.qnnInterface.QNN_INTERFACE_VER_NAME.backendCreate (nullptr ,nullptr ,&rt.backendH);
...
return true ;
}
void runInference (QNNRuntime& rt,float * inputData, size_t inputSize) {
QNN_Tensor_t inputTensor = {};
QNN_Tensor_t outputTensor = {};
rt.qnnInterface.QNN_INTERFACE_VER_NAME.graphExecute (
rt.graphH,&inputTensor,1 ,&outputTensor,1 ,nullptr ,nullptr );
}
8.2 编译命令 g++ -std=c++17 -o yolov8_inference main.cpp \
-I/data/qnn/include/ \
-L/data/qnn/ -lQnnHtp-ldl \
`pkg-config --cflags --libs opencv`
8.3 后处理逻辑 YOLOv8 输出格式为 [1, 84, 8400](以 80 类 COCO 数据集为例),需要进行后处理:
struct Detection {
float x, y, w, h;
float confidence;
int class_id;
};
std::vector<Detection> postprocess (float * output,
float conf_thresh,
float nms_thresh) {
std::vector<Detection> detections;
for (int i = 0 ; i < 8400 ; i++){
float x = output[0 *8400 + i];
float y = output[1 *8400 + i];
float w = output[2 *8400 + i];
float h = output[3 *8400 + i];
float max_conf = 0 ;
int max_class = 0 ;
for (int c = 0 ; c < 80 ; c++){
float conf = output[(4 + c)*8400 + i];
if (conf > max_conf){
max_conf = conf;
max_class = c;
}
}
if (max_conf > conf_thresh){
detections.push_back ({x, y, w, h, max_conf, max_class});
}
}
return applyNMS (detections, nms_thresh);
}
9. 常见问题与解决方案
9.1 ONNX 转换失败 问题 :qnn-onnx-converter 报告不支持的算子
使用较低的 opset 版本(如 opset=11)重新导出 ONNX
使用 onnx-simplifier 简化模型图
对于 5D 张量操作(如某些 Reshape),可能需要修改模型结构
考虑使用 QNN 自定义算子包(Custom Op Package)实现不支持的算子
9.2 量化后精度下降
增加校准数据集大小(建议 50-100 张代表性图像)
使用 FP16 激活值 + INT8 权重的混合量化
尝试 INT16 量化以获得更好精度
在 qnn-onnx-converter 中使用 --act_bw 16 提高激活值精度
9.3 HTP 运行时错误
确保模型已正确量化(非量化模型无法在 HTP 上运行)
检查 ADSP_LIBRARY_PATH 环境变量配置
确认 DSP 签名库已正确部署
使用 qnn-context-binary-generator 为目标 SoC 生成上下文二进制缓存
10. 性能优化建议
10.1 模型优化
使用 YOLOv8n(nano)或 YOLOv8s(small)变体以获得更快推理速度
降低输入分辨率(如 320x320 或 416x416)在可接受精度损失范围内
减少检测类别数量以降低输出处理开销
10.2 运行时优化
优先使用 HTP 加速器以获得最佳性能功耗比
使用离线上下文二进制缓存(qnn-context-binary-generator)减少初始化时间
使用 QNN 共享内存缓冲区减少数据拷贝
实现多线程流水线:图像采集、预处理、推理、后处理并行
10.3 预期性能参考 模型 输入尺寸 量化 预期 FPS (HTP) YOLOv8n 640x640 INT8 ~15-25 YOLOv8n 320x320 INT8 ~40-60 YOLOv8s 640x640 INT8 ~8-12
注意 :实际性能受多种因素影响,包括模型复杂度、输入尺寸、量化精度和系统负载等。建议在目标平台上进行实际测试以获得准确的性能数据。
结语 本文详细介绍了将 YOLOv8 模型移植到高通机器人 RB5 平台的完整流程,包括环境搭建、模型转换、量化、部署以及应用开发。通过遵循本文步骤,开发者可以快速在边缘端实现高效的目标检测推理。如果在移植过程中遇到问题,可参考常见问题章节的解决方案,并结合性能优化建议进一步提升模型运行效率。希望本文能为您的嵌入式 AI 项目提供有价值的参考。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online