基于MAX78000FTHR的螺栓、螺母和螺钉识别系统
本项目是一个AI自动识别项目,AI模型使用到的神经网络模型为卷积神经网络(CNN)。本项目将在Linux环境下对螺钉、螺母和螺栓进行模型训练。最终将使用MAX78000FTHR开发板的板载摄像头并搭配另外的TFT屏幕进行识别。
标签
嵌入式系统
AI
MAX78000
Pulsar2
更新2023-01-31
1987

一、项目简介

      本项目是一个AI自动识别项目,AI模型使用到的神经网络模型为卷积神经网络(CNN)。本项目将在Linux环境下使用python、pytorch等工具对螺钉、螺母和螺栓进行模型训练,然后使用官方提供的SDK生成与模型相应的C代码,这部分C代码将会在我们的项目代码中直接引用。本项目的最终应用平台为MAX78000FTHR开发板,我们将使用该开发板的板载摄像头并搭配另外的TFT屏幕对螺钉、螺母和螺栓进行识别。

二、项目设计思路

1、观测对象

      本项目的检测对象为螺钉、螺母和螺栓,输入为含有螺钉、螺母和螺栓这三个对象的图像的RGB数据,经过AI模型后输出结果。在深入学习AI训练之前我的设想是输出包括位置信息的识别的结果的,就是说不仅要识别出图像中有什么东西,还要识别出这个东西在哪里。但在深入了解之后发现要输出位置信息的话还需要使用到目标检测技术,最终我还是选择的更适合新手的单目标识别,待学成归来再挑战更高难度的目标识别+目标检测。

2、整体框架

TE6y6LjZ7fgmCFpcjdGmlnlwX91mNrnjJpNWSvzdq94+s9MmkT83ubjTu68W+Ixe1i0jCrSs37mD47iMN8YiIaGxjYERERERERERERE4YGBERERERERERkRMGRkRERERERERE5ISBEREREREREREROWFgREREREREREREThgYERERERERERGREwZGRERERERERETkhIERERERERERERE5YWBEREREREREREROGBgREREREREREZETBkZERERERERERPQa4B9wEK7d+tEEdAAAAABJRU5ErkJggg==

图1 整体框架图

      系统逻辑整体框图如上图图1所示,包含了正向传播和反向传播过程。其中隐含层包含了成千上万的参数,在深入学习AI之前隐含层在我眼里就是一个黑盒,完全不了解其工作方式,随着一点一点的学习才逐渐揭开其神秘面纱。

      正常应用时很好理解,就是已知输入层数值和隐含层数值,经过计算最终得出结果。而隐含层数值是需要经过训练才能得到的,而且每次训练得到数值还不一定相同。

      训练过程其实是已知输入层数值和输出结果求隐含层的数值。在训练时会给隐含层的所有参数一个随机的初始值,在已知输入值的情况下可以算出一个输出,再把这个输出与已知的输出比较,这个时候我们可以得到一个偏差。这个时候我们需要将这个偏差反向传播到隐含层来修改隐含层参数,这样就完成了一次训练,也叫学习。由于我们使用的是卷积神经网络,正向传播时还比较好计算,而反向传播时需要对每个参数求偏导,这个还是比较麻烦的。这个时候使用pytorch的好处就体现出来了,pytorch会自动完成求导,也就是说我们只用写好正向传播过程即可,反向传播可以交给pytorch。

3、CNN模型框图

3rUX9mYNQ9wAAAABJRU5ErkJggg==

图2 CNN模型

      我的CNN模型如上图图2所示,其中黄色框为输入层(高宽深为96x96x3的矩阵);蓝色框为隐含层的具体结构,共7层其中前6层为卷积层,第7层为全连接层;绿色框为中间的输出结果;红色框为最终输出结果。

      图2中所有卷积层前的输入都会补一圈0,也即pading=1,只会在高和宽上补一圈0,深度不变,同时卷积核的步长为1,这样是为了在经过卷积后的输出保持数据尺寸(高宽)不变,输出深度与卷积核的数量相同。从图2中可以看出在第2层到第5层卷积层的后面都会跟一个最大池化,这样做的目的是为了降低数据尺寸,也叫降采样。同时从图2 也可以看出所有卷积层使用的激活函数都是ReLU,ReLU是使用相对更广泛的激活函数,其他激活函数有Sigmoid、Tanh、Leaky ReLU等,各有优劣,本项目使用的是ReLU函数。全连接层使用的是pytorch提供的linear函数,使用时只需给linear函数提供输入尺寸和输出数量即可,用起来比较方便。

