在学习物体识别前,我们先来认识下图像识别。
图像识别,简单地来说,就是一个将图像与特定的词语对应起来的过程。从技术上来看,是利用电脑对图像进行处理、分析和理解,以识别各种不同模式的目标和对象的过程。图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。
文字识别的研究是从 1950年开始的,一般是识别字母、数字和符号,从印刷文字识别到手写文字识别,应用非常广泛。
数字图像处理和识别的研究开始于1965年。数字图像与模拟图像相比具有存储、传输方便可压缩、传输过程中不易失真、处理方便等巨大优势,这些都为图像识别技术的发展提供了强大的动力。
物体识别主要指对三维世界的物体及环境的感知和认识,属于高级的计算机视觉范畴。它是以数字图像处理与识别为基础的结合人工智能、系统学等学科的研究方向,其研究成果被广泛应用在各种工业及机器人中。
了解了这些知识,我们再来看下面这四幅图,第一张图片是手写数字,可以看到电脑将它正确地识别为了425,后三张图片则分别分类为猫、人和车。
这就是文字识别和物体识别的一些应用,电脑可通过深度学习算法,对输入的图像进行识别,并给出每幅图片的识别结果。
在人工智能领域,识别问题又可以归类为分类问题,所以物体识别,也可以称之为物体分类。
我们前面提到了,图像识别就是电脑获取,处理和分析图像数据的过程,这个过程其实也就是计算机视觉的实现过程。简而言之,计算机视觉使得电脑能够“看”事物——甚至包括人类无法看到的事物。然而,要想让电脑做到人类无法做到的事情,我们必须首先使电脑能够做到人类可以做的事情:看到并标记物体和生物。这是图像识别的主要功能。
我们先来看下下面这四幅猫的图片,我们可以很轻松地分辨出这四张图片都是猫,即使它们外形长相完全不同,且体态各异,即使它只露出了一截尾巴,但我们仍然可以分辨的出来。
但这对电脑来说却十分困难,因为电脑并没有像我们人类大脑这样复杂的系统。
那么,到底电脑是如何识别图片的呢?我们来看下一节内容。
电脑想要正确分类图片,就需要像我们人类一样去学习,知道图片中大量的资讯。目前,最有可能让电脑实现“看”的能力的技术叫做深度学习(Deep Learning,简称DL),它是一种让电脑从图片中学习的方法。学习的过程称为训练,识别的过程称为推理(测试)。
电脑要识别图片,前提便是需要大量的图片数据作为输入,传入电脑以供其学习。
我们以识别猫为例,前期需要先准备大量的各种品类的猫,并且打上标签,告诉电脑:这些是猫,也就是这些图片的分类,然后电脑将这些数据输入网路,执行训练,通过不断地迭代进行学习,达到正确认识这些猫的目的。
然后,我们输入电脑一张新的猫的图片,进行测试,电脑执行测试演算法,便可给出输入图片的正确分类。
这个过程就是电脑“看”事物(学习),并给出答案(识别)的过程。
深度学习就是一种机器学习框架,通过模仿人类的神经元系统,为电脑提供自主学习能力。因此,电脑可以自动识别与发掘图像数据的特征,准确识别图片中的内容,而无需根据指令或手动编码来实现(但它需要大量的数据),并大大提高了计算精度及识别准确率。
而模仿人类神经元系统的方法,在人工智能领域被称为神经网路(Neural Networks)。
下面,我们以图像识别的入门级应用:MNIST手写数字识别为例,来认识神经网路与深度学习的原理。其中,MNIST是一个手写数字的图片数据集。
手写识别是常见的图像识别任务。电脑通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风格迥异,大小不一, 造成了电脑对手写识别任务的一些困难。
在研究过程中,数字手写体识别由于其有限的类别(0~9共10个数字)成为了相对简单的手写识别任务。所以,我们从简单的手写数字识别入手,来认识实现图像识别的演算法。
前面已经提到,电脑需要像人一样思考学习,才能识别出图像,我们不妨反推一下,想一想我们小时候是怎样学习数字的,大家总结回想一下,我们学习数字的思维过程。为什么我们可以看到各式各样形状的数字,依旧可以知道它们分别是多少呢?
这个过程也就是电脑要模仿的,我们把这个学习步骤写出来。
这个就是人类学习和认知的过程,也就是机器要模仿的,现在我们将人的学习方式类比到电脑中,就会知道电脑学习并识别数字的过程了。
我们向电脑输入正确的带有标签的图像数据,电脑看到的并不是像我们人类看到的那样,如下图左边的图片,而是下图右边数字矩阵的样子。电脑中处理图像,处理的是图像中每一个像素(像素是电脑萤幕上所能显示的最小单位,是用来表示图像的单位)。
上一节我们提到了,深度学习需要大量的数据作为输入,在手写数字识别系统中,数据来自于MNIST数据集,它包含60000个训练集和10000测试数据集。分为图片和标签,图片是28*28的像素矩阵,标签为0~9共10个数字。
有了数据集,下一步,便是将数据输入到深度学习网路中,也就是神经网路中(这里采用的是LeNet-5卷积神经网路模型,卷积神经网路是深度学习神经网路中最常见的一种),进行自动的特征提取及学习,这个过程就是前面提到过的训练过程。
我们知道,人类大脑的神经网路是由神经元和突触组成,它们协同工作,完成对外界资讯的处理与传递。
那么,人脑的神经网路对比到深度学习中,就是如下图所示的网路。
大量的手写数字图像就是输入数据,作为第一层:输入层(一般情况下,输入层不在网路结构中体现,而在后面训练开始时给出),因为每张图像的像素是28x28,所以每张图像一共有784个像素,电脑中的索引一般从0开始,所以输入x即为x0-x783。
中间部分称为隐藏层,在LeNet-5网路中,主要采用的是:卷积层Convolutional Layer(启动层为ReLu Layer)、池化层Pooling Layer以及全连接层Fully Connected Layer。
全连接层中加入启动函数:Softmax,这是一个回归模型,用于分类过程,可解决多分类问题。这里的手写数字识别就是一个多分类问题,0-9共10类,所以最后的输出层y的结果为y0-y9。
并且Softmax也是一个概率函数,它可以给出输入图像识别为不同类别的概率,以此来让使用者判断输入图像中的数字更像哪一个识别结果。
这部分就是神经网路的网路结构,是深度学习演算法实现图像处理及学习的根本。
前面我们给出了人类学习和认识数字的过程,也就是下图左边的部分,通过上一节的学习,我们知道了电脑学习并认识数字的过程,那么总结起来,就是下图右边所示的步骤。
我们知道了手写数字识别的原理,那么,现在就来看看实际电脑中是如何实现图像识别的吧。
打开网址:https://ai-blockly.cocorobo.hk/ ,进入AI blockly页面。
进入后,首先选择Examples选项。
然后,继续选择Tensor Flow选项,然后选择Digit Recognition选项,并选择OK。
然后,就会出现如下图所示的积木程式块。
继续点击右下角区域中的RUN按钮,即可开始训练。
训练的迭代过程中,会产生如下图所示的函数曲线图及网路结构资讯(Model Architecture),可通过观察曲线图的变化,来判断训练执行的状态及模型的训练效果。
如上图所示,是演示的最终效果,左边是曲线图,第一副图是训练集(loss)和验证集(val_loss)的loss变化曲线,loss是损失函数,即模型预测出的结果与标签标注的真实值的差值。这个差值是随著训练轮数Epoch的增加而逐渐减小的。
第二幅图是训练集(acc)和验证集(val_acc)的准确率变化曲线,准确率为识别正确的图像个数除以总的图像数的比值,该值随著Epoch的增加而逐渐增大。
右侧为推理测试区,在画布中写出你要测试的数字,点击Detect,即可得到最终的识别结果。
其结果将打印显示在右上方区域的Console中。
手写数字识别的整个实现过程到这里就结束了。
接下来,我们来学习今天最重要的部分——物体识别。
物体识别(Object Recognition)是计算机视觉中的一个应用,目的是让电脑去分析一张图片或者一段影片中的物体,并标注出其中物体所属的类别。
YOLO是目前应用非常广泛的一种物体识别演算法。YOLO的意思是You only look once,也就是你只看一眼,就能认出这是什么物体,体现YOLO演算法识别的精度和速度。
YOLO是基于Pascal VOC2012数据集的目标检测系统。它能够检测到20种Pascal的目标类别,包括:
在学习了解了深度学习与物体识别的原理之后,我们开始积木程式块的学习,将理论与实践相结合,才能更好地学习并认识物体识别。
<tr>
<td width="50%">积木</td>
<td width="20%">指令</td>
<td width="30%">说明</td>
</tr>
<td width="50%"><img src="./media/ai/AI_r1.png" width="300"/></td>
<td width="20%">载入模型</td>
<td width="30%">载入人工智能模型,可以从选单中选择常用识别模型<img src="./media/ai/AI_r2.png" width="300"/></td>
<td width="50%"><img src="./media/ai/AI_r3.png" width="300"/></td>
<td width="20%">获取识别结果</td>
<td width="30%">获取当前结果,可选择数字识别的结果或者识别为某个数字的置信度<img src="./media/ai/AI_r4.png" width="300"/></td>
<td width="50%"><img src="./media/ai/AI_r5.png" width="300"/></td>
<td width="20%">物体识别</td>
<td width="30%">获取物体识别真假值,如果识别到物体会返回「真」值,否则返回「假」值</td>
<td width="50%"><img src="./media/ai/AI_r6.png" width="300"/></td>
<td width="20%">物体识别结果的参数</td>
<td width="30%">获取识别到的每个物体的各项参数,包括:<img src="./media/ai/AI_r7.png" width="300"/></td>
<td width="50%"><img src="./media/ai/AI_r8.png" width="300"/></td>
<td width="20%">人脸识别</td>
<td width="30%">获取人脸识别真假值,如果识别到人脸会返回「真」值,否则返回「假」值</td>
<td width="50%"><img src="./media/ai/AI_r9.png" width="300"/></td>
<td width="20%">人脸识别结果的参数</td>
<td width="30%">获取识别到的每个人脸的各项参数,包括:<img src="./media/ai/AI_r10.png" width="300"/></td>
<td width="50%"><img src="./media/ai/AI_r11.png" width="300"/></td>
<td width="20%">加载客制化模型</td>
<td width="30%">从指定路径加载用户预训练好的客制化模型:/sd/user/mymodel.kmodel
并根据要识别的物体种类来设定客制化物体的类别名称:Object Name
<td width="50%"><img src="./media/ai/AI_r12.png" width="300"/></td>
<td width="20%">客制化的物体识别</td>
<td width="30%">获取客制化物体识别真假值,如果识别到客制化物体会返回「真」值,否则返回「假」值</td>
<td width="50%"><img src="./media/ai/AI_r13.png" width="300"/></td>
<td width="20%">客制化物体识别结果的参数</td>
<td width="30%">获取识别到的每个客制化物体的各项参数,包括:<img src="./media/ai/AI_r14.png" width="300"/></td>
在积木指令区点按以下指令,并依次放在积木编程区: 1. AI模组|图像处理:【相机初始化】 2. 循环:【一直重复执行】 3. AI模组|AI模型:【加载预设模型】 选择:模型:「常见物体检测模型」 图像:「img_objectrecognition」 4. 变数:【设定变数】img_objectrecognition 5. AI模组|相机:【获取相机捕捉的图像】 6. 逻辑:【逻辑判断】 7. AI模组|模型:【识别到了任意常见物体】 8. 序列埠通讯|打印:【打印文字】 识别到物体则显示「Object Detected」,否则「Nothing Detected」 |
|
注意:步骤4必须使用内建变数「img_objectrecognition」,所以首先要在步骤3使用「加载预设模型」指令,然后才进行步骤4及步骤5。 | |
测试结果:在「代码区」点按「串口互动窗」,将模组向四周扫描,并观察显示的结果如下,当检测到有物体时会显示「Object Found」,否则会显示「Nothing」 |
重复活动一的程式,在步骤8「显示文字」指令修改如下: 1. 循环:【For循环】 2. AI模组|模型:【识别到了任意常见物体】 3. 序列埠通讯:【打印】 4. AI模组|模型:【获取物体参数】选择「物体名称」 |
|
测试结果:点按「串口互动窗」,将模组向四周扫描,并观察显示的结果如下,当检测到有物体时会显示「物体名称」,否则会显示「Nothing」 |
在积木指令区点按以下指令,并依次放在积木编程区: 1. AI模组|萤幕:【初始化】 2. AI模组|相机:【初始化】 3. 循环:【重复执行】 |
在【重复执行】积木指令内,放置下列积木指令: 4. AI模组|AI模型:【加载模型】 (模型:常见物体识别模型 图像:img_objectrecognition) 5. 变数:【赋值】(名称:img_objectrecognition) 6. AI模组|相机:【获取影像】 7. 变数:【建立变数】(名称:img_display) 8. AI模组|图像处理:【调整画布尺寸】 9. AI模组|图像处理:【图像转换】 |
|
在【图像转换】积木指令之后,放置下列积木指令: 10. 逻辑:【逻辑判断】 11. AI模组|AI模型:【物体识别】 12. 循环:【For循环】 13. AI模组|AI模型:【物体识别】 14. AI模组|图像处理:【萤幕文字】,并修改座标的X值及Y值,使「物体名称」显示在萤幕左上角的适宜位置 15. 文字:【建立字串使用】 16. AI模组|模型:【获取物体参数】选择「物体名称」 17. AI模组|图像处理:【萤幕文字】并输入「Nothing Detected.」,并修改座标的X值及Y值 |
|
在步骤10【逻辑判断】积木指令之后,放置下列积木指令: 18. AI模组|萤幕:【设定起始点坐标】、【显示画布】(名称:img_display 起始座标X:8 Y值:36) |
|
将上面专题中的第三步改为以下内容:在萤幕中显示识别到的物体位置并以检测框的形式标注出来。
在【图像转换】积木指令之后,放置下列积木指令: |
在步骤10【逻辑判断】积木指令之后,放置下列积木指令: 19. AI模组|萤幕:【显示画布】(名称:img_display 起始座标X:8 Y值:36) |
完整Python代码: |
完整程式: |
运行结果: |