21电赛-智能送药小车(视觉)数字识别部分详解
一、任务要求
设计并制作智能送药小车,模拟完成在医院药房与病房间药品的送取作业。 院区结构示意如图1所示。院区走廊两侧的墙体由黑实线表示。走廊地面上画有 居中的红实线,并放置标识病房号的黑色数字可移动纸张。药房和近端病房号(1、2 号)如图1所示位置固定不变,中部病房和远端病房号(3-8号)测试时随机设定。
工作过程:参赛者手动将小车摆放在药房处(车头投影在门口区域内,面向 病房),手持数字标号纸张由小车识别病房号,将约 200g 药品一次性装载到送药小车上;小车检测到药品装载完成后自动开始运送;小车根据走廊上的标识信 息自动识别、寻径将药品送到指定病房(车头投影在门口区域内),点亮红色指示灯,等待卸载药品;病房处人工卸载药品后,小车自动熄灭红色指示灯,开始返回;小车自动返回到药房(车头投影在门口区域内,面向药房)后,点亮绿色指示灯。
![](https://i-blog.csdnimg.cn/blog_migrate/610e024528000279425516bf5617f8a0.png)
二、视觉部分实现
1.K210简介
K210全称为堪智K210,是嘉楠科技自主研发的一款采用RISC-V处理器架构,具备视听一体、自主IP内核与可编程能力强三大特点,支持机器视觉与机器听觉多模态识别,可广泛应用于智能家居、智能园区、智能能耗和智能农场等场景。
![](https://i-blog.csdnimg.cn/blog_migrate/2e84fc73d85080831d1949fa22e49173.png)
我们采用的是DOCK板
![](https://i-blog.csdnimg.cn/blog_migrate/cb58746065c58a627b39efaa48cdac31.png)
开发环境及语言
MicroPython 是基于 Python3 的语法做的一款解析器,包含了 Python3 的大多数基础语法, 主要运行在性能和内存有限的嵌入式芯片上。(注意 Micropython 不包含 Python3 的所有语法)
编译器
![](https://i-blog.csdnimg.cn/blog_migrate/f50f53f756e03cbed9b8db07345c736e.png)
详细配置及教程参考官方文档
MaixPy 文档简介 - Sipeed Wiki
2.数字识别实现
最初尝试模型库中手写数字识别,效果不太好,于是我们决定自己制作数据集,上传到Maixhub训练模型。
采用目标检测方法训练yolo模型, 使用K210采集数字照片,按照数字“1”到“8”进行数据集标注和打包后,上传数据集并创建训练任务。
1) 数据集制作
(这是21年做的 当时官网训练模型要求数据集的格式如下(旧版本))
![](https://i-blog.csdnimg.cn/blog_migrate/6d7b76b58a8cc1b60889eb7907322e2b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/100b669ac99fe1e6187e39b2b71b5aa4.png)
现在新版已经可以支持在线导入图片、进行标注。
也可以本地导入上传压缩包(这里和旧版略有不同)。
文章是maixhub新版的本地上传的方法,最近试了试之前的格式不能用了。大家可以尝试在线导入图片、标注,比较便捷。
2)数据集的格式
![](https://i-blog.csdnimg.cn/blog_migrate/c9fecee77058350c5633a405fa71e79c.png)
按如上格式分别制作1~8 ,8个压缩包
例:"1"文件夹
![](https://i-blog.csdnimg.cn/blog_migrate/38c3acb7276c155e63dc8ac53b36f081.png)
![](https://i-blog.csdnimg.cn/blog_migrate/10df3ba056a943e1871f5d5ef1666b7e.png)
images文件夹
存放照片 注意大小224×224
![](https://i-blog.csdnimg.cn/blog_migrate/13a2ca376103257ba3bf101f8ddd345b.png)
xml文件夹
数据标注
存放每个照片对应的xml文件(即标注完的照片)
![](https://i-blog.csdnimg.cn/blog_migrate/dae5a8b0ccd19bdb6906651731b14e87.png)
标注软件
![](https://i-blog.csdnimg.cn/blog_migrate/bbd4765770226a0fdcd2265db4975ebf.png)
数据集标注
![](https://i-blog.csdnimg.cn/blog_migrate/c44a4877a4cbf9bb70c1222682f9c90b.png)
最后压缩
![](https://i-blog.csdnimg.cn/blog_migrate/4d2e471d5bc7d27a8eb5f4dfe39f5e26.png)
按相同步骤制作2~8,最后有8个压缩包
这个标注操作不熟练,可以在上传完图片之后官网在线标注,非常便捷。
![](https://i-blog.csdnimg.cn/blog_migrate/c4163a7a32c02b5240d31c80d88d216a.png)
3)训练模型
MaixHub 训练模型网址
创建项目
![](https://i-blog.csdnimg.cn/blog_migrate/34e7c71468ed4955d95a4a925d34a3e3.png)
项目类型是图像检测
![](https://i-blog.csdnimg.cn/blog_migrate/821cb2fb51b2b0b06b6b8e9ef9751b06.png)
创建数据集
![](https://i-blog.csdnimg.cn/blog_migrate/a89b0588eb77a7b9a4320a3f2d4004c7.png)
选择从本地上传数据集
![](https://i-blog.csdnimg.cn/blog_migrate/84bbdb66455e3136e1b6e86b4fa5a434.png)
批量选择一部分放到验证集,也可以不放
![](https://i-blog.csdnimg.cn/blog_migrate/d32b6277e962778a98a375ec0c3ec371.png)
官网给出的介绍
创建任务
![](https://i-blog.csdnimg.cn/blog_migrate/7671cda2e89ae78dd2d8a2a5fa0b7326.png)
最后部署模型,手动部署即可
这里是我训练完的,可以下载
源码即模型下载 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()
更多推荐
所有评论(0)