新用户注册入口 老用户登录入口

[转载]OpenMV数字识别进而控制直流电机转速【小白篇】

文章作者:转载 更新时间:2024-01-10 08:44:41 阅读数量:281
文章标签:OpenMV数字识别模型训练图像预处理数据调整JPG格式转换
本文摘要:本文作者记录了初次使用OpenMV进行数字识别项目的实践过程,涉及从MNIST数据集的下载与预处理(包括将ubyte格式转换为jpg格式、按标签分类图片)到模型训练的关键步骤。在模型训练阶段,由于云端训练限制及国外书写习惯差异,作者针对性地对数据集进行了筛选优化,并通过调整图像参数提高了识别准确率。最终,作者成功将训练好的模型部署至OpenMV设备上,实现了通过识别摄像头捕捉的数字来控制直流电机转速的目标检测功能。整个项目涵盖了OpenMV、数字识别、MNIST数据集、模型训练、图像预处理、数据调整、JPG格式转换、UBYTE格式、目标检测以及云端训练等多个关键技术环节。
转载文章

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_57100435/article/details/130740351。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

文章目录

  • 前言
  • 一、数字识别模型训练
    • 1.下载训练集
    • 2.对数据进行调整
      • 2.1 将ubyte格式转为jpg格式
      • 2.2 将图片按照标签分类到具体文件夹
      • 2.3 数据存在的缺陷
      • 2.4 优化建议(核心)
  • 二、模型训练
  • 三、项目实现
    • 1. 代码实现
    • 2. 采用器件
    • 2. 注意事项
  • 总结


前言

第一次接触OpenMV也是第一次将理论用于实践,是老师让我实现的一个小测验,这几天完成后决定写下完整的过程。本文主要是当缝合怪,借鉴和参考了其他人的代码再根据我个人设备进行了一定的调整,此外还包括了我自身实践过程中的一些小意外。
!!!一定要根据个人器件型号和个人设备来参考


一、数字识别的模型训练

1.下载训练集

研究期间,我发现大部分人以及官网教程采用的都是自己拍摄照片再进行网络训练,存在的缺陷就是数据集较小不全面、操作繁琐。个人认为如果是对标准的数字进行识别,自己手动拍取照片进行识别足够了。但想要应用于更广泛的情况,应该寻找更大的数据集,所以我找到了国外手写数字的数据集MNIST。建议四个文件都下载
数据链接:MINIST数据集

2.对数据进行调整

2.1 将ubyte格式转为jpg格式

代码参考链接:python将ubyte格式的MNIST数据集转成jpg图片格式并保存

import numpy as np
import cv2
import os
import structdef trans(image, label, save):#image位置,label位置和转换后的数据保存位置if 'train' in os.path.basename(image):prefix = 'train'else:prefix = 'test'labelIndex = 0imageIndex = 0i = 0lbdata = open(label, 'rb').read()magic, nums = struct.unpack_from(">II", lbdata, labelIndex)labelIndex += struct.calcsize('>II')imgdata = open(image, "rb").read()magic, nums, numRows, numColumns = struct.unpack_from('>IIII', imgdata, imageIndex)imageIndex += struct.calcsize('>IIII')for i in range(nums):label = struct.unpack_from('>B', lbdata, labelIndex)[0]labelIndex += struct.calcsize('>B')im = struct.unpack_from('>784B', imgdata, imageIndex)imageIndex += struct.calcsize('>784B')im = np.array(im, dtype='uint8')img = im.reshape(28, 28)save_name = os.path.join(save, '{}_{}_{}.jpg'.format(prefix, i, label))cv2.imwrite(save_name, img)if __name__ == '__main__':#需要更改的文件路径!!!!!!#此处是原始数据集位置train_images = 'C:/Users/ASUS/Desktop/train-images.idx3.ubyte'train_labels = 'C:/Users/ASUS/Desktop/train-labels.idx1.ubyte'test_images ='C:/Users/ASUS/Desktop/t10k-images.idx3.ubyte'test_labels = 'C:/Users/ASUS/Desktop/t10k-labels.idx1.ubyte'#此处是我们将转化后的数据集保存的位置save_train ='C:/Users/ASUS/Desktop/MNIST/train_images/'save_test ='C:/Users/ASUS/Desktop/MNIST/test_images/'if not os.path.exists(save_train):os.makedirs(save_train)if not os.path.exists(save_test):os.makedirs(save_test)trans(test_images, test_labels, save_test)trans(train_images, train_labels, save_train)