三、素材搜集过程

1、原始素材录制

      刚开始是准备在网络上搜集相关训练素材的,经过搜索发现公开的数据很少,几乎没有。因此我打算自己录制素材,然后在电脑上对录制好的图像进行分割与标注,以完成素材搜集。

      最初的方案我是使用板载的摄像头搭配额外的屏幕以及一张SD卡做一个照相机,然后搭建一个简易的录制环境录制好原始素材保存到SD卡中。最后在电脑上编写一个标注软件对录制好的图像进行剪切与标注。录制环境与照相机拍摄效果如下图图3与图4所示。

2Q==                 9k=

图3 录制环境                                               图4 照相机拍摄效果

      但在后续测试时发现这样的素材训练出来的效果太差了,主要是使用这个照相机拍摄的图片像素本来就低,导致标注后每个素材的像素小的只有30*30左右,大的也就90*90左右,而且还是长的长、宽的宽,经过pytorch的resize之后就直接变形了,这样的素材训练后实际测试发现完全没法识别,基本就没有正确的。

      最终我用了另一套方案,直接使用手机拍照,再将手机拍摄的素材导入电脑进行标注。手机拍好的原始素材如下图图5所示,由于最初没考虑那么多每种对象只买了一个规格,最终只拍了60张,现在想来应该每种对象多买些规格的。

AU+vnRWahMKfAAAAAElFTkSuQmCC

图5 手机拍摄的原始素材

2、图像标注

      我是在电脑上用Qt编写了一个标注软件,点击一次鼠标左键开始框选,再点一次鼠标左键结束框选,中途可以点击鼠标右键取消框选。目前标注时会将每个框内的图像按顺序保存起来,每框一次就保存一次。同时在标注后,保存图片前多加了一个resize(96)的步骤,这样就不用在pytorch里进行resize了。

      未来可以升级一下,将每个框的坐标、大小和标签都保存在文本文件内,这样就可以做目标识别了。使用效果如下图图6所示。

BwAAAABJRU5ErkJggg==

图6 标注工具使用效果

3、生成数据集

      标注完成后就可以得到三个文件夹的图像数据,现在只需要从这些图片中抽取一部分出来做测试集,剩下的就是训练集。再学习pytorch与官方训练代码的时候得先学python,学习了一些python的皮毛后就可以用python写个程序来生成测试集了,我是在标注完的output文件夹下写了个test.py来从标注数据中随机抽取一部分图片来充当测试集的。最初还是手动选择的,学了python之后就方便多了。

四、AI模型训练

1、数据集处理

      由于我们的项目比较基础,数据集的处理还是比较简单的,只需要使用pytorch提供的torchvision.datasets.ImageFolder()方法就可以很方便的把数据集转换成tensoor数据,使用方法可以参考官方demo中的cats_vs_dogs。

2、CNN网络模型

      这一步网络模型的编写其实是最难的,所幸有官方demo可以参考,不然真的无从下手。考虑到MAX78000的RAM大小,我将图片的尺寸设定为96*96,这样一张图可以完整的保存在RAM中,从而不用使用摄像头DMA的steam模式(这是因为我打算将图片保存下来,所以中间有一些比较耗时的操作,导致我在使用steam模式时发现经常堵塞,)。

3、训练、评估、量化

      完成了最难的前两步后剩下的就比较简单了,需要编写训练、评估、量化的bash脚本,这样就不用每次训练都要输出一长串的命令和参数了。这一步参考官方demo和readme文件可以很轻松的写出来,官方readme文档里也有详细的说明每个参数的作用和示例。写完这些就可以按部就班的开始训练、评估、量化,最后生成C代码了,这套流程中最耗时的就是训练,不过由于我自己的数据集比较小,训起来还是很快的。这些训练相关的代码我都打包放在附件里了,只有我自己写的部分,SDK就不复制出来了,太大了。

