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