21电赛-智能送药小车之视觉识别部分详解

一、任务要求

设计并制作智能送药小车,模拟完成在医院药房与病房间药品的送取作业。 院区结构示意如图1所示。院区走廊两侧的墙体由黑实线表示。走廊地面上画有 居中的红实线,并放置标识病房号的黑色数字可移动纸张。药房和近端病房号(1、2 号)如图1所示位置固定不变,中部病房和远端病房号(3-8号)测试时随机设定。

工作过程:参赛者手动将小车摆放在药房处(车头投影在门口区域内,面向 病房),手持数字标号纸张由小车识别病房号,将约 200g 药品一次性装载到送药小车上;小车检测到药品装载完成后自动开始运送;小车根据走廊上的标识信 息自动识别、寻径将药品送到指定病房(车头投影在门口区域内),点亮红色指示灯,等待卸载药品;病房处人工卸载药品后,小车自动熄灭红色指示灯,开始返回;小车自动返回到药房(车头投影在门口区域内,面向药房)后,点亮绿色指示灯。

21电赛-智能送药小车之视觉识别部分详解_第1张图片

二、视觉部分实现

1.K210简介

K210全称为堪智K210,是嘉楠科技自主研发的一款采用RISC-V处理器架构,具备视听一体、自主IP内核与可编程能力强三大特点,支持机器视觉与机器听觉多模态识别,可广泛应用于智能家居、智能园区、智能能耗和智能农场等场景。

21电赛-智能送药小车之视觉识别部分详解_第2张图片

我们采用的是DOCK板

21电赛-智能送药小车之视觉识别部分详解_第3张图片

开发环境及语言

MicroPython 是基于 Python3 的语法做的一款解析器,包含了 Python3 的大多数基础语法, 主要运行在性能和内存有限的嵌入式芯片上。(注意 Micropython 不包含 Python3 的所有语法)

编译器

21电赛-智能送药小车之视觉识别部分详解_第4张图片

详细配置及教程参考官方文档
MaixPy 文档简介 - Sipeed Wiki

2.数字识别实现

最初尝试模型库中手写数字识别,效果不太好,于是我们决定自己制作数据集,上传到Maixhub训练模型。

采用目标检测方法训练yolo模型, 使用K210采集数字照片,按照数字“1”到“8”进行数据集标注和打包后,上传数据集并创建训练任务。

1) 数据集制作

(这是21年做的 当时官网训练模型要求数据集的格式如下(旧版本))

21电赛-智能送药小车之视觉识别部分详解_第5张图片
21电赛-智能送药小车之视觉识别部分详解_第6张图片

现在新版已经可以支持在线导入图片、进行标注。

也可以本地导入上传压缩包(这里和旧版略有不同)。

文章是maixhub新版的本地上传的方法,最近试了试之前的格式不能用了。大家可以尝试在线导入图片、标注,比较便捷。

2)数据集的格式

21电赛-智能送药小车之视觉识别部分详解_第7张图片

按如上格式分别制作1~8 ,8个压缩包

例:"1"文件夹

21电赛-智能送药小车之视觉识别部分详解_第8张图片

images文件夹

存放照片 注意大小224×224

21电赛-智能送药小车之视觉识别部分详解_第9张图片

xml文件夹

数据标注

存放每个照片对应的xml文件(即标注完的照片)

标注软件

21电赛-智能送药小车之视觉识别部分详解_第10张图片

数据集标注

21电赛-智能送药小车之视觉识别部分详解_第11张图片

最后压缩

按相同步骤制作2~8,最后有8个压缩包

3)训练模型

MaixHub 训练模型网址

创建项目

21电赛-智能送药小车之视觉识别部分详解_第12张图片

项目类型是图像检测

21电赛-智能送药小车之视觉识别部分详解_第13张图片

创建数据集

21电赛-智能送药小车之视觉识别部分详解_第14张图片

选择从本地上传数据集

21电赛-智能送药小车之视觉识别部分详解_第15张图片

批量选择一部分放到验证集,也可以不放

官网给出的介绍

创建任务

21电赛-智能送药小车之视觉识别部分详解_第16张图片

最后部署模型,手动部署即可

这里是我训练完的,可以下载

源码即模型下载 K210数字识别模型含代码

三、K210与STM32通信代码

将识别到的数字传送到32端


import sensor, image, lcd, time
import KPU as kpu
import gc, sys
from machine import UART
from fpioa_manager import fm
fm.register(8, fm.fpioa.UART1_RX, force=True) #串口
fm.register(9, fm.fpioa.UART1_TX, force=True) #串口
uart = UART(UART.UART1, 115200, read_buf_len=4096)

def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=(224,224))
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)

def main(anchors, labels = None, model_addr="/sd/m.kmodel", sensor_window=(224, 224), lcd_rotation=0, sensor_hmirror=True, sensor_vflip=True):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_hmirror(sensor_hmirror)
    sensor.set_vflip(sensor_vflip)
    sensor.run(1)

    lcd.init(type=1)
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)

    if not labels:
        with open('labels.txt','r') as f:
            exec(f.read())
    if not labels:
        print("no labels.txt")
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
        lcd.display(img)
        return 1
    try:
        img = image.Image("startup.jpg")
        lcd.display(img)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
        lcd.display(img)

    try:
        task = None
        task = kpu.load(model_addr)
        kpu.init_yolo2(task, 0.5, 0.3, 5, anchors) # threshold:[0,1], nms_value: [0, 1]
        while(True):
            img = sensor.snapshot()
            t = time.ticks_ms()
            objects = kpu.run_yolo2(task, img)
            t = time.ticks_ms() - t
            if objects:
                for obj in objects:
                    pos = obj.rect()   #返回一个坐标元组x y w h
                    if obj.value() >0.7:#识别到的概率大于0.7才判断,提高准确度
                        img.draw_rectangle(pos) #把图片框起来
                        img.draw_string(pos[0], pos[1], "%s : %.2f" %(labels[obj.classid()], obj.value()), scale=2, color=(255, 0, 0) #lcd上打上标签
                  
                        uart.write(labels[obj.classid()]+'\r\n')
                        #print(c,pic_posy)
            img.draw_string(0, 200, "t:%dms" %(t), scale=2, color=(255, 0, 0))
            lcd.display(img)
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)


if __name__ == "__main__":
    try:
        labels = ["1", "2", "3", "4", "5", "6", "7", "8"]
        anchors = [2.53125, 3.5625, 2.125, 3.03125, 2.9375, 4.0, 3.75, 5.375, 4.6875, 6.09375]
        # main(anchors = anchors, labels=labels, model_addr=0x300000, lcd_rotation=0)
        main(anchors = anchors, labels=labels, model_addr="/sd/m.kmodel")
    except Exception as e:
        sys.print_exception(e)
        lcd_show_except(e)
    finally:
        gc.collect()



你可能感兴趣的:(单片机,目标检测)