
简介面向RDK X5开发者的YOLOv11部署源码包聚焦自训练检测模型从PyTorch权重到板端运行的全流程迁移可直接用于项目二次开发与实验验证。资源共10个文件包括Python训练/导出/部署脚本、量化YAML配置、环境搭建Shell脚本与依赖清单覆盖ONNX导出、输出头修正、模型完整性检查、量化配置与BIN文件生成等关键环节压缩包仅18KB轻量精简便于按需修改和快速实验。目前已有245人学习适合具备一定深度学习基础、希望在嵌入式平台上实践YOLO系列模型部署的开发者。借助该源码包可复用完整的模型转换与量化实现逻辑学习在RDK X5上构建适配YOLOv11的开发环境并参考板端部署中的代码调整思路避免环境配置和格式转换阶段的常见问题明显缩短从模型训练到硬件部署的研发周期。 这段时间在RDK X5上把YOLOv11跑通了从ONNX导出、模型转换到NPU推理、后处理整个过程踩了不少坑也沉淀了一套可以直接运行的源码。这篇文章就把完整的部署思路、转换命令、代码结构和避坑经验写出来给准备在端侧AI硬件上做目标检测的同学一个参考。RDK X5是地瓜机器人推出的开发套件集成10 TOPS算力的BPU非常适合机器人和边缘视觉场景YOLOv11是目前Ultralytics主推的检测模型精度和速度都比较均衡。把YOLOv11部署到RDK X5上意味着可以在本地实现实时目标检测不依赖云服务器特别适合产线质检、巡检机器人、智能交通、无人零售这类对时延和隐私敏感的应用。这篇内容不打算只贴几个命令行就完事我会把每个关键步骤背后的逻辑也讲清楚比如为什么从ONNX开始转、为什么后处理要自己写、量化校准数据怎么准备。只要你手里有一块RDK X5跟着操作就能复现就算你用的是其他NPU开发板这套思路也完全通用。1. 项目背景与整体设计思路1.1 为什么选择RDK X5RDK X5是地瓜机器人面向开发者推出的机器人开发套件核心芯片是旭日5内部集成了一颗BPUBrain Processing Unit神经网络加速单元官方标称整数算力10 TOPS。这个算力水平在端侧设备里属于比较能打的档位既能跑轻量级目标检测模型也能同时挂载多路传感器数据流。板子的外设接口非常齐全这也是我选它做视觉项目的主要原因。除了常规的USB、HDMI、千兆网口还带MIPI-CSI摄像头接口、PWM、I2C、SPI、UART、GPIO等引脚图在官方Wiki和原理图里都能找到。这意味着你可以直接把摄像头、电机驱动、激光雷达挂在同一块板子上非常适合做移动机器人、机械臂抓取、智能安防这类需要感知和执行闭环的项目。另外RDK X5支持完整的Linux系统开发体验接近普通嵌入式Linux开发板Python生态也能直接用。相比在MCU或者DSP上做深度学习推理RDK X5的开发门槛低很多上手周期大概两三天就能进入正题。我当时选择它的核心原因就是看中它的工具链比较成熟模型转换、推理API、示例代码都有官方文档支撑不至于让人卡在环境地狱里出不来。1.2 YOLOv11模型选型与整体部署链路YOLOv11是Ultralytics公司在YOLO系列基础上推出的新版本相比之前的YOLOv8在Backbone和Neck部分做了优化计算量更小检测精度也保持得不错。在端侧部署时我一般优先选yolo11n或者yolo11s这两个尺寸。yolo11n在RDK X5上可以跑出很高的帧率适合实时性要求高的场景yolo11s精度更好适合对识别准确率更敏感的任务。部署的整体链路可以拆成三段在PC上使用ultralytics框架导出ONNX模型在PC上使用RDK X5官方模型转换工具将ONNX模型转换成NPU可执行的模型文件把转换后的模型文件放到RDK X5上用官方推理库加载模型、做前处理、推理和后处理。很多人第一次接触NPU部署时有一个误区以为直接把PyTorch权重拷到板子上就能跑。实际上NPU不能直接解释PyTorch的算子图必须经过格式转换和算子映射。RDK X5的BPU只支持厂商定义的算子集合所以转换这一步是绕不开的。我建议把整个链路想象成一个“翻译编译”的过程ONNX是中间语言转换工具负责把它翻译成NPU认识指令翻译完成后的.bin模型文件才是真正能在BPU上运行的东西。2. 环境准备与工具链梳理2.1 硬件、系统与开发环境搭建开始之前先把硬件事项列清楚。我实际用到的设备清单如下RDK X5开发板一块电源适配器官方要求12V/2A以上建议直接上12V/3A避免高负载时供电不足导致重启一张至少32GB的TF卡用于烧录系统一根USB转TTL串口线或者直接用HDMI接显示器一个USB摄像头或者MIPI-CSI摄像头推荐先用USB摄像头快速验证一台PCUbuntu 20.04/22.04都可以用于模型导出和转换。系统镜像从地瓜机器人官方Wiki下载下载完成后用Etcher或者balenaEtcher把镜像烧录到TF卡。烧录完成之后插入TF卡上电开机默认账号通常是root密码在官方文档里有说明登录后建议先执行一次apt update apt upgrade把系统包更新到最新。联网方面我建议优先接有线网或者配置好WiFi因为后续需要安装不少Python依赖。确认网络通畅之后还要检查一下板子的Python版本和pip版本。RDK X5系统默认自带Python 3.8/3.10左右这两个版本跑hobot推理库都没问题。如果系统里同时存在多个Python版本记得用python3 -m pip来指定当前环境的pip避免装错位置。2.2 依赖安装与模型导出准备RDK X5的NPU推理官方库叫hobot_dnn在系统镜像里可能已经预装但为了确保版本一致我建议在开发板环境里执行一次安装顺便把numpy、opencv-python这些基础库一起装上。命令如下pip3 install hobot-dnn pip3 install numpy opencv-pythonhobot_dnn是连接Python应用和BPU的桥梁它会读取转换好的.bin模型文件把输入张量送到NPU计算再把输出张量取回来。这个库本身不包含复杂的图像处理能力所以还需要OpenCV来读图、缩放、归一化。在PC端需要安装ultralytics和onnx相关工具。建议单独建一个虚拟环境避免把系统环境搞乱。命令如下python3 -m venv yolox5_env source yolox5_env/bin/activate pip install ultralytics onnx onnxruntime这里装onnxruntime不是为了在PC上跑推理而是为了方便检查导出后的ONNX模型结构确认输入输出节点是否正确。后面转换工具报错时就可以用onnxruntime快速定位到底是模型本身的问题还是转换工具的问题。3. 模型转换与量化落地3.1 用Ultralytics导出ONNX导出ONNX是整条链路里最简单的一步但也最容易因为版本问题翻车。执行下面这条命令yolo export modelyolo11n.pt formatonnx opset12这里有几个关键点值得展开说一下。第一把opset固定在12。新版本的ultralytics默认opset可能是17或者更高但NPU转换工具对ONNX算子版本的支持往往比PC框架滞后。opset太高会导致转换器遇到不认识的算子直接报错。我实测在RDK X5工具链下opset 12是最稳妥的既能兼容大部分算子又不会牺牲精度。第二尽量使用固定输入尺寸。默认导出的模型输入是1x3x640x640这个尺寸我保留了下来。不要使用动态batch或者动态分辨率NPU更擅长处理静态shape动态shape会让后处理代码至少复杂三倍而且性能不一定有改善。第三导出后检查输出。在PC上用onnxruntime简单跑一次确认输出张量形状符合预期。YOLOv11的输出通常是一个二维数组形状类似[1, 84, 8400]其中84代表4个坐标加上80个类别分数8400代表不同尺度下锚点框的总数。如果输出shape和你预期不一致先不要继续往下走回到模型配置里检查。3.2 转换到NPU可执行的模型格式拿到ONNX模型之后就需要用RDK X5的模型转换工具把它变成.bin模型文件。以地平线/地瓜工具链为例转换命令类似于hb_mapper makertbin --model-type onnx \ --model yolo11n.onnx \ --output_dir ./yolo11n_bin \ --input-shape 1,3,640,640 \ --calibration-dataset ./calib_data \ --calibration-size 100这里需要重点解释--calibration-dataset参数。NPU在转换浮点模型时通常默认做INT8量化也就是把FP32权重压缩到INT8这样可以大幅提升推理速度、降低内存带宽压力。量化需要一组有代表性的真实图片来做“校准”让工具统计出每一层激活值的合理分布范围。校准数据集不要用纯黑图片也不要用跟实际场景完全无关的风景图最理想的情况是准备100到200张与真实业务场景相似的图片比如你之后要检测的是工厂零件就多放一些零件图片。这个细节直接影响量化后的检测精度很多人忽略了结果模型跑出来漏检严重还以为是模型转换失败了。转换完成后输出目录里会有yolo11n.bin以及其他相关的模型信息文件。bin文件就是我们最终要拷到RDK X5上使用的模型。转换工具通常会输出一些性能预估信息和算子支持情况如果某个算子不在BPU支持的列表里工具会给出告警这时返回去修改ONNX导出参数或者替换相应模块比在板子上排查要简单得多。4. 可运行源码结构与推理实现4.1 源码目录设计一套清晰的源码结构能让你在调试时少走很多弯路。以我自己整理的仓库为例目录结构如下rdk_x5_yolov11/ ├── models/ │ └── yolo11n.bin ├── data/ │ └── test.jpg ├── rdk_yolov11.py ├── requirements.txt └── README.mdmodels目录存放转换好的.bin模型data目录放测试图片rdk_yolov11.py是主推理脚本requirements.txt记录依赖列表。这样组织的原因是模型文件和代码分离后续更换模型或者增加新的测试图片时不需要改动代码整个目录可以打包发布别人拿过去只要补一个模型文件就能运行。主脚本的设计我分成了四个模块化的函数load_model()加载.bin模型返回推理句柄preprocess()读取图片完成resize、letterbox、归一化、通道变换infer()把预处理后的图像数据送入NPU获取模型输出postprocess()解析输出执行NMS绘制检测框并保存结果。这样拆分的好处是后续如果换摄像头输入只需要替换preprocess()里面的图像来源不需要动其他部分。4.2 推理主流程与关键代码解析下面这个是简化但完整的推理主流程我在RDK X5上实测可以正常运行。import cv2 import numpy as np from hobot_dnn import pyeasy_dnn MODEL_PATH models/yolo11n.bin CLASS_NAMES [person, car, bicycle, ...] # 按照自己数据集的类别顺序填写 CONF_THRESHOLD 0.25 IOU_THRESHOLD 0.45 INPUT_SIZE (640, 640) def load_model(model_path): models pyeasy_dnn.load(model_path) return models[0] def preprocess(image, input_size): img cv2.cvtColor(image, cv2.COLOR_BGR2RGB) h, w img.shape[:2] ratio min(input_size[0] / h, input_size[1] / w) new_h, new_w int(h * ratio), int(w * ratio) resized cv2.resize(img, (new_w, new_h)) canvas np.full((input_size[0], input_size[1], 3), 114, dtypenp.uint8) x_off (input_size[1] - new_w) // 2 y_off (input_size[0] - new_h) // 2 canvas[y_off:y_off new_h, x_off:x_off new_w] resized blob canvas.astype(np.float32) / 255.0 blob blob.transpose(2, 0, 1)[None, ...] return blob, ratio, x_off, y_off def infer(model, blob): outputs model(blob) return outputs[0].valuesletterbox处理非常关键。YOLOv11在训练时会对输入图像做等比例缩放并在底部或右侧填充灰色边部署推理时也必须做同样的操作否则检测框坐标会全部偏移甚至完全检测不到目标。我见过不少人直接resize到640x640不保持比例最后坐标全乱。填充值这里用的是114这是YOLO系列训练时的默认值保持和训练一致可以减少分布偏移。hobot_dnn的推理接口是model(blob)输入一个形状为1x3x640x640的numpy数组输出是模型输出层的结果。由于YOLOv11是一个单输出模型所以直接取outputs[0]即可。如果后续用YOLOv8或YOLOv5的某些变体可能需要处理多输出那就要按输出索引分别解析。4.3 后处理与NMS实现后处理是整个流程里最需要细心的地方。模型输出的原始结果是归一化的坐标和类别分数必须经过解码、置信度筛选、NMS非极大值抑制之后才是最终检测框。def postprocess(output, ratio, x_off, y_off, conf_threshold, iou_threshold): # output shape: [1, 84, 8400] output output.squeeze(0) boxes [] scores [] class_ids [] for i in range(output.shape[1]): class_scores output[4:, i] class_id np.argmax(class_scores) confidence class_scores[class_id] if confidence conf_threshold: continue cx, cy, bw, bh output[0:4, i] x1 (cx - bw / 2 - x_off) / ratio y1 (cy - bh / 2 - y_off) / ratio x2 (cx bw / 2 - x_off) / ratio y2 (cy bh / 2 - y_off) / ratio boxes.append([x1, y1, x2, y2]) scores.append(float(confidence)) class_ids.append(int(class_id)) indices cv2.dnn.NMSBoxes(boxes, scores, conf_threshold, iou_threshold) final_boxes [boxes[i] for i in np.array(indices).flatten()] final_scores [scores[i] for i in np.array(indices).flatten()] final_classes [class_ids[i] for i in np.array(indices).flatten()] return final_boxes, final_scores, final_classes重点说一下解码公式。模型输出的中心坐标cx, cy和宽高bw, bh都是相对于640x640输入图的而输入图里包含了一部分填充区域。所以我们先把坐标还原到640x640原图坐标系再减掉填充偏移、除以缩放比例才能得到原始图像中的坐标。这里的ratio和x_off/y_off就是从preprocess()里一路传过来的如果中间少传了一个参数画框位置就会整体偏移。NMS我直接用OpenCV的cv2.dnn.NMSBoxes实现不用自己手写速度和稳定性都有保障。这里还有一个性能细节要提在RDK X5这种端侧设备上NMS的计算量虽然不算大但如果检测框数量特别多循环解码的过程也会占不少CPU。可以考虑在上板前把置信度阈值从0.25提高到0.3甚至0.4能显著减少候选框数量对帧率提升有帮助。5. 实测性能与踩坑记录5.1 性能调优与量化效果我实际在RDK X5上跑yolo11n模型输入分辨率640x640量化后单帧推理时间大约在30到50毫秒之间换算下来20到30帧每秒左右加上摄像头取流和可视化整体能稳定跑在20帧以上。这个性能已经满足大多数机器人视觉场景了比如室内无人机避障、AGV导航、简单的安防检测。如果想进一步压榨性能有几个思路比较有效把输入分辨率从640x640降到416x416或者320x320推理时间能减少一半以上精度下降幅度通常可以接受使用MIPI-CSI摄像头直接接入ISP管线省掉USB传输的拷贝开销在Python侧用两个线程一个线程负责图像采集和预处理另一个线程负责NPU推理躲开IO等待尽量使用yolo11n而不是yolo11s除非项目对精度要求非常苛刻。量化带来的精度损失需要单独评估。我自己的测试里yolo11n经过INT8量化后在公开数据集上的mAP大概下降1到2个百分点普通目标检测场景完全够用。但如果你的业务对细小目标、近距离模糊目标特别敏感建议准备一个验证集把量化前后的检测结果放在一起对比一下再决定是否采用量化模型。5.2 踩坑记录与排查表部署过程中遇到的各种坑我整理成了一张排查表按频率排序现象原因解决办法模型转换时算子不支持ONNX opset版本过高或包含BPU不支持算子重置opset12导出检查是否有动态shape简化自定义模块推理输出全为0或结果为空前处理没有letterbox输入分布与训练不一致严格按letterbox流程处理填充值与训练保持一致检测框位置偏移严重坐标解码时忘了还原填充偏移和缩放比例检查x_off、y_off、ratio是否传对类别大量错乱类别名称顺序与训练集不一致按训练时的data.yaml顺序重排类别列表推理帧率很低单线程串行IO和推理引入双线程或多缓冲区调度板子高负载下重启供电不足更换12V/3A电源检查TF卡散热这里我再单独强调一个非常隐蔽的坑量化校准数据集的选择。我第一次转换时图省事随便找了几十张网上下的图片做校准结果在真实场景里漏检率特别高。后来换成了从实际应用场景中截取的100张图片同样模型、同样转换参数精度立刻回到可用水平。原因是量化算法需要通过校准图片估计激活值的动态范围校准图片分布和实际推理分布差异越大量化误差就越大。还有一个容易忽略的点就是requirements.txt里最好固定依赖版本尤其是numpy和opencv-python。RDK X5系统环境里可能已经装过旧版本numpy如果后面安装新库时强行升级了numpy可能导致hobot_dnn的C扩展库加载失败。遇到这种问题时最简单的处理方式是重新创建虚拟环境按顺序安装依赖不要用pip install --upgrade随意更新。最后再分享一个我自己的部署习惯拿到新板子先跑一个最简单的分类模型确认工具链通通再上检测模型。转换前把输入分辨率固定下来后处理参数和量化校准数据集保持一致这样能省很多排查时间。另外RDK X5跑YOLOv11的时候编译OpenCV时最好启用NEON优化Python侧能明显感觉到图像预处理速度变快。如果你打算做视频流实时分析可以直接把推理结果编码成JPEG用RTSP或者WebSocket推送出去板子的CPU和BPU配合起来完全撑得住。希望这篇内容能帮你把YOLOv11在RDK X5上顺利跑起来少走一些我走过的弯路。本文还有配套的精品资源点击获取