问题分析
核心原因:YOLOv8 的输出格式与 dnn_node_example 期望的标准检测模型格式不匹配,导致后处理时访问非法内存(段错误 exit code -11)。
从你的输出头看:
[(1, 80, 80, 1), (1, 80, 80, 64), (1, 40, 40, 1), (1, 40, 40, 64), (1, 20, 20, 1), (1, 20, 20, 64)]
这是 YOLOv8 的解耦头格式(cls + reg 分开),而 dnn_node_example 期望的是耦合头格式(如 YOLOv3/v5)。
让我先搜索社区是否有 YOLOv8 部署的相关案例:
问题分析
根据你的报错日志,核心问题是 dnn_example_node 进程段错误崩溃(exit code -11),导致 WebSocket 收不到 AI 数据。
从你的输出头信息来看:
[(1, 80, 80, 1), (1, 80, 80, 64), (1, 40, 40, 1), (1, 40, 40, 64), (1, 20, 20, 1), (1, 20, 20, 64)]
问题定位:输出头格式错误!
你的模型输出是 NHWC 格式(6 个输出头),但 dnn_node_example 的 YOLOv8 parser 期望的是 NCHW 格式,且输出顺序应该是 bbox 在前,cls 在后。
解决方案
步骤 1:修正 ONNX 导出脚本
你的 export_monkey_patch.py 中的 Detect_forward 函数有问题。需要修改输出顺序和格式:
def Detect_forward(self, x):
result = []
for i in range(self.nl):
# 先输出 bbox,再输出 cls(关键!)
bbox = self.cv2[i](x[i]) # (B, 64, H, W) - bbox
cls = self.cv3[i](x[i]) # (B, nc, H, W) - cls
# 保持 NCHW 格式,不要 permute
result.append(bbox)
result.append(cls)
return result
关键修改点:
- 输出顺序:先 bbox 后 cls(你当前代码是先 cls 后 bbox)
- 保持 NCHW:不要调用
.permute(0, 2, 3, 1)(你当前代码做了 permute 变成 NHWC)
步骤 2:重新导出 ONNX 模型
cd D:\zhinengche\OriginCar\yolo\yolov8
python export_monkey_patch.py --pt datasets/runs/detect/train/weights/best.pt --imgsz 640 640 --opset 11
导出后验证 ONNX 模型输出:
python3 -c "
import onnx
model = onnx.load('best.onnx')
for output in model.graph.output:
print(f'{output.name}: {[d.dim_value for d in output.type.tensor_type.shape.dim]}')
"
期望输出(NCHW 格式):
bbox_P3: [1, 64, 80, 80]
cls_P3: [1, 1, 80, 80] # 如果是单类别
bbox_P4: [1, 64, 40, 40]
cls_P4: [1, 1, 40, 40]
bbox_P5: [1, 64, 20, 20]
cls_P5: [1, 1, 20, 20]
步骤 3:重新量化模型
使用修正后的 ONNX 重新量化:
cd /workspace
hb_mapper makertbin --config obstacle_config.yaml --model-type onnx
注意检查 obstacle_config.yaml:
input_parameters:
input_name: 'images'
input_type_rt: 'nv12'
input_type_train: 'rgb'
input_layout_rt: 'NHWC' # 板端输入布局(BPU 要求)
input_layout_train: 'NCHW' # 训练时布局(保持 NCHW)
input_shape: '1x3x640x640'
norm_type: 'data_scale'
scale_value: '0.003921568627451' # 1/255
步骤 4:验证 bin 模型输出
在板子上验证新模型的输出格式:
python3 << 'EOF'
from hobot_dnn import pyeasy_dnn as dnn
models = dnn.load('/home/sunrise/yiqiang_ws/src/origincar/models/obstacle.bin')
model = models[0]
print(f"Model outputs: {len(model.outputs)}")
for i, out in enumerate(model.outputs):
p = out.properties
print(f"Output[{i}]: shape={p.shape}, layout={p.layout}, type={p.dtype}")
EOF
期望输出:
Output[0]: shape=(1, 64, 80, 80), layout=NCHW # bbox_P3
Output[1]: shape=(1, 1, 80, 80), layout=NCHW # cls_P3
Output[2]: shape=(1, 64, 40, 40), layout=NCHW # bbox_P4
Output[3]: shape=(1, 1, 40, 40), layout=NCHW # cls_P4
Output[4]: shape=(1, 64, 20, 20), layout=NCHW # bbox_P5
Output[5]: shape=(1, 1, 20, 20), layout=NCHW # cls_P5
步骤 5:检查配置文件
确认 yolov8workconfig.json 配置正确:
{
"model_file": "/home/sunrise/yiqiang_ws/src/origincar/models/obstacle.bin",
"dnn_Parser": "yolov8",
"model_output_count": 6,
"reg_max": 16,
"class_num": 1,
"cls_names_list": "/home/sunrise/yiqiang_ws/src/origincar/models/obstacles.list",
"strides": [8, 16, 32],
"score_threshold": 0.25,
"nms_threshold": 0.7,
"nms_top_k": 300
}
快速验证
如果还是不确定,先用板子自带的官方模型测试 TROS 是否正常:
# 使用官方模型测试
ros2 launch dnn_node_example dnn_node_example.launch.py
如果官方模型能跑通,说明是你的模型格式问题;如果官方模型也崩溃,说明系统环境问题。
相关资源
建议先执行步骤 1 和步骤 2,修正导出脚本后重新导出 ONNX,这是最关键的问题点。