RDKX5的TROS部署自己的yolov8输出结构全是F32,该怎么调整?

你好!看到 wzm1809434 也遇到了同样的问题。这个问题确实很典型,我来总结一下最终解决方案

核心问题

YOLOv8 部署到 RDK X5 时,hb_mapper PTQ 流程默认不量化输出层,导致:

  • 所有输出都是 F32 + NONE
  • 但 TROS 的 yolov8 parser 期望 bbox 分支是 S32 + SCALE

正确解决方案

步骤 1:使用 rdk_model_zoo 官方的 YOLOv8 导出脚本

不要自己修改导出脚本,直接使用社区验证过的:

# 1. 克隆 rdk_model_zoo
git clone -b rdk_x5 https://github.com/D-Robotics/rdk_model_zoo.git
cd rdk_model_zoo/samples/vision/ultralytics_yolo/conversion

# 2. 查看导出脚本
ls -la
# 找到 export_yolo26_detect_bpu.py 或类似脚本

关键:YOLOv8 在 Ultralytics 框架中也被称为 YOLOv26,所以要用 ultralytics_yolo 相关的导出脚本,而不是 yolov5 的。


步骤 2:正确的导出流程

# 1. 训练你的 YOLOv8 模型(5 分类)
yolo task=detect mode=train model=yolov8n.pt data=your_data.yaml epochs=100 imgsz=640

# 2. 使用官方导出脚本(关键!)
cd rdk_model_zoo/samples/vision/ultralytics_yolo/conversion/onnx_export
python export_yolo26_detect_bpu.py \
  --weights /path/to/your/best.pt \
  --imgsz 640 \
  --opset 11

# 3. 验证 ONNX 输出(应该全是 F32,这是正常的)
python3 -c "
import onnx
model = onnx.load('yolo26_det_bpu.onnx')
for output in model.graph.output:
    shape = [d.dim_value for d in output.type.tensor_type.shape.dim]
    print(f'{output.name}: shape={shape}')
"

步骤 3:正确的 hb_mapper YAML 配置

model_parameters:
  onnx_model: './yolo26_det_bpu.onnx'
  march: "bayes-e"
  layer_out_dump: False
  working_dir: 'model_output'
  output_model_file_prefix: 'yolov8_cow'

input_parameters:
  input_name: "images"
  input_type_rt: 'nv12'
  input_type_train: 'rgb'
  input_layout_train: 'NCHW'
  norm_type: 'data_scale'
  scale_value: 0.003921568627451

calibration_parameters:
  cal_data_dir: './cal_bin'
  cal_data_type: 'float32'
  calibration_type: 'default'

compiler_parameters:
  compile_mode: 'latency'
  debug: False
  optimize_level: 'O3'

注意

  • layer_out_dump: False(不要输出中间层)
  • 不要添加 optimization_parameters(1.24.3 版本不支持)

步骤 4:编译并验证

# 1. 编译
hb_mapper makertbin --model-type onnx --config yolov8.yaml

# 2. 验证模型输出
hrt_model_exec model_info --model_file=./model_output/yolov8_cow.bin

# 期望输出(6 个输出,bbox 应该是 S32):
# output[0]: shape=(1,80,80,5), type=F32   # cls_P3
# output[1]: shape=(1,80,80,64), type=S32  # bbox_P3 ✓
# output[2]: shape=(1,40,40,5), type=F32   # cls_P4
# output[3]: shape=(1,40,40,64), type=S32  # bbox_P4 ✓
# output[4]: shape=(1,20,20,5), type=F32   # cls_P5
# output[5]: shape=(1,20,20,64), type=S32  # bbox_P5 ✓

步骤 5:TROS 配置

{
  "model_file": "/home/sunrise/yolov8/yolov8_cow.bin",
  "task_num": 4,
  "dnn_parser": "yolov8",
  "model_output_count": 6,
  "reg_max": 16,
  "class_num": 5,
  "cls_names_list": "my_config/cow.list",
  "strides": [8, 16, 32],
  "score_threshold": 0.25,
  "nms_threshold": 0.7,
  "nms_top_k": 300,
  "output_order": [0, 1, 2, 3, 4, 5]
}

如果还是不行

备选方案:使用 Python 推理

如果 TROS parser 始终无法兼容,可以直接用 Python 推理:

from hobot_dnn import pyeasy_dnn as dnn
import numpy as np

# 加载模型
models = dnn.load('/home/sunrise/yolov8/yolov8_cow.bin')
model = models[0]

# 推理
outputs = model.inference(input_image)

# 手动后处理
# 1. 解码 bbox(output[1], [3], [5])
# 2. 获取 cls(output[0], [2], [4])
# 3. NMS

关键差异总结

操作 错误做法 正确做法
导出脚本 自己修改 Detect_forward rdk_model_zoo 官方脚本
输出量化 在 PyTorch 中转 int32 hb_mapper 自动处理
YAML 配置 添加 cal_data_count 等无效参数 只用标准参数
layer_out_dump True(导致 69 个输出) False(只有 6 个输出)

相关资源


给 wzm1809434 的建议

你的问题和 huajinxhr 完全一样,直接按上述步骤操作即可。最关键的是使用 rdk_model_zoo 官方的导出脚本,不要自己修改 Detect_forward 函数。

如果还有问题,建议:

  1. hrt_model_exec model_info 的输出发出来
  2. 确认输出数量是 6 个(不是 69 个)
  3. 确认 bbox 分支是 S32(不是 F32)

祝顺利!:rocket: