自定义训练Yolov8模型转ONNX→NCNN后推理异常求助
问题排查与解决
1. 模型导出与转换阶段的维度/输出映射问题
验证ONNX模型的输出正确性
虽然你解决了onnxsim的段错误,但要先确认简化后的ONNX模型本身输出正常。用onnxruntime跑测试图片,检查类别概率是否对应bus/car/truck:import onnxruntime as rt import numpy as np from PIL import Image sess = rt.InferenceSession("best-sim.onnx") input_name = sess.get_inputs()[0].name output_name = sess.get_outputs()[0].name # 按YOLOv8标准预处理图片 img = Image.open("test.jpg").resize((640, 640)) img_array = np.array(img).astype(np.float32) / 255.0 img_array = np.transpose(img_array, (2, 0, 1)) img_array = np.expand_dims(img_array, axis=0) output = sess.run([output_name], {input_name: img_array}) pred = output[0][0] class_idx = np.argmax(pred[:,4:], axis=1) print(class_idx) # 应输出0/1/2对应bus/car/truck,而非其他值若此处输出异常,重新导出ONNX时指定opset版本:
yolo mode=export model={HOME}/best.pt format=onnx opset=12修正ncnn输出层与步长配置
YOLOv8原生输出包含3个尺度的特征图(对应步长8、16、32),你仅设置strides = {32}会丢失大部分特征信息,导致分类错位。修改为:std::vector<int> strides = {8, 16, 32};同时打开
best.param文件,确认最后几行的输出层名称与netron中看到的完全一致,确保ex.extract提取的是正确的输出层。
2. 代码中的类别映射与预处理问题
核对类别索引顺序
确认训练时data.yaml中的类别顺序(如bus:0, car:1, truck:2)与cpp代码中class_names的顺序完全匹配,顺序错位会直接导致分类结果错误。统一图片预处理逻辑
检查cpp中的预处理是否与YOLOv8训练时一致:- 确保图片resize到模型输入尺寸(如640x640)
- 归一化方式匹配(YOLOv8默认除以255.0)
- 通道顺序转换正确(ncnn默认处理BGR,需转为RGB后输入)
示例预处理代码:
cv::Mat img = cv::imread("test.jpg"); cv::Mat resized; cv::resize(img, resized, cv::Size(640, 640)); ncnn::Mat in = ncnn::Mat::from_pixels(resized.data, ncnn::Mat::PIXEL_BGR2RGB, resized.cols, resized.rows); in = in / 255.0f;
3. ncnn模型的兼容性验证
若你在转换时做了int8量化,可能导致小样本训练模型的精度损失。暂时跳过量化步骤,直接用原始fp32模型测试:
onnx2ncnn best-sim.onnx best.param best.bin
内容的提问来源于stack exchange,提问作者Pastukhov
相关产品推荐
相关产品推荐