2.2 将图片按照标签分类到具体文件夹

文章参考链接:python实现根据文件名自动分类转移至不同的文件夹
注意:为了适合这个数据集和我的win11系统对代码进行了一点调整,由于数据很多如果只需要部分数据一定要将那些数据单独放在一个文件夹。

# 导入库
import os
import shutil# 当前文件夹所在的路径,使用时需要进行修改
current_path = 'C:/Users/ASUS/Desktop/MNIST/test'
print('当前文件夹为:' + current_path)# 读取该路径下的文件
filename_list = os.listdir(current_path)# 建立文件夹并且进行转移
# 假设原图片名称 test_001_2.jpg
for filename in filename_list:name1, name2, name3 = filename.split('_')   # name1 = test  name2 = 001  name3 = 2.jpgname4, name5 = name3.split('.')             # name4 = 2  name5 = jpgif name5 == 'jpg' or name5 == 'png':try:os.mkdir(current_path+'/'+name4)print('成功建立文件夹:'+name4)except:passtry:shutil.move(current_path+'/'+filename, current_path+'/'+name4[:])print(filename+'转移成功!')except Exception as e:print('文件 %s 转移失败' % filename)print('转移错误原因:' + e)print('整理完毕!')

2.3 数据存在的缺陷

  1. 数据集内的图片数量很多,由于后面介绍的云端训练的限制,只能采用部分数据(本人采用的是1000张,大家可以自行增减数目)。

  2. 数据集为国外的数据集,很多数字写的跟我们不一样。如果想要更好的适用于我们国内的场景,可以对数据集进行手动的筛选。下面是他们写的数字2:

可以看出跟我们的不一样,不过数据集中仍然存在跟常规书写的一样的,我们需要进行人为的筛选。

2.4 优化建议(核心)

分析发现,部分数字精度不高的原因主要是国外手写很随意,我们可以通过调整网络参数(如下)、人为筛选数据(如上)、增大数据集等方式进行优化。


二、模型训练

主要参考文章:通过云端自动生成openmv的神经网络模型,进行目标检测
!!!唯一不同的点是我图像参数设置的是灰度而不是上述文章的RGB。
下面是我模型训练时的参数设置(仅供参考):
在这里插入图片描述
通过混淆矩阵可以看出,主要的错误在于数字2、6、8。我们可以通过查看识别错误的数字来分析可能的原因。


三、项目实现

!!!我们需要先将上述步骤中导出文件中的所有内容复制粘贴带OpenMV中自带的U盘中。然后将其中的.py文件名称改为main

1. 代码实现

本人修改后的完整代码展示如下,使用的是OpenMV IDE(官网下载):

