绪论
平时在食堂买饭时,有的师傅会不经意算错钱,而且新的二维码结算设备需要无线网络,操作复杂,付款要等待一段时间,显示不清楚,身边有的同学被收错过钱,然后要费好长的时间才能要回来。如果能实现这个菜价识别系统,就能自动计算菜价,自动收钱,省去人工操作。使学校食堂收费更规范化、系统化。对提高食堂服务效率和工作人员服务质量有重要意义。除了食堂使用,这套系统还可以用在一些半自助餐厅或者无人餐厅。
本次论文主要讲的是食堂菜价识别系统基本原理和开发过程,阐述了神经网络训练、系统设计和系统实施的全过程。采用Python作为开发语言,Ubuntu作为后台系统。重点介绍了识别系统中的实现过程:包括收集训练集、 模型训练、接口设计、系统物理配置方案、系统实现、系统测试以及系统功能简介。
本论文主要又绪论、需求分析、总体设计、目标检测的构建、其他程序设计、系统测试6部分组成,主要研究了Tensorflow Object Detection API的使用和深度学习在日常应用上的尝试。
第二章 需求分析
二.1. 功能需求分析
菜价识别系统的总目标是在一个平台(暂时是微信公众平台)可以通过拍照获得菜价信息,利用校内现有的计算机软件和硬件的资源并借助阿里云,尝试开发能基本实现菜价识别并显示的系统,可以后台修改菜价、菜名。当有新菜加入时,可以通过迁移学习快速更新模型。
二.2. 可行性分析
2012年以后,得益于数据量的上涨、运算力的提升和机器学习新算法(深度学习)的出现,人工智能开始大爆发。据领英近日发布的《全球AI领域人才报告》显示,截至2017年一季度,基于领英平台的全球AI(人工智能)领域技术人才数量超过190万,仅国内人工智能人才缺口达到500多万。人工智能的研究领域也在不断扩大,包括专家系统、机器学习、进化计算、模糊逻辑、计算机视觉、自然语言处理、推荐系统等。
TensorFlow的对象检测API是一个非常强大的工具,可以快速启用任何人(特别是没有像我一样没有真正的机器学习背景的人)来构建和部署功能强大的图像识别软件。
因此我们可以简单地利用深度学习技术构建一套计算机视觉软件,并将更大的经历用在应用的实现上。
第三章 总体设计
三.1. 系统开发工具介绍
三.1.1. Python
是一种解释,高层次,通用编程语言。由Guido van Rossum创建并于1991年首次发布,Python的设计理念强调代码可读性,特别是使用重要的空白。它提供的结构可以实现小规模和大规模的清晰编程。Van Rossum领导语言社区直到2018年7月辞去领导职务。
Python具有动态类型系统和自动内存管理功能。它支持多种编程范例,包括面向对象,命令式,功能性和程序性。它还有一个全面的标准库。
Python解释器可用于许多操作系统。CPython是Python 的参考实现,是开源软件,并且具有基于社区的开发模型,几乎所有Python的其他实现都是如此。Python和CPython由非营利性Python软件基金会管理。
三.1.2. Tensorflow
TensorFlow是一个使用数据流图进行数值计算的开源软件库。图形节点表示数学运算,而图形边缘表示在它们之间流动的多维数据阵列(张量)。这种灵活的体系结构使您可以将计算部署到桌面,服务器或移动设备中的一个或多个CPU或GPU,而无需重写代码。TensorFlow还包括 TensorBoard,一种数据可视化工具包。
TensorFlow最初是由研究人员和工程师在Google机器智能研究组织的Google Brain团队开发的,目的是进行机器学习和深度神经网络研究。该系统通用性足以适用于各种其他领域。
三.2. 主要Python库介绍
三.2.1. Threading
在计算机科学中,执行线程是可由调度器独立管理的最小程序指令序列,调度器通常是操作系统的一部分。线程和进程的实现在操作系统之间有所不同,但在大多数情况下,线程是进程的一个组件。多个线程可以存在于一个进程中,并发执行和共享资源(如内存),而不同进程不共享这些资源。特别是,进程的线程共享其可执行代码及其值在任何给定时间动态分配变量和非线程局部 全局变量。
该模块在较低级别_thread模块之上构建更高级别的线程接口。
三.2.2. Re-正则表达式操作
此模块提供与Perl中类似的正则表达式匹配操作。
要搜索的模式和字符串都可以是Unicode字符串(str)以及8位字符串(bytes)。但是,不能混合Unicode字符串和8位字符串:也就是说,不能将Unicode字符串与字节模式匹配,反之亦然; 类似地,当要求替换时,替换字符串必须与模式和搜索字符串具有相同的类型。
正则表达式使用反斜杠字符(’')来表示特殊形式或允许使用特殊字符而不调用它们的特殊含义。这与Python在字符串文字中用于相同目的的相同字符的使用相冲突; 例如,要匹配文字反斜杠,可能必须写’\\‘为模式字符串,因为正则表达式必须是\,并且每个反斜杠必须表示为\常规Python字符串文字。
三.2.3. os-其他操作系统接口
该模块提供了一种使用操作系统相关功能的便携方式。
这里主要用到了os.system()。用来在子shell中执行命令(字符串)。这是通过调用标准C函数实现的system(),并具有相同的限制。
三.2.4. matplotlib
Matplotlib是Python编程语言的绘图库及其数学扩展NumPy。它提供了一个面向对象的 API,用于使用通用GUI工具包(如Tkinter,wxPython,Qt或GTK +)将图表嵌入到应用程序中。还有一个基于状态机(如OpenGL)的程序 “pylab”接口,设计与MATLAB非常相似,但不鼓励使用它。[3] SciPy 利用Matplotlib。
三.2.5. urllib-URL处理模块
urllib 是一个包,它收集了几个用于处理URL的模块。
这里主要用到了urllib.request.urlretrieve(url,filename = None,reporthook = None,data = None ),将URL表示的网络对象复制到本地文件。
三.2.6. Cython
是用C语言实现Pyhon,是目前应用最广泛的解释器。最新的语言特性都是在这个上面先实现,基本包含了所有第三方库支持,但是CPython有几个缺陷,一是全局锁使Python在多线程效能上表现不佳,二是CPython无法支持JIT(即时编译),导致其执行速度不及Java和Javascipt等语言。于是出现了Pypy。
三.2.7. Pillow
PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。
由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性。
该库提供广泛的文件格式支持,高效的内部表示和相当强大的图像处理功能。
核心图像库旨在快速访问以几种基本像素格式存储的数据。它应该为一般的图像处理工具提供坚实的基础。
三.3. 系统模块设计
三.3.1. 模块划分
系统模块包括数据收集,模型训练,分析计算和后端接口四大模块。
数据收集用来在微信公众平台收集训练集
模型训练用来训练模型
分析计算用来识别菜品
后端接口用来连接用户与分析计算模块
功能模块图如图3-1。
图3-1 系统模块图
三.4. 神经网络简述
在深度学习中,卷积神经网络(CNN或ConvNet)是一类深度神经网络,最常用于分析视觉图像。
CNN使用多层感知器的变体设计,需要最少的预处理。它们也被称为移位不变或空间不变人工神经网络(SIANN),基于它们的共享权重架构和平移不变性特征。
卷积网络被启发由生物工艺在之间的连接图案的神经元类似于动物的组织视觉皮层。个体皮质神经元仅在被称为感受野的视野的受限区域中对刺激作出反应。不同神经元的感受野部分重叠,使得它们覆盖整个视野。
与其他图像分类算法相比,CNN使用相对较少的预处理。这意味着网络学习传统算法中手工设计的过滤器。这种独立于特征设计中的先前知识和人力的努力是一个主要优点。
图3-2典型卷积神经网络
三.4.1. 设计
卷积神经网络由输入和输出层以及多个隐藏层组成。CNN的隐藏层通常由卷积层,RELU层即激活功能,池化层,完全连接层和归一化层组成。
作为神经网络中的卷积的过程的描述是按照惯例。数学上它是互相关而不是卷积(尽管互相关是一个相关的操作)。这仅对矩阵中的指数具有重要性,因此权重放在哪个指数处。
三.4.2. 卷积
卷积层将卷积运算应用于输入,将结果传递给下一层。卷积模拟个体神经元对视觉刺激的反应。
卷积是从输入图像中提取特征的第一层。卷积通过使用小方块输入数据学习图像特征来保持像素之间的关系。这是一个数学运算,需要两个输入,如图像矩阵和滤波器或内核
图3-3卷积层示意图
每个卷积神经元仅处理其感受野的数据。尽管可以使用完全连接的前馈神经网络来学习特征以及对数据进行分类,但是将该架构应用于图像是不实际的。由于与图像相关联的非常大的输入尺寸,每个像素是相关变量,因此即使在浅(深的相反)结构中也需要非常多的神经元。例如,尺寸为100×100的(小)图像的完全连接层对于第二层中的每个神经元具有10000个权重。卷积操作为这个问题带来了解决方案,因为它减少了自由参数的数量,允许网络更深,参数更少。例如,无论图像大小如何,大小为5 x 5的平铺区域(每个都具有相同的共享权重)仅需要25个可学习的参数。通过这种方式,它通过使用反向传播来解决在训练具有多个层的传统多层神经网络中消失或爆炸的梯度问题。
三.4.3. 池化
池化层部分将减少图像太大时的参数数量。空间池也称为子采样或下采样,它降低了每个地图的维度,但保留了重要信息。
图3-4池化层示意图
卷积网络可以包括本地或全局池化层。通过将一层神经元簇的输出组合成下一层中的单个神经元,池化层减少了数据的维度。本地池结合了小簇,通常为2 x 2.全局池对卷积层的所有神经元起作用。此外,池化可以计算最大值或平均值。Max池使用来自先前层的每个神经元簇的最大值。平均池使用从每个神经元簇中的现有层的平均值。
三.4.4. 全连接
全连接层将一层中的每个神经元连接到另一层中的每个神经元。它原则上与传统的多层感知器神经网络(MLP)相同。扁平矩阵穿过完全连接的层以对图像进行分类。
图3-5全连接层示意图
三.4.5. 感受野
在神经网络中,每个神经元接收来自前一层中某些位置的输入。在完全连接的层中,每个神经元接收来自前一层的每个元素的输入。在卷积层中,神经元仅从前一层的受限子区域接收输入。通常,子区域具有正方形形状(例如,尺寸5乘5)。神经元的输入区域称为其感受野。因此,在完全连接的层中,感受野是整个前一层。在卷积层中,接收区域小于整个前一层。
三.4.6. 权重
神经网络中的每个神经元通过将一些函数应用于来自前一层中的感受野的输入值来计算输出值。应用于输入值的函数由权重向量和偏差(通常为实数)指定。通过对偏差和权重进行增量调整,在神经网络中进行学习。权重和偏差的矢量被称为滤波器并且表示输入的一些特征(例如,特定形状)。CNN的一个显着特征是许多神经元共享相同的滤波器。这减少了内存占用因为在共享该过滤器的所有感受野中使用单个偏差和单个权重向量,而不是每个感受野具有其自身的偏差和权重向量
第四章 目标检测的构建
四.1. 环境配置
首先安装Tensorflow及需要用到的python库并CLONE Object Detection API
#from ~
Pip3 install tensorflow-gpu==1.12
pip install –user Cython
pip install –user contextlib2
pip install –user pillow
pip install –user lxml
pip install –user jupyter
pip install –user matplotlib
克隆models目录
Git clone https://github.com/tensorflow/models.git
Tensorflow对象检测API使用Protobufs配置模型和训练参数。在使用框架之前,必须编译Protobuf库。
# From tensorflow/models/research/
protoc object_detection/protos/*.proto –python_out=.
在本地运行时,tensorflow / models / research /和slim目录应该附加到PYTHONPATH。
#from ~
Cat>>.bashrc
export PYTHONPATH=$PYTHONPATH:/home/jcjcjc/Desktop/models/research:/home/jcjcjc/Desktop/models/research/slim
最后通过运行以下命令来测试您是否已正确安装Tensorflow Object Detection API:
#from models / research
Python3 object_detection/builders/model_builder_test.py
图4-1命令执行结果图
四.2. 数据集收集、处理
首先使用了微信公众平台进行收集。为了增加用户粘性,联结了图灵机器人,用户除了提交数据集,还可以和机器人聊天。
微信后台被动回复用户消息主要处理逻辑:
微信后台被动回复用户消息代码见附录A
图4-2 数据集截图(1)
与此同时,还发动朋友协助拍照,获取数据集。此数据集相比微信后台获取的质量相对更高。
图4-3 数据集截图(2)
数据集收集结束后,还要手工打标,此处使用了标注工具labelImg。
#from ~
Git clone https://github.com/tzutalin/labelImg.git
Cd labelImg/
python3 labelImg.py
图4-3 打标工具使用截图
TensorFlow目标检测API要求所有标记的训练数据都采用TFRecord文件格式。由于LabelImg以与PASCAL VOC数据集相同的格式保存标注图片,所以可以先把.xml标签和图片调整为PASCAL VOC格式,再使用tensorflow已经提供的create_pascal_tf_record.py轻松生成TFRecord文件。
–VOC2007#不同年份的数据集
–Annotations#存放xml文件,与JPEGImages中的图片一一对应
–ImageSets#
–Main#存放的是目标识别的数据,主要有test.txt , train.txt, val.txt,trainval.txt四个文件。
–Layout#未用到,不需新建
–Segmentation#未用到,不需新建
–JPEGImages#存放所以数据集图片
–SegmentationClass#未用到,不需新建
–SegmentationObject#未用到,不需新建
按照PASCAL VOC格式存放数据集后,要制作VOC2007数据集中的trainval.txt, train.txt , test.txt , val.txt。trainval占总数据集的50%,test占总数据集的50%;train占trainval的50%,val占trainval的50%;
-train.txt 是用来训练的图片文件的文件名列表
- val.txt是用来验证的图片文件的文件名列表
- trianval.txt是用来训练和验证的图片文件的文件名列表
- test.txt 是用来测试的图片文件的文件名列表
将打标时用到的所有菜品名称存入research/object_detection/data/jc下,data/jc/目录为之后训练目录。
图4-4 passcal_lable_map.pbtxt文件截图
使用create_pascal_tf_record.py转换为TFRecord格式数据集。
#from /home/jcjcjc/Desktop/models/research/object_detection
python3 dataset_tools/create_pascal_tf_record.py \
–data_dir=’/home/jcjcjc/Desktop/demo/‘ \
–label_map_path=data/jc/pascal_label_map.pbtxt \
–year=VOC2007 –set=trainval –output_path=’data/jc/pascal_train.record’ \
python3 dataset_tools/create_pascal_tf_record.py \
–data_dir=’/home/jcjcjc/Desktop/demo/‘ \
–label_map_path=data/jc/pascal_label_map.pbtxt \
–year=VOC2007 –set=test –output_path=’data/jc/pascal_val.record’
至此,数据集收集处理完毕。
四.3. 模型选择
图4-5 模型对比图
四.3.1. MobileNets-用于移动视觉应用的高效卷积神经网络
MobileNets,是TensorFlow的移动优先计算机视觉模型系列,旨在有效地最大限度地提高准确性,同时注意设备或嵌入式应用程序的受限资源。MobileNets是小型,低延迟,低功耗模型,参数化以满足各种用例的资源限制。它们可以用于分类,检测,嵌入和分割,类似于使用其他流行的大型模型(如Inception)。
MobileNets基于流线型架构,使用深度可分离卷积来构建轻量级深度神经网络。
四.3.2. R-FCN-基于区域的完全卷积网络的对象检测
与先前基于区域的检测器(例如快速/快速R-CNN)相比,基于区域的检测器完全卷积,几乎所有计算都在整个图像上共享。结果是以每张图像170毫秒的测试时间速度实现,比快速R-CNN对应物快2.5-20倍。
四.3.3. Faster R-CNN-利用区域提案网络实现实时目标检测
在这项工作中,引入了一个区域提议网络(RPN),它与检测网络共享全图像卷积特征,从而实现了几乎无成本的区域提议。RPN是一个完全卷积网络,可同时预测每个位置的对象边界和对象分数。RPN经过端到端的培训,可以生成高质量的区域提案,由快速R-CNN用于检测。通过共享其卷积特征将RPN和Fast R-CNN合并到一个网络中。
由于电脑性能低并且期望低延迟,所以选择了TensorFlow提供的最简单(也是最快)的预训练模型,MobileNets。
四.4. 训练与测试
将模型下载下来,将里面的三个.ckpt的检查点拷贝到之前创建的训练目录下的models下,并创建train文件夹。
修改ssdlite_mobilenet_v1_coco.config。首先修改fine_tune_checkpoint,设置为检查点的路径(”models/model.ckpt”)。修改num_steps为训练次数,接下来,需要更改训练和评估数据集的input_path和label_map_path为TFRecord格式数据集路径。
在数据目录下,执行训练程序
python3 train.py –logtostderr \
–train_dir=./models/train \
–pipeline_config_path=ssdlite_mobilenet_v1_coco.config
经过漫长的训练后,使用存盘程序将训练检查点保存为.pb的模型
python3 export_inference_graph.py \
–input_type image_tensor \
–pipeline_config_path ./ssdlite_mobilenet_v1_coco.config \
–trained_checkpoint_prefix ./models/train/model.ckpt-125 \
–output_directory ./fine_tuned_model
第五章 其他程序设计
五.1. 后台管理
五.1.1. 微信公众号信息处理模块–handle.py
图5-1 微信公众号信息处理模块流程图
微信公众号信息处理模块代码handle.py见附录B
表5-1 回复文本消息结构
参数 | 是否必须 | 描述 |
---|---|---|
ToUserName | 是 | 接收方帐号(收到的OpenID) |
FromUserName | 是 | 开发者微信号 |
CreateTime | 是 | 消息创建时间 (整型) |
MsgType | 是 | 消息类型,文本为text |
Content | 是 | 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示) |
表5-2 接收文本消息结构
参数 | 描述 |
---|---|
ToUserName | 开发者微信号 |
FromUserName | 发送方帐号(一个OpenID) |
CreateTime | 消息创建时间 (整型) |
MsgType | 消息类型,文本为text |
Content | 文本消息内容 |
MsgId | 消息id,64位整型 |
表5-3 接收图片消息结构
参数 | 描述 |
---|---|
ToUserName | 开发者微信号 |
FromUserName | 发送方帐号(一个OpenID) |
CreateTime | 消息创建时间 (整型) |
MsgType | 消息类型,图片为image |
PicUrl | 图片链接(由系统生成) |
MediaId | 图片消息媒体id,可以调用获取临时素材接口拉取数据。 |
MsgId | 消息id,64位整型 |
五.1.2. 计算节点通信控制模块–socc.py
图5-2 计算节点通信控制模块流程图
计算节点通信控制模块代码socc.py见附录C
五.1.3. 计算节点计算模块
图5-3 计算节点计算模块流程图
计算节点计算程序OObject_Detection_tf_API.py代码见附录D
计算节点通信程序mydemoclient.py代码见附录E
五.2. 安全设计
由于部署在阿里云,可以很简单地通过配置安全组实现只打开需要使用的端口。
图5-4 阿里云入方向安全组规则
图5-5 阿里云出方向安全组规则
第六章 系统测试
六.1. 神经网络测试
可以使用Tensorboard观察训练结果。
在训练目录下执行 tensorboard–logdir train/
之后可以在浏览器查看训练情况。
图6-1 tensorboard结果图(1)
可以看到训练过程中的loss率;
图6-2 tensorboard结果图(2)
可以看到,最终训练了125步,错误率为7.067.
将测试用图片存放在models/research/object_detection/test_images/下,在models/research/下执行目标检测程序python3 Object_Detection_tf_API.py,可以看到打印出了识别结果,在models/research\My-pic下可以看到执行后的结果。
图6-3 执行结果图(1)
图6-4 执行结果图(2)
六.2. 微信后台服务测试
用手机微信发送文字信息,收到自动回复,发送图片,收到“计算节点未链接= =”的回复;则表示微信后台服务正常。
图6-5 执行结果图(3)
六.3. 系统联调
在计算机models/research/下执行python3 mydemoclient.py执行计算节点程序。用手机在微信上发送图片,能收到回复的菜名。
图6-6 执行结果图(4)
存在问题及改进方向
食堂采集识别系统基本实现了菜价识别。对于高并发情况暂时还难以应对。下一步要在计算节点管理部分增加节点列表,实现分布运算。由于设备和数据集原因,目前识别精度不够高,可进一步提高。与微信服务器通信在使用http传输,为了更好地保护好用户隐私,可以改用https协议。计算节点与后台建立链接无需认证,图片等信息有可能被他人窃取,将在建立连接前进行认证,对认证未通过的链接直接close。这些问题主要是由于我对编程技术的运作不够熟悉,在以后的日子里我还需要更加努力的学习来提升自己的各方面的能力,减少这样的情况。