文章目录
- [RK3588 部署 YOLO26 目标检测:从训练到 NPU 推理](#RK3588 部署 YOLO26 目标检测:从训练到 NPU 推理)
-
- 一、部署架构
- [二、PC 端环境搭建](#二、PC 端环境搭建)
-
- [2.1 Python 环境](#2.1 Python 环境)
- [2.2 安装 PyTorch](#2.2 安装 PyTorch)
- [2.3 安装 YOLO 及依赖](#2.3 安装 YOLO 及依赖)
- [2.4 安装 RKNN Toolkit 2](#2.4 安装 RKNN Toolkit 2)
- 三、数据集准备
-
- [3.1 公开数据集:COCO](#3.1 公开数据集:COCO)
- [3.2 自定义数据集](#3.2 自定义数据集)
- [3.3 数据集配置文件](#3.3 数据集配置文件)
- 四、模型训练
-
- [4.1 官方预训练权重](#4.1 官方预训练权重)
- [4.2 从头训练](#4.2 从头训练)
- [4.3 监控](#4.3 监控)
- [五、模型导出:PT → ONNX → RKNN](#五、模型导出:PT → ONNX → RKNN)
-
- [5.1 PT → ONNX](#5.1 PT → ONNX)
- [5.2 ONNX → RKNN](#5.2 ONNX → RKNN)
- [5.3 不量化 + 低精度](#5.3 不量化 + 低精度)
- [六、RK3588 端推理](#六、RK3588 端推理)
-
- [6.1 板端环境](#6.1 板端环境)
- [6.2 推理流程](#6.2 推理流程)
- 七、性能数据
- 八、常见问题
- 九、优化方向
- 十、总结
- 代码链接与详细流程
购买即可解锁1000+YOLO优化文章,并且还有海量深度学习复现项目,价格仅需两杯奶茶的钱,每日更新
RK3588 部署 YOLO26 目标检测:从训练到 NPU 推理
一、部署架构
PC 端(训练 + 转换) RK3588 端(推理)
───────────────────── ─────────────────
YOLO26.pt (PyTorch)
↓ yolo export
YOLO26.onnx (opset=11)
↓ RKNN Toolkit2
YOLO26.rknn (INT8) ─── scp ───→ RKNN Runtime 加载
↓
OpenCV 取帧 → 推理 → 后处理 → 显示
RK3588 NPU 算力 6 TOPS(INT8),YOLO26n 量化后推理延迟约 15ms,可以稳定覆盖 30 FPS 实时检测。
二、PC 端环境搭建
2.1 Python 环境
bash
conda create -n yolo26 python=3.10 -y
conda activate yolo26
2.2 安装 PyTorch
根据 CUDA 版本(通过 nvidia-smi 确认):
bash
# CUDA 11.8
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# CPU 版
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
2.3 安装 YOLO 及依赖
bash
pip install ultralytics
pip install onnx onnxsim opencv-python
2.4 安装 RKNN Toolkit 2
bash
pip install rknn_toolkit2-2.0.0-cp310-cp310-linux_x86_64.whl
验证:
bash
python -c "from rknn.api import RKNN; print('RKNN OK')"
三、数据集准备
3.1 公开数据集:COCO
COCO 2017 包含 80 类、33 万张图像。下载:
bash
# 约 20GB,建议用下载工具
mkdir -p datasets/coco2017 && cd datasets/coco2017
wget http://images.cocodataset.org/zips/train2017.zip
wget http://images.cocodataset.org/zips/val2017.zip
wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip
COCO 数据集的标注文件格式为 JSON(不是 YOLO 的 txt),第一次训练需要用 Ultralytics 的默认转换逻辑,框架会自动处理。
3.2 自定义数据集
如果做垂直场景(工业缺陷、农作物、特定零件),需要自己标数据。
推荐标注流程:
采集图像(500+ 张,覆盖不同光照/角度)
→ 筛选(删除模糊/无目标)
→ LabelImg 标注(选择 YOLO 格式)
→ 划分(train:val:test = 7:2:1)
安装 LabelImg:
bash
pip install labelImg
labelImg
标注完成后目录结构:
datasets/my_dataset/
├── train/
│ ├── images/ (img1.jpg, img2.jpg, ...)
│ └── labels/ (img1.txt, img2.txt, ...)
├── val/
│ ├── images/
│ └── labels/
├── test/
│ ├── images/
│ └── labels/
└── dataset.yaml
3.3 数据集配置文件
datasets/my_dataset/dataset.yaml:
yaml
train: /home/user/datasets/my_dataset/train
val: /home/user/datasets/my_dataset/val
test: /home/user/datasets/my_dataset/test
nc: 3
names: ["defect_type_a", "defect_type_b", "defect_type_c"]
类别名称的顺序必须与标注时一致。
四、模型训练
4.1 官方预训练权重
bash
# 下载 YOLO26n(最小,最快)
wget https://github.com/THU-MIG/yolov26/releases/download/v1.0/yolo26n.pt
模型规格对比:
| 模型 | 参数量 | mAP (COCO) | T4 推理 | 适用场景 |
|---|---|---|---|---|
| YOLO26n | 4.2M | 37.3 | 1.3ms | 移动端/边缘端 |
| YOLO26s | 11.1M | 44.9 | 1.8ms | 边缘端主力 |
| YOLO26m | 25.8M | 50.2 | 2.5ms | 中等场景 |
| YOLO26l | 43.7M | 52.9 | 3.5ms | 高精度场景 |
RK3588 NPU 部署建议用 n 或 s。
4.2 从头训练
bash
yolo train model=yolo26n.pt data=dataset.yaml \
epochs=100 batch=32 imgsz=640 \
device=0 workers=8 \
project=./runs name=yolo26_custom
| 参数 | 说明 | 推荐值 |
|---|---|---|
| epochs | 训练轮数 | 100-300 |
| batch | 批次大小 | 按显存调(32/64/128) |
| imgsz | 输入分辨率 | 640(与 NPU 一致) |
| device | GPU 编号 | 0(单卡) |
| workers | 数据加载线程 | 4-8 |
| lr0 | 初始学习率 | 0.01 |
| patience | 早停轮数 | 50 |
训练过程输出:
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size
1/100 6.8G 1.523 2.847 1.234 87 640
2/100 6.8G 1.412 2.651 1.189 92 640
...
99/100 6.8G 0.852 1.234 0.678 103 640
4.3 监控
TensorBoard:
bash
tensorboard --logdir ./runs/yolo26_custom
关注指标:
| 指标 | 正常范围 | 异常处理 |
|---|---|---|
| box_loss | 0.8→0.5 | 不下降 → 学习率调大或检查数据 |
| cls_loss | 1.5→0.6 | 不下降 → 类别不平衡 |
| mAP@0.5 | >0.7 | 低于 0.5 → 数据质量或模型太小 |
| mAP@0.5:0.95 | >0.4 | 低于 0.2 → 标注精度不够 |
五、模型导出:PT → ONNX → RKNN
5.1 PT → ONNX
bash
yolo export model=yolo26n.pt format=onnx simplify=True opset=11
5.2 ONNX → RKNN
python
# onnx2rknn.py
from rknn.api import RKNN
ONNX_PATH = "yolo26n.onnx"
RKNN_PATH = "yolo26n.rknn"
rknn = RKNN(verbose=True)
rknn.config(
mean_values=[[0, 0, 0]],
std_values=[[255, 255, 255]],
target_platform="rk3588",
quantized_dtype="asymmetric_quantized-8",
)
ret = rknn.load_onnx(ONNX_PATH)
assert ret == 0
ret = rknn.build(do_quantization=True, dataset="./calibration.txt")
assert ret == 0
ret = rknn.export_rknn(RKNN_PATH)
assert ret == 0
rknn.release()
print(f"Done → {RKNN_PATH}")
calibration.txt:每行一张训练图像的路径,100-200 张即可。
bash
python onnx2rknn.py
5.3 不量化 + 低精度
python
rknn.config(target_platform="rk3588", quantized_dtype="asymmetric_quantized-8")
rknn.build(do_quantization=False, dataset="")
# 输出 FP16 推理,精度更高但速度慢约 40%
六、RK3588 端推理
6.1 板端环境
bash
pip install opencv-python-headless rknn-runtime
6.2 推理流程
python
import cv2
import numpy as np
from rknn.api import RKNN
RKNN_PATH = "yolo26n.rknn"
CLASSES = ["person", "car", "dog", ...] # 80 COCO 类
CONF_THR = 0.5
# 加载模型
rknn = RKNN()
rknn.load_rknn(RKNN_PATH)
rknn.init_runtime()
# 预处理(letterbox)
def letterbox(img, target=640):
h, w = img.shape[:2]
scale = min(target / h, target / w)
nh, nw = int(h * scale), int(w * scale)
resized = cv2.resize(img, (nw, nh))
canvas = np.full((target, target, 3), 114, dtype=np.uint8)
dh, dw = (target - nh) // 2, (target - nw) // 2
canvas[dh:dh+nh, dw:dw+nw] = resized
inp = canvas.astype(np.float32) / 255.0
return inp.transpose(2, 0, 1)[np.newaxis], scale, dh, dw
# 主循环
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
inp, scale, dh, dw = letterbox(frame)
outputs = rknn.inference(inputs=[inp])
# 解析检测结果
dets = outputs[0][0]
for i in range(dets.shape[1]):
max_score = dets[4:, i].max()
if max_score < CONF_THR:
continue
cls_id = dets[4:, i].argmax()
cx, cy, bw, bh = dets[:4, i]
x1 = int((cx - bw/2 - dw) / scale)
y1 = int((cy - bh/2 - dh) / scale)
x2 = int((cx + bw/2 - dw) / scale)
y2 = int((cy + bh/2 - dh) / scale)
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
label = f"{CLASSES[int(cls_id)]}: {max_score:.2f}"
cv2.putText(frame, label, (x1, y1-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv2.imshow("YOLO26 @ RK3588", frame)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
rknn.release()
七、性能数据
| 模型 | 输入 | 量化 | NPU 延迟 | 全链路 FPS |
|---|---|---|---|---|
| YOLO26n | 640 | INT8 | ~15ms | ~55 |
| YOLO26s | 640 | INT8 | ~30ms | ~28 |
| YOLO26n | 480 | INT8 | ~8ms | ~85 |
| YOLO26n | 640 | FP16 | ~25ms | ~35 |
八、常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
| ATC 报 "Unsupported op" | opset 太高 | 用 opset=11 重新导出 ONNX |
| RKNN 推理结果全 0 | 输入 tensor 不是 float32 或 NCHW | img = img.astype(np.float32) 并 transpose |
| 检测框位置偏移 | letterbox 的 scale/dw/dh 反算不一致 | 用同一个函数内的返回值 |
| 训练 mAP 不涨 | 学习率太低或数据标注有误 | lr0=0.01 预热 3 轮;检查所有 .txt 标注 |
| 摄像头打不开 | 权限或设备节点 | ls /dev/video*;sudo chmod 666 /dev/video0 |
九、优化方向
| 优化项 | 方法 | 收益 |
|---|---|---|
| 后处理加速 | numpy 向量化替换 Python 循环 | FPS +30% |
| 多线程流水线 | 推理线程与 I/O 线程分离 | 降低画面卡顿 |
| 输下降分辨率 | 640→480 | FPS 翻倍,小目标 mAP 下降约 3% |
| 最小模型 | s→n | FPS 翻倍,mAP 下降约 2% |
| 半精度推理 | INT8→FP16 | 精度恢复,速度下降 40% |
十、总结
YOLO26 在 RK3588 上的全流程是 PC 端训练 + ONNX 导出 → RKNN 转换(INT8 量化)→ 板端推理。YOLO26n 在 640 输入下 NPU 推理约 15ms,全链路可达 55 FPS。先用 COCO 预训练权重跑通转换链路,确认在 NPU 上推理结果正确,再切回自定义数据集做 finetune。
代码链接与详细流程
飞书链接:https://ecn6838atsup.feishu.cn/wiki/EhRtwBe1CiqlSEkHGUwc5AP9nQe?from=from_copylink
密码:946m22&8
链接可用,不要多复制空格了