# 数字识别后控制直流电机转速
from pyb import Pin, Timer
import sensor, image, time, os, tf, math, random, lcd, uos, gc# 根据识别的数字输出不同占比的PWM波
def run(number):if inverse == True:ain1.low()ain2.high()else:ain1.high()ain2.low()ch1.pulse_width_percent(abs(number*10))# 具体参数调整自行搜索
sensor.reset()                         # 初始化感光元件
sensor.set_pixformat(sensor.GRAYSCALE) # set_pixformat : 设置像素模式(GRAYSCALSE : 灰色; RGB565 : 彩色)
sensor.set_framesize(sensor.QQVGA2)      # set_framesize : 设置处理图像的大小
sensor.set_windowing((128, 160))       # set_windowing : 设置提取区域大小
sensor.skip_frames(time = 2000)        # skip_frames :跳过2000ms再读取图像
lcd.init()                             # 初始化lcd屏幕。inverse = False                        # True : 电机反转  False : 电机正转
ain1 =  Pin('P1', Pin.OUT_PP)          # 引脚P1作为输出
ain2 =  Pin('P4', Pin.OUT_PP)          # 引脚P4作为输出
ain1.low()                             # P1初始化低电平
ain2.low()                             # P4初始化低电平
tim = Timer(2, freq = 1000)            # 采用定时器2,频率为1000Hz
ch1 = tim.channel(4, Timer.PWM, pin = Pin('P5'), pulse_width_percent = 100) # 输出通道1 配置PWM模式下的定时器(高电平有效) 端口为P5 初始占空比为100%
clock = time.clock()                   # 设置一个时钟用于追踪FPS# 加载模型
try:net = tf.load("trained.tflite", load_to_fb=uos.stat('trained.tflite')[6] > (gc.mem_free() - (64*1024)))
except Exception as e:print(e)raise Exception('Failed to load "trained.tflite", did you copy the .tflite and labels.txt file onto the mass-storage device? (' + str(e) + ')')# 加载标签
try:labels = [line.rstrip('\n') for line in open("labels.txt")]
except Exception as e:raise Exception('Failed to load "labels.txt", did you copy the .tflite and labels.txt file onto the mass-storage device? (' + str(e) + ')')# 不断的进行运行
while(True):clock.tick()                                    # 更新时钟img = sensor.snapshot().binary([(0,64)])        # 抓取一张图像以灰度图显示lcd.display(img)                                # 拍照并显示图像for obj in net.classify(img, min_scale=1.0, scale_mul=0.8, x_overlap=0.5, y_overlap=0.5):# 初始化最大值和标签max_num = -1max_index = -1print("**********\nPredictions at [x=%d,y=%d,w=%d,h=%d]" % obj.rect())img.draw_rectangle(obj.rect())# 预测值和标签写成一个列表predictions_list = list(zip(labels, obj.output()))# 输出各个标签的预测值,找到最大值进行输出for i in range(len(predictions_list)):print('%s 的概率为: %f' % (predictions_list[i][0], predictions_list[i][1]))if predictions_list[i][1] > max_num:max_num =  predictions_list[i][1]max_index = int(predictions_list[i][0])run(max_index)print('该数字预测为:%d' % max_index)print('FPS为:', clock.fps())print('PWM波占空比为: %d%%' % (max_index*10))

2. 采用器件

使用的器件为OpenMV4 H7 Plus和L298N以及常用的直流电机关键是找到器件的引脚图,再进行简单的连线即可。
参考文章:【L298N驱动模块学习笔记】–openmv驱动
参考文章:【openmv】原理图 引脚图

2. 注意事项

上述代码中我用到了lcd屏幕,主要是为了方便离机操作。使用过程中,OpenMV的lcd初始化时会重置端口,所有我们在输出PWM波的时候一定不要发生引脚冲突。我们可以在OpenMV官网查看lcd用到的端口:
在这里插入图片描述
可以看到上述用到的是P0、P2、P3、P6、P7和P8。所有我们输出PWM波时要避开这些端口。下面是OpenMV的PWM资源:
在这里插入图片描述


总结

本人第一次自己做东西也是第一次使用python,所以代码和项目写的都很粗糙,只是简单的识别数字控制直流电机。我也是四处借鉴修改后写下的大小,这篇文章主要是为了给那些像我一样的小白们提供一点帮助,减少大家查找资料的时间。模型的缺陷以及改进方法上述中已经说明,如果我有写错或者大家有更好的方法欢迎大家告诉我,大家一起进步!

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_57100435/article/details/130740351。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

相关阅读
文章标题:[转载][洛谷P1082]同余方程

更新时间:2023-02-18
[转载][洛谷P1082]同余方程
文章标题:[转载]webpack优化之HappyPack实战

