K210学习记录(3)——kmodel生成与使用

0、引言

该博客仅作为学习K210单片机KPU跑目标检测模型记录,本人新人小白,本文旨在备忘,如有错误,还望指出,谢谢。
硬件:Sipeed Maix Dock开发板
软件:MaixPy IDE,NNCase Converter v0.1.0 RC5(模型转换工具)
相关工具及软件点击这里不需积分下载

1、模型转换

1.1、首先需要下载NNCase工具箱,各版本下载地址
1.2、有关nnc的使用,在Windows下首先在运行中,输入CMD,打开命令行窗口
1.3、使用cd命令,到nnc的根目录下
1.4、后使用nnc相关命令行进行操作,命令行说明可以参考
在将yolo.tflite模型放到ncc根目录下后,使用以下命令进行转换

ncc yolo.tflite yolo.kmodel -i tflite -o k210model --dataset images

其中yolo.tflite为ncc工具根目录下的待转换模型,yolo.kmodel为转换完成的模型名称(提前设定),-i tflite代表输入模型格式,而-o k210model则代表输出模型模式,–dataset images代表量化图片所存放的文件夹,images是文件夹名,一般放入训练集图片即可。
最终即可在ncc根目录下找到转换完成的kmodel文件
K210学习记录(3)——kmodel生成与使用_第1张图片

同时,你也可以使用QT版ncc转换工具,目前仅支持tflift格式的模型文件
K210学习记录(3)——kmodel生成与使用_第2张图片

2、模型使用

2.1、检查模型

通过上述步骤得到kmodel文件后,将其拷贝进FAT32格式的TF卡中(可以不用格式化),后将TF卡插入K210开发板
并使用以下代码进行测试。如成功读取到TF卡中的模型文件,液晶屏上将显示模型地址及模型尺寸。如下图所示

from Maix import GPIO, I2S, FFT
import image, lcd, math,sensor,time
import KPU as kpu

#初始化液晶屏
lcd.init(freq=15000000)
lcd.clear()

#加载SD卡中的模型
task = kpu.load("/sd/yolo.kmodel")
##测试模型是否加载成功,如成功会返回模型地址和模型尺寸
lcd.draw_string(1, 1, str(task), lcd.RED, lcd.BLACK)

K210学习记录(3)——kmodel生成与使用_第3张图片

其中kpu.load()函数的使用说明详见此,博客地址
K210学习记录(3)——kmodel生成与使用_第4张图片
源代码见此

STATIC mp_obj_t py_kpu_class_load(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
{
     
    int err = 0;
    uint32_t model_size;
    py_kpu_net_obj_t  *o = m_new_obj_with_finaliser(py_kpu_net_obj_t);
    o->base.type = &py_kpu_net_obj_type;

    if(mp_obj_get_type(pos_args[0]) == &mp_type_int)
    {
     	//load from flash address
        mp_int_t model_addr = mp_obj_get_int(pos_args[0]);

        if(model_addr <= 0)//TODO: address of code end
        {
     
            m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
            mp_raise_ValueError("[MAIXPY]kpu: model_addr must > 0 ");
            return mp_const_false;
        }

        o->model_addr = mp_obj_new_int(model_addr);
        o->model_path = mp_const_none;
		sipeed_kpu_err_t ret = sipeed_kpu_model_load(&o->kmodel_ctx, model_addr, NULL, &model_size);
        if(ret != SIPEED_KPU_ERR_NONE)
        {
     
            err = ret; //load error
            goto error;
        }
    }
    else if(mp_obj_get_type(pos_args[0]) == &mp_type_str)
    {
     
        const char *path = mp_obj_str_get_str(pos_args[0]);

        o->model_path = mp_obj_new_str(path,strlen(path));
        o->model_addr = mp_const_none;

        // if(NULL != strstr(path,".bin"))
        // {
     
        //     err=model_init(kpu_task,path);
        //     if( err != 0 )
        //     {
     
        //         model_deinit(kpu_task);
        //         goto error;
        //     }

        // }
        // else
        if( (NULL != strstr(path,".kmodel")) || (NULL != strstr(path,".smodel")) || (NULL != strstr(path,".emodel")) )
        {
     
            int ret = sipeed_kpu_model_load(&o->kmodel_ctx, 0, path, &model_size);
            if(ret != SIPEED_KPU_ERR_NONE)
            {
     
                err = ret;
                goto error;
            }
        }
        else
        {
        
            m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
            mp_raise_ValueError("[MAIXPY]kpu: model format don't match, only supply .kmodel ");
            return mp_const_false;
        }
        
    }
    else
    {
     
        m_del(py_kpu_net_obj_t, o,sizeof(py_kpu_net_obj_t));
        mp_raise_TypeError("[MAIXPY]kpu: only accept int or string");
        return mp_const_false;
    }    
    o->net_args = mp_const_none;
    o->net_deinit = mp_const_none;
    o->model_size = mp_obj_new_int(model_size);
    o->max_layers = mp_obj_new_int(sipeed_kpu_model_get_layer_num(o->kmodel_ctx));

    return MP_OBJ_FROM_PTR(o);

error:
{
     
    char* err_msg = get_kpu_err_str(err);
    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "[MAIXPY]kpu: load error:%d, %s", err, err_msg));
}
}

STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_kpu_class_load_obj, 1, py_kpu_class_load);

在确认K210单片机能正确识别到tf卡中的kmodel后,我们就可以进行下一步的工作了。

2.2、使用模型

from Maix import GPIO, I2S, FFT
import image, lcd, math,sensor,time
import KPU as kpu

#对摄像头进行初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
#sensor.set_windowing((224, 224))
#sensor.set_windowing((320, 240))
sensor.set_brightness(2)
sensor.set_vflip(1)
sensor.run(1)

#初始化液晶屏
lcd.init(freq=15000000)
lcd.clear()


clock = time.clock()
#标签类名
classes = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat',
'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person',
'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']

#加载SD卡中的模型
task = kpu.load("/sd/yolo.kmodel")
##测试模型是否加载成功,如成功会返回模型地址和模型尺寸
#lcd.draw_string(1, 1, str(task), lcd.RED, lcd.BLACK)

#设置锚框大小
anchor = (1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52)
#初始化kpu yolo2
#形参:模型尺寸,mp_obj
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):
    #用于计算FPS值
    clock.tick()
    #将摄像头采集到的值赋给img这个变量
    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img)
    #打印帧率(115200)
    print(clock.fps())
    if code:
        for i in code:
       		#画矩形框
            a=img.draw_rectangle(i.rect())
         	#显示出来
            a = lcd.display(img)
            for i in code:
            #打印类标签(根据bbox位置)
                lcd.draw_string(i.x(), i.y(), classes[i.classid()], lcd.RED, lcd.WHITE)
                lcd.draw_string(i.x(), i.y()+12, '%f1.3'%i.value(), lcd.RED, lcd.WHITE)
    else:
        a = lcd.display(img)
a = kpu.deinit(task)

3、参考资料

https://github.com/TonyZ1Min/yolo-for-k210
https://blog.sipeed.com/p/677.html
https://github.com/kendryte/nncase/tree/master/examples/20classes_yolo

你可能感兴趣的:(K210单片机学习,K210,kmodel,yolo)