使用 nncase 模拟器验证转换效果 出现报错 sim.load_model(kmodel) RuntimeError

Viewed 55

https://www.kendryte.com/k230_canmv/zh/main/zh/ai_dev_doc.html#id11 根据这个里面的例程(windows)修改文件地址后报错如下

C:\Install\Anaconda3\envs\YOLO\python.exe C:\All\PycharmProjects\yolov11\toK230\models_compare.py 
Traceback (most recent call last):
  File "C:\All\PycharmProjects\yolov11\toK230\models_compare.py", line 119, in <module>
    nncase_results = kmodel_inference(kmodel_path,kmodel_input_data,model_input_size)
  File "C:\All\PycharmProjects\yolov11\toK230\models_compare.py", line 76, in kmodel_inference
    sim.load_model(kmodel)
RuntimeError

进程已结束,退出代码为 1

测试了kmodel应该是没有问题的,如下:

import os

kmodel_path = "./models/numDetect_yolov5su.kmodel"
print("kmodel_path:", kmodel_path)
print("File exists:", os.path.exists(kmodel_path))

with open(kmodel_path, 'rb') as f:
    kmodel = f.read()
print("kmodel size:", len(kmodel))
=============================================================================
C:\Install\Anaconda3\envs\YOLO\python.exe C:\All\PycharmProjects\yolov11\toK230\test.py 
kmodel_path: ./models/numDetect_yolov5su.kmodel
File exists: True
kmodel size: 9768648

进程已结束,退出代码为 0

尝试了把nncase降级到2.8.3(原来是2.9.0)也没用

import os
import cv2
import numpy as np
import onnxruntime as ort
import nncase
import math

# 参数定义
IMG_PATH            = "../numDetect/dataset/data/images/test/0_91.jpg"
MEAN                = [0, 0, 0]
STD                 = [1, 1, 1]
MODEL_INPUT_SIZE    = [320, 320]
ONNX_MODEL          = "../numDetect/runs/detect/train/weights/best.onnx"   # ONNX 模型文件
KMODEL_PATH         = "./models/yolov5su.kmodel" # kmodel 模型文件

def get_onnx_input(img_path,mean,std,model_input_size):
    # 读取图片,图片数据一般是RGB三通道,颜色范围为[0, 255.0]
    image_fp32=cv2.imread(img_path)
    # 如果模型输入要求是RGB的,则转换为RGB格式,如果要求是BGR的,则不需要转换
    image_fp32=cv2.cvtColor(image_fp32, cv2.COLOR_BGR2RGB)
    # 缩放成模型输入大小
    image_fp32 = cv2.resize(image_fp32, (model_input_size[0], model_input_size[1]))
    # 数据类型为float32,
    image_fp32 = np.asarray(image_fp32, dtype=np.float32)
    # 数据标准化,先归一化到[0,1]范围内,然后减均值除方差
    image_fp32/=255.0
    for i in range(3):
        image_fp32[:, :, i] -= mean[i]
        image_fp32[:, :, i] /= std[i]
    # 按照模型输入要求处理成NCHW排布或者NHWC排布
    image_fp32 = np.transpose(image_fp32, (2, 0, 1))
    return image_fp32.copy()

def get_kmodel_input(img_path,mean,std,model_input_size):
    # 读取图片,图片数据一般是RGB三通道,颜色范围为[0, 255.0]
    image_uint8=cv2.imread(img_path)
    # 如果模型输入要求是RGB的,则转换为RGB格式,如果要求是BGR的,则不需要转换
    image_uint8=cv2.cvtColor(image_uint8, cv2.COLOR_BGR2RGB)
    # 缩放成模型输入大小
    image_uint8 = cv2.resize(image_uint8, (model_input_size[0], model_input_size[1]))
    # 数据类型为uint8,因为转换kmodel的时候开启了预处理,并且设定了标准化参数,因此这里的输入就不需要实现标准化了
    image_uint8 = np.asarray(image_uint8, dtype=np.uint8)
    # 按照模型输入要求处理成NCHW排布或者NHWC排布
    image_uint8 = np.transpose(image_uint8, (2, 0, 1))
    return image_uint8.copy()