更新时间:2023-08-07
[转载]webpack优化之HappyPack实战
文章标题:[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法

更新时间:2023-09-10
[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法
文章标题:[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo

更新时间:2024-03-11
[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo
文章标题:[转载]程序员也分三六九等?等级差异,一个看不起一个!

更新时间:2024-05-10
[转载]程序员也分三六九等?等级差异,一个看不起一个!
文章标题:[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集

更新时间:2024-01-12
[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集
名词解释
作为当前文章的名词解释,仅对当前文章有效。
MNIST数据集MNIST是一个广泛应用于机器学习和计算机视觉领域的手写数字数据库,全称为“Modified National Institute of Standards and Technology”(改进版美国国家标准与技术研究所)手写数字数据集。在本文中,作者使用MNIST数据集来训练模型进行数字识别任务,该数据集包含60,000个训练样本和10,000个测试样本,每个样本都是28x28像素的灰度图像,并且已按照0-9的标签分类。
OpenMVOpenMV是一款专为机器视觉设计的微型控制器开发平台,它集成了高性能的微处理器、摄像头模组以及用于图像处理和机器学习算法的硬件加速器。在文章中,作者通过OpenMV实现了从数字图像采集到模型推理,最终控制直流电机转速的过程,展现了其在嵌入式设备上进行实时目标检测和识别的强大功能。
TensorFlow LiteTensorFlow Lite是Google推出的轻量级机器学习框架,它是TensorFlow针对移动和嵌入式设备优化的版本。在本项目中,作者将训练好的模型转换为TensorFlow Lite格式,以便在资源有限的OpenMV平台上高效地部署和运行神经网络模型,实现对手写数字的实时识别。
混淆矩阵混淆矩阵是一种用于评估分类模型性能的统计表,它展示了模型预测结果与实际标签之间的对应关系。在文中,作者通过查看模型训练后的混淆矩阵分析了各个数字类别被正确识别和错误识别的情况,从而找出模型存在的不足并针对性地提出优化建议。
延伸阅读
作为当前文章的延伸阅读,仅对当前文章有效。
随着人工智能和机器学习技术的快速发展,基于OpenMV等微型机器视觉平台实现的手写数字识别应用已不再局限于理论研究,而是越来越多地融入到日常生活中。近日,一款结合了OpenMV与深度学习框架的智能门禁系统成功落地,该系统能够实时识别并验证用户手写的门牌号,大大提升了社区的安全性和便利性,充分展示了MNIST数据集训练模型在实际场景中的高效应用。
此外,针对跨国文化背景下的数字识别差异问题,有研究团队正着手构建包含多元书写风格的全球手写数字数据库,以期通过更全面的数据训练,提升各类设备对手写数字识别的普适性和准确性。同时,也有科研人员积极探索新的图像预处理技术和网络优化算法,如超分辨率技术、注意力机制等,进一步提高识别系统的鲁棒性和精度。
值得注意的是,云端训练与边缘计算的结合正在为OpenMV等嵌入式设备提供强大的后盾支持。例如,阿里云IoT部门最近推出的云端-边缘协同训练方案,允许用户在云端完成大规模数据训练后,将轻量化模型部署至OpenMV等终端设备上,既保证了模型性能,又降低了设备存储和计算压力,对于推动智能硬件在数字识别领域的广泛应用具有深远意义。
总之,在当今AI技术蓬勃发展的大背景下,OpenMV作为微型计算机视觉平台的角色愈发重要,其在手写数字识别项目中的实践不仅体现了技术的先进性,也昭示着未来物联网设备智能化的发展趋势。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
nc host port - 连接到远程主机的指定端口发送或接收数据。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
基于Redis的分布式锁互斥性与可靠性实现及命名空间与原子性保障 04-22 可自定义刻度动画的jQuery进度条插件 02-07 jQuery和css3网站操作提示向导插件 12-28 jQuery创意响应式两栏滚动幻灯片特效 11-30 带视频播放的全屏轮播图布局特效 09-07 黑色炫酷个人摄影师网站通用模板下载 01-20 Cassandra中哈希分区与范围分区策略:数据分布、Murmur3Partitioner与负载均衡实践 11-17 [转载]java培训后好找工作吗 11-13 响应式环保包装盒设计公司网站静态模板 11-04 本次刷新还10个文章未展示,点击 更多查看。
中文建筑工程公司静态html网站模板下载 07-03 红色大气高端特色餐厅加盟网站模板 06-21 Vue.js 中的数据绑定与取消绑定:事件监听器、$destroy() 方法及 v-model 指令的运用与虚拟DOM、组件销毁的关系解析 06-20 响应式游戏应用商店单页网站html模板 06-15 自考大学通用模板下载 06-13 jqtimeline.js-简单又好用的jquery时间轴插件 06-04 [转载]Java Work 05-26 红色简洁电影售票平台网站html模板 05-02 投资集团项目展示页面网站HTML5模板 03-22 soulmate粉色干净浪漫唯美婚礼单页响应式网站模板 03-07 页面滚动时动态为元素添加class的jQuery插件 03-05
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"