文章目录
目录
self.labels[class_id] == "Starting point"函数
前言
提示:这里可以添加本文要记录的大概内容:
本文章适用于V831(M2dock),训练的模型为2021年全国大学生电子设计大赛F(无人机)组的起点识别和绿色(草坪)识别
提示:以下是本篇文章正文内容,下面案例可供参考
一、关于训练模型
有可能很多人和我刚开始一样,使用手机拍拍照上传照片然后训练出来的模型识别度有80%以上。但是部署到v831后实际的识别效果却不佳
因为分辨率的关系,手机拍照的照片分辨率太高了。正确的方法应该是下载maixhub固件使用V831进行拍照,上传照片训练模型
这里推荐大家烧录后缀为maixhub的固件,其中内置了maixhub app可以直接进行拍照
固件下载链接下载站 - Sipeedhttps://dl.sipeed.com/shareURL/MaixII/MaixII-Dock/SDK/release
部署模型详细见大老鼠的视频
M2DOCK:国产全志 V831 开源 人工智能 神经网络 在线训练 AI 服务 maixhub 速览_哔哩哔哩_bilibili
二、代码
1.引入库
from maix import nn, camera, display, image, gpio
import serial
import binascii
import time
2.引用数定义IO
代码如下(示例):
ser = serial.Serial("/dev/ttyS1", 115200) # 连接串口
# 设置输入图像的尺寸
input_size = (224, 224)
# 加载模型和标签
model = "model-68044.awnn.mud"
# 设置检测物体名称
labels = ['Starting point']
anchors = [4.28, 4.31, 4.78, 4.78, 5.39, 5.48, 5.03, 5.0, 4.48, 4.53]
set_LAB = [(49, 72, -38, -2, 4, 40)] # 草坪的颜色
# 这里定义了PH6的引脚为led
led = gpio.gpio(6, "H", 1)
ttyS1指的是对应的串口号,我这里是串口1, 115200指的是波特率,到时候上位机读取数据时要注意调整成一样的
labels是你训练的标签名字,这个很重要(刚刚好开始学的时候不知道他的重要性)。如果检测到模型则会在OLED上的图像画框标注名称,但是中文会乱码。在后面的函数中还会用到这个名称,建议为数字或者英文
3.模型生成代码
基本不用管
class YOLOv2:
def __init__(self, model_path, labels, anchors, net_in_size, net_out_size):
self.labels = labels
self.anchors = anchors
self.net_in_size = net_in_size
self.net_out_size = net_out_size
print("-- load model:", model)
self.model = nn.load(model_path)
self._decoder = nn.decoder.Yolo2(len(labels), anchors, net_in_size=net_in_size, net_out_size=net_out_size)
# 进行目标识别检测
def run(self, img, nms=0.3, threshold=0.5):
out = self.model.forward(img, layout="hwc")
boxes, probs = self._decoder.run(out, nms=nms, threshold=threshold, img_size=input_size)
return boxes, probs
4.在图像上绘制检测到的目标框和标签
这里也是模型代码的一部分,但是基本上检测都在这
def draw(self, img, boxes, probs):
for i, box in enumerate(boxes):
class_id = probs[i][0]
prob = probs[i][1][class_id]
msg = "{}:{:.2f}%".format(self.labels[class_id], prob*100)
img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3], color=(255, 255, 255), thickness=2)
img.draw_string(box[0] + 2, box[1] + 2, msg, scale = 1.2, color = (255, 255, 255), thickness = 2)
# 如果检测到(Starting point)起飞点
if self.labels[class_id] == "Starting point":
# 在找到 "Starting point" 时执行的操作
found_starting_point = True
if found_starting_point:
# 要发送的十六进制数据
Starting_point_data = '05'
# 将十六进制数据转换为字节(byte)数组
byte_Starting_point = bytes.fromhex(Starting_point_data)
# 发送数据检测到起点的
ser.write(byte_Starting_point)
# 发送数据包box
# binascii.hexlify()函数将字节流转换为十六进制字符串使用
# decode('utf-8')将字节字符串解码为普通的字符串
# bytes.fromhex()函数将十六进制字符串转换回字节流格式
# ///头帧为'00'尾帧为'FF'中间的为box/
flag_head_data = '00'
flag_tail_data = 'FF'
byte_flag_head = bytes.fromhex(flag_head_data)
# 头帧先进行发送
ser.write(byte_flag_head)
box_hex = binascii.hexlify(bytearray(box)).decode('utf-8')
box_bytes = bytes.fromhex(box_hex)
ser.write(box_bytes)
# box发送完毕
# 开始发送尾帧
byte_flag_tail = bytes.fromhex(flag_tail_data)
# 尾帧再进行发送
ser.write(byte_flag_tail)
self.labels[class_id] == "Starting point"函数
这个函数是判断是否检测到上述所说的labels,一个训练集的有多个标签时,会有多个labels。该函数将"XX"的XX进行检验
ser.write()函数
ser.write()发送的数据类型是字节串(bytes
),所以我们将数据发送给电脑或者32等单片机都得要进行数据转换,但是如果是V831这边检测倒是XX,就给个信号就行的话。也可以直接发送一个字节串,然后单片机那边的串口检验一下,单片机做出判断或者执行XXX命令语句
如果要把模型的数据发送出去就得要将字节流转换为十六进制字符串使用binascii.hexlify(函数将字节流转换为十六进制字符串你要发送的原始数据函数)
decode('utf-8')将字节字符串解码为普通的字符串
bytes.fromhex()函数将十六进制字符串转换回字节流格式
box[]列表的内容
左上角x box[0]
左上角y box[1]
wide box[2]
high box[3]
右下角x box[0] + box[2]
右上角y box[1] + box[3]
main()函数
在训练出的模型代码中,main()函数是调用了def main():
if __name__ == "__main__":
try:
main()
# /以下是异常情况给屏幕出现的现象,基本上不用管///
except Exception as e:
import traceback, time
msg = traceback.format_exc()
print(msg)
img = image.new(size = (240, 240), color = (255, 0, 0), mode = "RGB")
img.draw_string(0, 0, msg, scale = 0.8, color = (255, 255, 255), thickness = 1)
display.show(img)
所以如果我们要对main()函数进行修改基本上在中进行修改def main():
def main():
在训练出的模型代码中,def main():只是进行了对检测物体画框的操作
def main():
camera.config(size=input_size)
yolov2 = YOLOv2(model, labels, anchors, input_size, (input_size[0] // 32, input_size[1] // 32))
while True:
img = camera.capture()
boxes, probs = yolov2.run(img, nms=0.3, threshold=0.5)
yolov2.draw(img, boxes, probs)
blobs = img.find_blobs(set_LAB)
if blobs:
# led.set_value表示对led进行高电平/低电平的赋值
led.set_value(0)
time.sleep(0.01)
led.set_value(1)
time.sleep(0.01)
display.show(img)
这里是检测到set_LAB(设定颜色)后PH6进行高低电平的转换
img.find_blobs()函数是检测图像中设定颜色的LAB 阈值
由于CSDN上传文件下载有问题所以给大家一下模型文件的链接
链接:https://pan.baidu.com/s/1eqG0f_HeetigP5qPdUdWiA?pwd=i41r
提取码:i41r
总结
V831生态还不太好,本人刚开始学的时候也是没什么资料,希望本文章可以帮到大家。文章内如有不对,欢迎斧正