五、成果展示

      目前为止训练效果最好的成果分别如下图7~图9所示。

FnN5sYQf7ieIEtgXMyYle-PtAZu5

图7 螺钉识别效果(72.7%)

FgItjVpVZFyM8KoqiW9-kZeXxUso

图8 螺母识别效果(100%)

FgxhOTts5WKVT5fcnQdQd9fgn82l

图9 螺栓识别效果(99.9%)

      从结果上可以看出来螺钉的识别效果是比较差的,我自己测试的时候也发现螺栓和螺母基本上每次都能识别对,但螺钉识别错的次数就比较多,不知道是我训练的素材的问题还是训练时的设置参数问题。AI训练的魔幻之处就在于每次修改参数不一定能让系统更准确,所以每次训练完生成的代码最好是保存起来,我刚开始都是直接替换的,吃了几次亏就不敢了。

六、结语

      经过了将近三个月的磕磕绊绊总算是完结了这个项目,虽然项目比较基础,但实际要学的东西还是很多的。比如CNN,之前经常能听说这个词,但这个词具体是什么意思却不知道。项目的前半段时间主要是在学习MAX78000的使用和AI训练环境搭建,MAX78000学的烦了就去搭建Linux环境,搭建linux环境的时候老是报错快气死就去折腾MAX78000,两个混搭着来。后边的时间主要就是在查资料和学Python了,查资料真的是一件很痛苦的事,网络上存在太多无脑搬运和似四而非的东西了,而像论文这种其实更多的是看思路,底层原理论文里边也不会详细解释。学python其实感觉还是比较舒服的(我是用的齐伟编写的开源免费的《Python 完全⾃学教程》来学习的),现在学了一些python的基础应用后就可以在我们的工作和生活中用起来,比如文件批量改名之类的。我从数据集里边随机抽取部分图片做测试集就是用python完成的,像这种能把学习的东西应用起来的成就感还是很令人满足的。

      最初其实是准备用FreeRTOS完成项目的,因为MAX78000只有一个SPI接口,而我们有SD卡、屏幕和触摸屏三个SPI设备,所以准备使用三个片选(CS)配合RTOS的信号量来完美实现三个设备的驱动。但后来发现SD卡在SPI模式下片选信号其实是要参与到通信时序中去的,这样会导致信号量一直阻塞,去掉信号量的话经常会不识别卡,最后还是用裸机完成的项目,系统也没做太复杂。

      完成本项目最大的阻碍其实是AI这块,让我一个搞单片机的去弄AI这个跨界程度我感觉还是有点大的,主要是还没有理论基础,这就导致我看官方demo代码都经常看不明白。我感觉啊,专业的事还是得交给专业的人来做,或者官方直接出个软件,我把数据往里一丢,点一下按键他就自动给我训练,然后自动生成C代码,这样难度就会降低很多。

      最初预期的效果其实有目标检测的功能的,就是不仅能识别出这个东西是什么,还能识别出这个东西在图像的那个位置。后来查资料就发现这个是把一张图片预先框很多区域,然后对这些区域进行识别。考虑到自身的能力和时间限制就退而求其次,做个基础点的,一张图片就一个识别对象,直接对这张图进行识别,就不要位置信息了,位置信息可以作为未来的一个升级方向。

      完成这个项目后我感觉最大的收获是学会python的部分基础应用,AI这块我感觉除了在MAX78000这个系列的平台上,随便换个平台我估计就两眼一抹黑了,也许就剩一点理论知识了。

      MAX78000的照相机代码和最终识别代码、pytorch相关代码、标注软件源码和可执行文件、图片素材、硬件原理图和PCB以及本项目报告的Word版本已经全部上传至Gitee(https://gitee.com/xwl_fighter/max78000)。

软硬件
电路图
附件下载
MAX78000程序.rar
MAX78000程序,bns文件夹为最终识别代码,IMGTAKE为照相机程序
pytorch相关代码.rar
训练相关代码
ImageCut.rar
PC端Qt标注软件源码
团队介绍
个人团队
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号