def onnx_inference(onnx_path,onnx_input_data):
    # 创建 ONNX 推理会话(加载模型)
    ort_session = ort.InferenceSession(onnx_path)
    # 获取模型输出名称列表,用于后续调用推理
    output_names = []
    model_outputs = ort_session.get_outputs()
    for i in range(len(model_outputs)):
        output_names.append(model_outputs[i].name)

    # 获取模型的输入信息
    model_input = ort_session.get_inputs()[0]             # 第一个输入(通常只有一个)
    model_input_name = model_input.name                   # 输入的名称(键)
    model_input_type = np.float32                         # 输入数据类型,这里假设是 float32
    model_input_shape = model_input.shape                 # 输入张量的形状(维度)

    # 处理输入数据,需确保和模型输入形状一致
    model_input_data = onnx_input_data.astype(model_input_type).reshape(model_input_shape)

    # 执行推理,传入输入名称和数据,返回所有输出结果
    onnx_results = ort_session.run(output_names, { model_input_name : model_input_data })
    return onnx_results

def kmodel_inference(kmodel_path,kmodel_input_data,model_input_size):
    # 初始化nncase 模拟器
    sim = nncase.Simulator()
    # 读取kmodel
    with open(kmodel_path, 'rb') as f:
        kmodel = f.read()
    # 加载kmodel
    sim.load_model(kmodel)
    # 读取输入数据
    input_shape = [1, 3, model_input_size[1], model_input_size[0]]
    dtype = sim.get_input_desc(0).dtype
    # 处理输入数据,需确保和模型输入形状一致
    kmodel_input = kmodel_input_data.astype(dtype).reshape(input_shape)
    # 设置模拟器输入tensor,此处为单输入
    sim.set_input_tensor(0, nncase.RuntimeTensor.from_numpy(kmodel_input))
    # 模拟器推理kmodel模型
    sim.run()
    # 获取推理输出
    kmodel_results = []
    for i in range(sim.outputs_size):
        kmodel_result = sim.get_output_tensor(i).to_numpy()  # 转换为numpy数组
        kmodel_results.append(kmodel_result)  # 保存到列表中
    return kmodel_results

def cosine_similarity(onnx_results,kmodel_results):
    output_size=len(kmodel_results)
    # 将每个输出展成一维,然后计算余弦相似度
    for i in range(output_size):
        onnx_i=np.reshape(onnx_results[i], (-1))
        kmodel_i=np.reshape(kmodel_results[i], (-1))
        cos = (onnx_i @ kmodel_i) / (np.linalg.norm(onnx_i, 2) * np.linalg.norm(kmodel_i, 2))
        print('output {0} cosine similarity : {1}'.format(i, cos))
    return

if __name__ == '__main__':
    img_path=IMG_PATH
    mean=MEAN
    std=STD
    model_input_size=MODEL_INPUT_SIZE
    # ONNX 模型文件
    onnx_model = ONNX_MODEL
    # kmodel 模型文件
    kmodel_path = KMODEL_PATH
    # 生成onnx模型输入数据
    onnx_input_data = get_onnx_input(img_path,mean,std,model_input_size)
    # 生成kmodel模型输入数据
    kmodel_input_data = get_kmodel_input(img_path,mean,std,model_input_size)
    # onnx模型推理
    onnx_results = onnx_inference(onnx_model,onnx_input_data)
    # kmodel模型推理
    nncase_results = kmodel_inference(kmodel_path,kmodel_input_data,model_input_size)
    # 计算输出相似度
    cosine_similarity(onnx_results,nncase_results)

1 Answers

修改什么文件地址了

.kmodel的地址啊,改成我自己的了

代码放上面了

加载模型有问题,可能是你的模型转的不对