1. 概述
RV1126B 是瑞芯微推出的面向前端视觉的高集成度 SoC,采用 14nm 工艺,内置 NPU 算力最高可达 3 TOPS,支持 INT8/FP16 混合精度推理,是智能摄像头、边缘安防等场景的主流芯片方案。
本教程将完整演示 YOLO12 模型从训练权重 → ONNX 导出 → RKNN 转换 → INT8 量化 → 板端部署推理 的全流程。

2. 环境准备
2.1 主机端环境(x86_64 Linux / WSL2)
模型转换在主机完成,需要安装以下工具:
工具 | 版本要求 | 说明 |
Python | 3.8 ~ 3.10 | RKNN-Toolkit2 兼容性最佳 |
RKNN-Toolkit2 | 1.6.x+ | 官方模型转换工具 |
Ultralytics | 8.3.0+ | YOLO12 官方库 |
ONNX | 1.14+ | 中间格式 |
安装步骤:
# 1. 安装 ultralytics(含 YOLO12)
pip install ultralytics
# 2. 安装 RKNN-Toolkit2(从官方下载 whl)
# 下载地址:https://github.com/airockchip/rknn-toolkit2
pip install rknn_toolkit2-1.6.0+xxxxxxxx-cp38-cp38-linux_x86_64.whl
# 3. 验证安装
python -c "from rknn.api import RKNN; print('RKNN OK')"
python -c "from ultralytics import YOLO; print('YOLO OK')"
1.1 开发板端环境
RV1126B 开发板需预装:
官方 Linux SDK(Buildroot / Debian)
librknnrt.so 运行时库
rknn_server 服务(用于远程调试)
Python3 + rknn-toolkit-lite2(可选,Python 推理用)
2. 方法一:Ultralytics 一键导出 RKNN(最简方式)
Ultralytics 8.3.0+ 已原生支持 RKNN 格式导出,指定 target_platform='rv1126b' 即可一键生成。
2.1 Python 脚本导出
from ultralytics import YOLO
# 加载 YOLO12 模型(n/s/m/l 按需选择)
model = YOLO('yolo12n.pt')
# 导出为 RV1126B 专用 RKNN 模型
model.export(
format='rknn',
name='rv1126b', # 目标平台
imgsz=640, # 输入尺寸
batch=1,
half=False # FP16 开关
)
1.2 CLI 命令行导出
# FP16 精度模型
yolo export model=yolo12n.pt format=rknn name=rv1126b imgsz=640
# INT8 量化模型(需提供校准数据集)
yolo export model=yolo12n.pt format=rknn name=rv1126b imgsz=640 int8=True data=coco128.yaml
导出完成后,在 yolo12n_rknn_model/ 目录下生成 .rknn 文件,可直接跳至第五章部署。
2. 方法二:手动 ONNX → RKNN 全流程(可控性强)
如果需要精细控制量化参数、调试中间层,推荐使用手动转换流程。
2.1 步骤 1:导出 ONNX 模型
# 导出 ONNX(默认 opset=17,动态 batch 关闭)
yolo export model=yolo12n.pt format=onnx imgsz=640 simplify=True
关键参数说明:
simplify=True:使用 onnxsim 简化计算图,提升 NPU 适配率
opset=17:RKNN-Toolkit2 对 opset 12~17 支持最好
导出后生成 yolo12n.onnx
1.3 步骤 2:准备校准数据集
INT8 量化需要 100~500 张代表性图片作为校准集。创建 dataset.txt,每行一个图片路径:
./calib_images/000001.jpg
./calib_images/000002.jpg
./calib_images/000003.jpg
...
校准图片需与实际场景分布一致,建议从训练集中随机抽取,无需标注。
1.3 步骤 3:RKNN 转换脚本
创建 convert_rknn.py:
from rknn.api import RKNN
# ========== 配置参数 ==========
ONNX_MODEL = 'yolo12n.onnx'
RKNN_MODEL = 'yolo12n_rv1126b_int8.rknn'
DATASET = './dataset.txt'
QUANTIZE_ON = True # True=INT8量化, False=FP16
TARGET_PLATFORM = 'rv1126b'
if __name__ == '__main__':
# 1. 创建 RKNN 对象
rknn = RKNN(verbose=True)
# 2. 模型配置
print('--> Config model')
rknn.config(
mean_values=[[0, 0, 0]], # YOLO 归一化方式: pixel/255
std_values=[[255, 255, 255]],
target_platform=TARGET_PLATFORM,
quantized_algorithm='normal', # 量化算法: normal/mmse
quantized_dtype='asymmetric_quantized-8',
optimization_level=3 # 优化等级 0~3
)
print('done')
# 3. 加载 ONNX 模型
print('--> Loading ONNX model')
ret = rknn.load_onnx(model=ONNX_MODEL)
if ret != 0:
print('Load ONNX failed!')
exit(ret)
print('done')
# 4. 构建模型(含量化)
print('--> Building model')
ret = rknn.build(
do_quantization=QUANTIZE_ON,
dataset=DATASET,
rknn_batch_size=1
)
if ret != 0:
print('Build model failed!')
exit(ret)
print('done')
# 5. 导出 RKNN 模型文件
print('--> Export RKNN model')
ret = rknn.export_rknn(RKNN_MODEL)
if ret != 0:
print('Export RKNN failed!')
exit(ret)
print(f'Model saved: {RKNN_MODEL}')
# 6. 释放资源
rknn.release()
执行转换:
python convert_rknn.py
1.3 转换参数调优建议
参数 | 推荐值 | 说明 |
quantized_algorithm | mmse | 精度优先,比 normal 高 1~2% mAP |
optimization_level | 3 | 最高优化等级,合并算子、去除冗余 |
mean_values / std_values | [0,0,0] / [255,255,255] | YOLO 系列标准归一化 |
inputs / input_size_list | 自动识别 | 一般无需手动指定 |
注意:YOLO12 引入了注意力机制(Attention),部分算子可能需要回退到 CPU。若转换时报错算子不支持,可尝试降低模型规格(如用 yolo12n 而非 yolo12m),或开启 verbose=True 查看具体不支持算子。
2. 开发板端部署推理
2.1 文件传输
将生成的 .rknn 模型、测试图片推送到开发板:
adb push yolo12n_rv1126b_int8.rknn /userdata/
adb push test.jpg /userdata/
1.4 Python 推理(rknn-toolkit-lite2)
适合快速验证、原型开发。在板端创建 infer_yolo12.py:
import cv2
import numpy as np
from rknnlite.api import RKNNLite
# ========== 配置 ==========
RKNN_MODEL = '/userdata/yolo12n_rv1126b_int8.rknn'
IMG_PATH = '/userdata/test.jpg'
IMG_SIZE = 640
CONF_THRESH = 0.25
NMS_THRESH = 0.45
CLASSES = 80 # COCO 类别数
# COCO 类别名(节选)
CLASS_NAMES = ['person', 'bicycle', 'car', 'motorcycle', ...]
def preprocess(img_path):
"""图像预处理:resize + 归一化 + 通道转换"""
img = cv2.imread(img_path)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
resized = cv2.resize(img_rgb, (IMG_SIZE, IMG_SIZE))
return resized, img
def postprocess(output, orig_shape):
"""YOLO12 后处理:解码 + NMS"""
# output shape: [1, 84, 8400] → 转置为 [8400, 84]
pred = np.transpose(output[0], (1, 0))
# 提取框坐标与置信度
boxes = pred[:, :4] # cx, cy, w, h
scores = pred[:, 4:] # 类别置信度
# 找最大类别分数
class_ids = np.argmax(scores, axis=1)
confidences = scores[np.arange(len(scores)), class_ids]
# 置信度过滤
mask = confidences > CONF_THRESH
boxes = boxes[mask]
confidences = confidences[mask]
class_ids = class_ids[mask]
# cxcywh → xyxy
boxes_xyxy = np.zeros_like(boxes)
boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2] / 2
boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3] / 2
boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2] / 2
boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3] / 2
# 缩放回原图尺寸
h, w = orig_shape
scale_x = w / IMG_SIZE
scale_y = h / IMG_SIZE
boxes_xyxy[:, 0] *= scale_x
boxes_xyxy[:, 2] *= scale_x
boxes_xyxy[:, 1] *= scale_y
boxes_xyxy[:, 3] *= scale_y
# NMS
indices = cv2.dnn.NMSBoxes(
boxes_xyxy.tolist(),
confidences.tolist(),
CONF_THRESH, NMS_THRESH
)
results = []
if len(indices) > 0:
for i in indices.flatten():
results.append({
'bbox': boxes_xyxy[i].astype(int),
'score': float(confidences[i]),
'class_id': int(class_ids[i]),
'class_name': CLASS_NAMES[int(class_ids[i])]
})
return results
if __name__ == '__main__':
# 1. 初始化 RKNN Lite
rknn_lite = RKNNLite()
ret = rknn_lite.load_rknn(RKNN_MODEL)
if ret != 0:
print('Load model failed')
exit(ret)
# 2. 初始化运行时(自动识别 RV1126B)
ret = rknn_lite.init_runtime(core_mask=RKNNLite.NPU_CORE_0)
if ret != 0:
print('Init runtime failed')
exit(ret)
# 3. 预处理
input_data, orig_img = preprocess(IMG_PATH)
# 4. 推理
outputs = rknn_lite.inference(inputs=[input_data])
# 5. 后处理
results = postprocess(outputs, orig_img.shape[:2])
# 6. 打印结果
for r in results:
print(f"{r['class_name']}: {r['score']:.3f} bbox={r['bbox']}")
# 7. 释放
rknn_lite.release()
运行:
python3 infer_yolo12.py
1.5 C/C++ 推理(高性能生产环境)
生产环境推荐使用 C API(librknnrt.so),性能比 Python 高 20~30%。核心流程:
#include "rknn_api.h"
// 1. 初始化
rknn_context ctx;
rknn_init(&ctx, model_data, model_size, 0, NULL);
// 2. 设置输入
rknn_input inputs[1];
inputs[0].index = 0;
inputs[0].buf = img_data;
inputs[0].size = img_size;
rknn_inputs_set(ctx, 1, inputs);
// 3. 推理
rknn_run(ctx, NULL);
// 4. 获取输出
rknn_output outputs[1];
rknn_outputs_get(ctx, 1, outputs, NULL);
// 5. 后处理(同 Python 逻辑)
// ...
// 6. 释放
rknn_outputs_release(ctx, 1, outputs);
rknn_destroy(ctx);
完整 C++ Demo 可参考官方 rknpu2/examples/rknn_yolov5_demo,替换模型与后处理参数即可适配 YOLO12。
2. 性能与精度参考
2.1 RV1126B 上 YOLO12n 实测数据
模型 | 精度 | 输入尺寸 | 推理耗时 | NPU 占用 | mAP@0.5 |
YOLO12n | INT8 | 640×640 | ~45ms | ~90% | ~38% |
YOLO12n | FP16 | 640×640 | ~80ms | ~85% | ~40% |
YOLO12s | INT8 | 640×640 | ~90ms | ~95% | ~47% |
数据基于 RV1126B @ 1.2GHz NPU 主频,实际速度受 DDR 带宽、系统负载影响。
1.6 精度优化建议
1. 校准集质量优先:优先使用真实场景图片,数量 200~500 张
2. 使用 MMSE 量化:quantized_algorithm='mmse',精度提升 1~2%
3. 混合精度:关键层(如检测头)保持 FP16,其余 INT8
4. 输入尺寸:640 平衡精度速度,也可尝试 416/512 进一步提速
2. 常见问题排查
Q1 转换时报错「算子不支持」
原因:YOLO12 的部分 Attention 算子 RV1126B NPU 未完全支持
解决:使用 yolo12n 轻量版;或在 config 中设置 op_target 将指定层分配给 CPU
Q2 推理结果全乱、检测框偏移
原因:均值/标准差配置错误,或前后处理通道不匹配
解决:确认 mean_values/std_values 与训练时一致;检查 RGB/BGR 顺序
Q3 板端推理速度远低于预期
原因:可能模型回退到 CPU 运行
排查:设置 RKNN_LOG_LEVEL=4 查看各层执行设备;优化计算图
Q4 INT8 量化后精度掉点严重
原因:校准集代表性不足,或量化算法不合适
解决:扩充校准集;切换 mmse 算法;对敏感层关闭量化
3. 完整流程总结
YOLO12.pt → 导出 ONNX → onnxsim 简化 → RKNN-Toolkit2 转换
↓
INT8 量化(校准集)→ 生成 .rknn → adb 推送到开发板
↓
板端加载模型 → 图像预处理 → NPU 推理 → 后处理解码 → 输出结果
如需针对特定场景(如智慧工地、明厨亮灶)定制 YOLO12 模型并完成端到端部署优化,可以进一步调整锚框、训练数据和量化策略。
需求留言: