目 录
摘要 Ⅰ
ABSTRACT Ⅱ
第一章 绪论
1.1手写体数字识别研究的发展及研究现状
1.2神经网络在手写体数字识别中的应用
1.3 论文结构简介
第二章 手写体数字识别
2.1手写体数字识别的一般方法及难点
2.2 图像预处理概述
2.3 图像预处理的处理步骤
2.3.1 图像的平滑去噪
2.3.2 二值话处理
2.3.3 归一化
2.3.4 细化
2.4 小结
第三章 特征提取
3.1 特征提取的概述
3.2 统计特征
3.3 结构特征
3.3.1 结构特征提取
3.3.2 笔划特征的提取
3.3.3 数字的特征向量说明
3.3 知识库的建立
第四章 神经网络在数字识别中的应用
4.1 神经网络简介及其工作原理
4.1.1神经网络概述[14]
4.1.2神经网络的工作原理
4.2神经网络的学习与训练[15]
4.3 BP神经网络
4.3.1 BP算法
4.3.2 BP网络的一般学习算法
4.3.3 BP网络的设计
4.4 BP学习算法的局限性与对策
4.5 对BP算法的改进
第五章 系统的实现与结果分析
5.1 软件开发平台
5.1.1 MATLAB简介
5.1.2 MATLAB的特点
5.1.3 使用MATLAB的优势
5.2 系统设计思路
5.3 系统流程图
5.4 MATLAB程序设计
5.5 实验数据及结果分析
结论 27
参考文献 28
致谢 30
附录 31
摘 要
手写体数字识别是模式识别中一个非常重要和活跃的研究领域,数字识别也不是一项孤立的技术,它所涉及的问题是模式识别的其他领域都无法回避的;应用上,作为一种信息处理手段,字符识别有广阔的应用背景和巨大的市场需求。因此,对数字识别的研究具有理论和应用的双重意义。
人工神经网络识别方法是近年该研究领域的一种新方法,该方法具有一些传统技术所没有的优点:良好的容错能力、分类能力强、并行处理和自学习能力,并且是离线训练和在线识别的。这些优点使它在手写体字符的识别中能对大量数据进行快速实时处理,并达到良好的识别效果。
由于手写体数字识别难于建立精确的数学模型,所以本文采用BP神经网络对这一问题进行处理。神经网络模式识别的一个关键步骤是预处理和特征提取,对于手写体数字识别,本文采用了一种基于结构特征和统计特征的提取方法,并用程序实现了这一特征提取过程。
通过测试,本识别系统对于较规范的手写体数字的识别达到了很好的识别效果。
关键词: 手写体数字识别,特征提取,人工神经网络,MATLAB
ABSTRACT
Handwritten character recognition is a very important and active research in pattern recognition. Theoretically, it is not an isolated technique. It concerns with the problem that all the other areas of pattern recognition must confronted; practically, being a kind of information processing measured, character recognition has a very broad application background and vast need of market. Thus, it is of both theoretical and practical significance.
Artificial neural network recognition method is a new method of the research field in recent years, and this method has some merit that traditional technique do not have; good tolerance for error, strong sorting ability, strong parallel handling ability and strong self-learning ability as well as its off-line training and on-line recognizing. All these merits contribute its perfect performance in handling vast data set and handling in timely manner.
It’s difficult to make accurate mathematics model for handwritten numeral recognition, so BP neural networks is used here. The key steps of neural networks pattern recognition are preprocessing and feature subset selection. In this paper, algorithm of feature subset selection basing on structural characteristics and statistical characteristics has been adopted in handwritten numeral recognition, and the process of feature subset selection had been realized in program.
Recognition system in this paper has achieved a good rate of recognition in random handwritten numeral by test.
Keyword: handwritten numeral recognition, feature extraction, artificial neural network, MATLAB
第一章 绪 论
1.1手写体数字识别研究的发展及研究现状
模式识别[2]是六十年代初迅速发展起来的一门学科。由于它研究的是如何用机器来实现人(及某些动物)对事物的学习、识别和判断能力,因而受到了很多科技领域研究人员的注意,成为人工智能研究的一个重要方面。一个模式识别系统的基本职能是对系统所要处理的模式归属于哪一类做出判别,从该系统的模式输入到系统做出判别之间,主要包括信息检测、预处理、特征提取和分类几大环节。
字符识别是模式识别领域中的一个非常活跃的分支。一方面是由于问题本身的难度使之成为一个极具挑战性的课题;另一方面,是因为字符识别不是一项孤立的应用技术,其中包含的模式识别领域中其他分支都会遇到的一些基本和共性的问题。从50年代开始,许多的研究者就在这一研究领域开展了广泛的探索并为模式识别的发展产生了积极的影响。
字符识别,从采用的输入设备来分,可分为脱机识别(又称为光学字符识别Optical Character Recognition ,OCR)和联机识别,脱机字符又分为印刷体和手写字符识别,从对书写者要求来分,手写字符又分为限制性和非限制性的手写字符识别。在联机手写字符识别中,计算机能够通过与计算机相连的手写输入设备获得输入字符笔划的顺序、笔划的方向以及字符的形状,所以相对OCR来说它更容易识别一些。但联机字符识别有一个重要的不足就是要求输入者必须在指定的设备上书写,然而人们在生活中大部分的书写情况是不满足这一要求的,比如人们填写各种表格资料,开具支票等。如果需要计算机去认识这些已经成为文字的东西,就需要OCR技术。比起联机字符识别来,OCR不要求书写者在特定输入设备上书写,它可以与平常一样书写,所以OCR的应用更为广泛。OCR所使用的输入设备可以是任何一种图像采集设备,如扫描仪、数字相机等。通过使用这类采集设备,OCR系统将书写者已经写好的文字作为图像输入到计算机中,然后由计算机去识别。由于OCR的输入只是简单的一副图像,它就不能像联机输入那样比较容易的从物理上获得字符笔划的顺序信息,因此OCR是一个更具挑战性的问题。
脱机字符识别(OCR)分为印刷体OCR和手写OCR。印刷体字符比手写体字符少了随机性,它的识别相对容易些,难点已经不在识别环节,而在于字符的分割上。印刷体识别的错误绝大多数都是错误的分割引起的[3]。对于手写体OCR,无论是联机还是脱机识别,手写体的识别都要经历由限制性手写体识别到非限制性手写体识别两个阶段。本文将以手写体数字为代表,讨论非限制性手写体字符的识别。脱机字符识别的研究最早始于上个世纪六十年代,是为了应付汉英翻译的需要。八十年代后的研究重心转移到脱机手写字符的识别上。对于小类别数的字符集如数字、字母的识别,已经可以做到对书写不加任何的限制。非限制性手写OCR的研究始终以阿拉伯数字为主导。这事因为,第一,十个阿拉伯数字是全世界的一套通用字符。第二,在数字的许多应用场合,如报表、账单、支票等,手写体还难以被印刷体所替代,而且对识别的可靠性要求极高。三,由于类别数少,所以模式识别中的许多方法研究均可以以数字识别作为实验背景。对脱机手写体字符的研究,人们由简单集成笔画密度、笔画方向和背景特征方法过渡到特征匹配方法,进而过渡到结合神经网络方法,随着对识别可靠性要求的提高,九十年代以后,多分类器集成方法成为了一个研究重点。
1.2神经网络在手写体数字识别中的应用
目前,随着计算机的迅速发展,性能价格比的不断提高,模式识别技术已经从理论探讨为主发展到大量的实际应用,人们将更多的注意力开始转向那些用于语音、图像、机器人以及人工智能等的模式识别实际问题。解决这些问题的关键是需要进行复杂而庞大的实时数据处理,而现有计算机的存贮容量及计算复杂性的局限,使得真正实时化的应用受阻。这种面向实时应用的模式识别问题促使人们开始将并行处理的神经网络[4]应用到模式识别,而神经网络模式识别技术又将模式识别实时应用推进了一大步,手写体数字识别就是这种应用的一个很重要的领域。
手写体数字识别是一项极具研究价值的课题,随着神经网络[1]和模糊逻辑技术的发展,人们对这一问题的研究又采用了许多新的方法和手段,也使得这一古老的课题焕发出新的生命力[5]。目前国际上有相当多的学者在研究这一课题,它包括了模式识别领域中所有典型的问题:数据的采集、处理及选择、输入样本表达的选择、模式识别分类器的选择以及用样本集对识别器的有指导的训练。人工神经网络为手写体数字识别提供了新的手段。正是神经网络所具有的这种自组织自学习能力、推广能力、非线性和运算高度并行的能力使得模式识别成为目前神经网络最为成功的应用领域。
二十多年来,人们在数字识别领域做了大量的研究工作,所提出的各种方法在印刷体和手写印刷体数字识别方面已经取得了较好的成绩,识别率稳定在96%左右。但是自由手写体数字的识别工作目前并不成熟,仍旧是文字识别中最有挑战性的课题之一。
字符识别长期以来都是采用传统的识别方法,对印刷体字符的识别率一般只是稳定在96%左右,不能进一步提高;而对手写体字符的识别,其研究还处于探索阶段,其识别率还相当低,因此,为了提高识别率,就必须寻求新的方法和途径。
进入九十年代以来,人工神经网络(ANN)技术发展十分迅速,它具有模拟人类部分形象思维的能力,是一种模仿人脑学习、记忆、推理等认知功能的新方法。特别是它的信息并行分布式处理能力和自学习功能等显著优点,更是激起了人们对它的极大的兴趣。人工神经网络是由一些类似人脑神经元的简单处理单元相互连接而成的复杂网络。已涌现出许多不同类型的ANN及相应的学习算法,其中BP(或EBP-Error Back Propagation)网络及学习算法得到了广泛关注和研究,并在数字识别方面取得了许多有意义的应用成果。
1.3 论文结构简介
本毕业设计主要解决以图像形式存在的手写体数字识别的问题。整体分为三个部分,第一部分是图像预处理,第二部分是对手写体数字的结构特征的提取,第三部分是设计神经网络并对前面得到的样本数据进行学习和训练。
本文通过图像预处理和数字特征提取以后基于神经网络的判别方法,然后结合使用了MATLAB工具箱中提供的人工神经网络函数设计了一种手写数字识别的新方法。实验表明,该方法可以获得较好的识别率。
第二章 手写体数字识别
2.1手写体数字识别的一般方法及难点
字符识别问题的研究已有几十年的历史了,但时至今日,字符识别的研究成果远未达到人们所期望的,这其中有理论研究和技术实现等多方面因素. 在理论方面,我们对人类的视觉认知机理的研究还只是初步的,远未达到深入和透彻的水平。在技术方面,我们使用的计算机的运算水平和存储能力, 比起人脑的信息存储和处理能力有很大差距. 因此,目前的文字识别只能建立在现有的理论基础上,使用现有的技术来研究和解决问题。手写体数字识别是字符识别的一个分支,问题虽然简单,但却有较大的实用价值。
数字的类别虽然只有十种,笔划又简单,其识别问题表面上是一个较简单的分类问题。但实际上,虽然各种新的识别算法不断的推出。其识别率和误识率仍距实用有相当距离。手写阿拉伯数字具有变形多差异大的特点,字形与书写人的职业、文化程度、书写习惯以及所使用笔墨纸张所处环境等都有关,所以手写体数字变形多、规律复杂。具体地说有两个:一是0~ 9 十个数字中,其中的一些数字字形相差不大,使得准确区分某些数字相当困难;二是数字虽然只有十种,但同一数字写法千差万别。不同的人写出的同一个数字都有差别,即使同一个人在不同的时候也会有不同的写法。笔划的书写顺序经常发生变化,因此极大地增加了匹配的难度。一般人写字时都不会一笔一划的书写,为了节省时间,连笔字是自然而然的事情,对于结构识别而言,连笔一方面使笔划种类大大增加,甚至达到难以归纳的程度;另一方面,连笔又使得笔段抽取难度大增,因为连笔会增加一些冗余笔段,连笔造成的畸变又会使笔段方向严重离散。总之,连笔不论对于基于哪种基元的结构识别都是严峻的挑战。这是造成手写数字识别过程复杂、达到较高识别率困难的根本原因。
如图2.1各种各样的手写体数字。
图2.1 各种各样的手写体数字
2.2 图像预处理概述
预处理[6]是字符识别重要的一环, 它把原始的图像转换成识别器所能接受的二进制形式。
要识别手写体数字首先要对其字符图像进行预处理。预处理的主要目的是去除字符图像中的噪声、压缩冗余信息, 得到规范化的点阵, 为识别做好准备。这就要求预处理在消除图像中与识别无关的因素时尽量保持原图像的字符特征。
手写体数字图像预处理的过程,就一般情况而言,主要经过如图2.2所示的几个步骤。不同的识别方法对预处理的项目和要求有所不同。如结构识别方法[7],对字符规范化可以从简,甚至不需要。有的识别方法对细化要求很高,有的则不需要细化。本章中将分别对平滑去噪、二值化、归一化和细化分小节讨论。
图2.2 图像预处理的基本流程
2.3 图像预处理的处理步骤
2.3.1 图像的平滑去噪
手写体数字由于其随机性大,断笔,连笔、飞白状况时常发生,为了减少灰度图像的一些不该出现的黑白噪声,可以采用图像的平滑去噪技术。
进行图像平滑处理的是一种空域滤波器[8],空域滤波器一般可分为线性滤波和非线性滤波两类。线性滤波器的设计常基于对傅立叶变换的分析,如均值滤波器;非线性滤波器则一般直接对邻域进行操作,如中值滤波器。
以下为采用中值滤波对图像进行平滑处理的部分代码[9]:
for i=2:175;
for j=2:259
Xtemp=0;
for m=1:3
for n=1:3
Xtemp=Xtemp+X2(i+m.2,j+n.2);
end
end
Xtemp=Xtemp/9;
X3(i,j)=Xtemp;
end
end
2.3.2 二值化处理
图像的二值化就是把图像中的像素根据一定的标准划分成两种颜色。在这个系统中就是根据像素的灰度值处理成黑白两种颜色。对数字字符图像二值化后要能真实的再现原数字, 其基本要求为:笔画中不出现空白点, 二值化的笔画基本保持原来文字的结构特征。图像二值化的关键在于阈值的选择。图像的二值化有很多成熟的算法, 有整体阈值二值化法、局部阈值二值化法、动态阈值二值化法等。
二值化的关键在于阈值的选取,阈值选取主要分为整体阈值法、局部阈值法和动态阈值法。三类阈值的选择是一个比较复杂的问题,有的可以由计算机自动选择,有的需人工干预。基于字符识别扫描得到的图像目标与背景的灰度级有明显的差别,字符图像的二值化可采用整体阈值法中的双峰法,该方法简单易行,针对目标与背景的灰度级有明显差别的图像,其灰度直方图的分布呈双峰状,两个波峰分别与图像中的目标和背景相对应,波谷与图像边缘相对,应当在分割阈值位于谷底时,图像分割可取得最好的效果。
下面给出我在设计过程中二值化以后的效果图如图2.3。
图2.3 二值化处理
2.3.3 归一化
本文使用的数字图像都是在 Windows XP 画图板中手写输入的。由于10 ×14像素图像(10 是图像宽度,14 是图像高度)较小,书写时难度较大。我们希望书写时尽量不限制图像的大小,然后通过计算统一尺寸,使之具有同一高度,同一宽度,称之为归一化[10]。
在数字图像处理中有一些比较成熟的缩放图像的算法,例如 MATLAB 使用 imresize函数来改变图像的大小。它的调用格式为 I2=imresize(I,rate),I 存储的是原始图像的数组,rate 是变化率,I2 存储的是改变后图像的数组。例如 rate=0.5 时,高度和宽度都将缩小一半,原始图像也就缩小了一半。这一算法的缺点是只能将原始图像的高度和宽度同时变化相同的比例,如果我们希望将原始图像变成10 ×1 4像素的图像,该算法就无法解决了。显然这种算法不适合解决我们面临的问题。
本文提出了一种新的归一化算法,可以将不同尺寸的二值图像统一为10×14 像素的图像。具体算法是:先得到原始图像的高度和宽度,分别与系统要求得到的高度和宽度作比较,得出要变换的系数,然后根据得到的系数计算每一个原始像素点归一化后在新图像中的位置,最后计算新图像中每个像素点的值,方法是:求出原始像素点及其周围三个点的像素值的平均值,最后用函数 floor.m 取整,调用格式为 B=floor(A),B 取小于或者等于 A 的整数。
归一化算法程序代码如下:
ans=imread('0.bmp'); %读入图片 0.bmp,28 × 28像素图像
imshow(ans)
[r,c]=size(ans); % r 是原图像的高度,c 是宽度
for i=2:(r-1)
for j=2:(c-1)
n=i/(r/14);
n=ceil(n);
m=j/(c/10);
m=ceil(m);
M(n,m)=(ans(i,j)+ans(i,j+1)+ans(i,j-1)+ans(i-1,j))/4;
N(n,m)=floor(M(n,m));
end
end
imshow(N)
例如,数字图像“0.bmp”经该归一化算法计算得到矩阵 M,MATLAB 运行结果如图2.4所示。
图2.4 归一化处理
2.3.4 细化
许多字符识别方法在预处理中都很重视对二值化字符的细化处理。直观来说,细化就是将二值化字符点阵逐层剥去轮廓上的点,变成笔画宽度只有一个像素宽度的字符骨架图形。之所以需要细化处理,是因为二值化点阵图形中,对识别有价值的文字特征信息主要集中在字符骨架上,细化后的字符骨架既保留了原字符的绝大部分的特征,又利于特征提取。细化后骨架的存储量比原来的二值化字符点阵要少得多,降低了处理工作量。
手写体数字细化的基本要求如下:
第一、保持原有字符笔画的连续性,不能由于细化造成笔画断裂。
第二、要细化为单线,即笔画宽度为一个像素。
第三、细化后的骨架应尽量是原来笔画的中心线。
2.4 小结
预处理是手写数字识别中不可缺少的组成部分,对图像预处理的好坏直接影响到识别的结果, 关系到识别算法的好坏。文中首先对待识别数字的预处理进行了介绍,包括平滑去噪、二值化、归一化、细化等图像处理方法,经过这些预处理步骤, 对图像中部分变形信息进行了修正, 消除图像中与识别无关的因素, 而且尽量保持原图像的字符特征, 在实验中提高了数字识别网络的性能。
第三章 特征提取
3.1 特征提取的概述
模式识别使用特征来区分不同的种类。因此,特征提取是模式识别系统的关键部分。特征提取的目标是找到某种变换,将N维或N*N维的模式类别空间转换到维数小得多的M维特征空间,并同时保留模式识别所需要的大部分信息。通过特征提取,模式分类可以在维数低得多的空间上进行,从而降低了计算的复杂度。而且,对给定的训练样本进行特征提取可以获得更精确的分类函数的描述,以构造更可靠的分类规则。
同样对于手写体数字的识别,特征提取可以降低字符信息量、去除无用的冗余信息,提高识别系统效率,一直是字符识别领域中的关键点。
特征提取的目的是从原始数据中抽取出用于区分不同类型的本质特征。无论是识别过程还是学习过程,都要对研究对象固有的、本质的重要特征或属性进行量测并将结果数值化,形成特征矢量。
手写体数字的识别中,常用的特征有结构特征和统计特征。结构特征和统计特征各有其优点:结构特征能描述字符的结构,对于不同人书写的字符,形体不同,但结构都是一致的,所以结构特征能克服手写字体因人而引起的畸变;统计特征最大的优点是对环境噪音不敏感,如若字符的背景噪音通常都是呈高斯分布,用统计特征进行识别可对此影响忽略不计。本章将用两小节分别对结构特征和统计特征进行论述。
3.2 统计特征
对复杂图像信号作小波变换[11],进行多分辨率分析,已经成为图像信号分析和处理的常用方法。由于小波变换的结果体现为大量的小波分解系数,这些系数包含了系统或信号本身大量和多样的特征信息。如果图像信号的主要信息能以一个或一组特征量来表征,我们就可以更加直观、有效和方便地对各种随机信号进行信息提取、信号检测、特征识别。
统计特征分为宏观特征信息和局部特征信息。宏观特征信息是需要在整幅图像上获取的特征信息。传统的全局特征主要包括:全局变换特征(对字符图像进行各种变换,利用变换系数作为特征向量,常用的变换有Fourier变换、K-L变换、小波变换等)、不变矩特征、全局笔划方向特征等;常用的局部统计特征有:局部笔划方向特征、Gabor特征等。统计特征对微小的畸变不敏感,但区分相似的能力较差。
以下为程序设计中对小波分析提取低频部分的统计特征的实例:
f=imread('sample.bmp');输入图像
[c,s]=wavedec2(h,3,'db2');对人脸图像进行3阶小波分解,并提取小波系数
wave2gray(c,s,8);显示小波分解后各子图
y=wavecopy('a',c,s)
figure,imshow(mat2gray(y));提取主要特征
3.3 结构特征
采用结构特征[12]对字符进行结构分析从而达到识别目的,是一种非常直观的方法。字符由各个子部件构成,逐级分析字符图像的结构,根据各元素的属性、数量及其相互关系,便可判定待识字符。与统计方法相比,结构分析不注重特征的绝对位置,只考虑特征的相对关系,因而对书写风格的变化不敏感,其缺点在于特征提取和模板的建立都十分困难,匹配算法也比较复杂,神经网络的应用弥补了这个缺点,只要提取出适当的结构向量作为神经网络的输入向量,会得到令人满意的识别输出结果。以下详细介绍。
3.3.1 结构特征提取
首先对经预处理后的图像进行分割,如图3.1所示。
图3.1 图像分割
对图像分割后,结构特征提取的算法如下:
(1)对细化后的数字图像取竖直的三条直线,分别取在5/12,1/2,7/12处,记下这三条竖直直线与数字笔段的交点数。
(2)再取水平三条直线,分别取在1/3,1/2,2/3处, 分别记下这三条水平直线与数字笔段的交点数。
(3)再取对角两条直线, 分别记下这两条对角直线与数字笔段的交点数。
3.3.2 笔划特征的提取
经细化后的数字图像其特征较为稳定,且笔划简单,因此对其抽取的基本结构组件能反映数字的本质特征,从而可快速有效地识别数字,并达到较好的分类效果。数字端点如图3.2所示。
图3.2数字端点
对图像分割后,结构特征提取的算法如下:
(1)按从上到下,从左到右的顺序扫描预处理后图像并选择黑像素点P;
(2)计算像素P的8-邻域之和N;
(3)若N=1,则像素P为端点,端点计数器加一;
(4)重复步骤(1)-(3),直到遍历整个图像。
3.3.3 数字的特征向量说明
依据上述特征提取方法,本系统中的特征矢量由9个分量组成,其排列如下所示:
DATA=[ 竖直中线交点数,
竖直5/12处,
竖直7/12处,
水平中线交点数 ,
水平1/3处交点数,
水平2/3处交点数,
左对角线交点数,
右对角线交点数,
端点数 ];
3.3 知识库的建立
由于本文采用的是基于模式知识库的识别方法,所以对字符的结构特征的分析以及字符模型的构造是一个十分重要的环节,图3.3就是对识别数字的标准形态进行具体分析而构造的模板。
图3.3 规范手写体数字形态
以下为规范手写体数字形态的特征向量:
DATA01=[2,2,2,2,2,2,2,2,0];
DATA11=[1,0,0,1,1,1,1,1,2];
DATA21=[3,3,3,1,1,1,1,1,3];
DATA31=[3,2,3,1,1,1,2,2,3];
DATA41=[1,1,1,2,2,1,3,2,4];
DATA51=[3,3,3,1,1,1,2,2,4];
DATA61=[3,3,2,1,1,2,3,2,1];
DATA71=[2,2,2,1,1,1,1,1,2];
DATA81=[4,4,4,2,2,2,2,2,0];
DATA91=[3,3,3,1,2,1,3,1,1]。
由于本系统是对自由手写体进行识别, 因而要考虑数字书写体的多变性。通过对图3.4所示的数字变体的分析来对知识库进行补充。
图3.4手写体数字变体
以下为手写体数字变体形态的特征向量:
DATA02=[1,1,2,2,2,2,1,2,2];
DATA22=[3,2,2,1,1,1,1,3,2];
DATA32=[3,1,4,2,1,1,2,2,3];
DATA42=[1,2,2,3,3,1,2,2,2];
DATA52=[3,3,3,1,1,1,2,2,4];
DATA62=[3,1,3,1,1,2,2,2,2];
DATA82=[4,4,4,2,1,2,1,2,2];
DATA92=[3,2,3,2,1,1,3,1,3]。
最后得到的知识库由上述两套模板所组成。
第四章 神经网络在数字识别的应用
4.1 神经网络简介及其工作原理
人的智能来自于大脑,大脑是由大量的神经细胞或神经元组成的。每个神经元可以看作为一个小的处理单元,这些神经元按照某种方式互相连接起来,构成了大脑内部的生理神经元网络。他们中各神经元之间连接的强弱,按照外部的激励信号作自适应变化,而每个神经元又随着接收到的多个激励信号的综合大小呈现兴奋或抑制状态。
4.1.1神经网络概述
人工神经元网络是生理学上的真实人脑神经网络的结构和功能,以及若干基本特性的某种理论抽象、简化和模拟而构成的一种信息处理系统。从系统观点看,人工神经元网络是由大量神经元通过极其丰富和完善的联接而构成的自适应非线性动态系统。由于神经元之间有着不同的连接方式,所以组成不同结构形态的神经网络[14]系统是可能的。
据现在的了解,大脑的学习过程就是神经元之间连接强度随外部激励信息做自适应变化的过程,大脑处理信息的结果确由神经元的状态表现出来。显然,神经元是信息处理系统的最小单元。虽然神经元的类型有很多种,但其基本结构相似。
4.1.2神经网络的工作原理
人工神经网络首先要以一定的学习准则进行学习,然后才能工作。现以人工神经网络对手写“A”、“B”两个字母的识别为例进行说明,规定当“A”输入网络时,应该输出“1”,而当输入为“B”时,输出为“0”。
所以网络学习的准则应该是:如果网络做出错误的判决,则通过网络的学习,应使得网络减少下次犯同样错误的可能性。首先,给网络的各连接权值赋予(0,1)区间内的随机值,将“A”所对应的图像模式输入给网络,网络将输入模式加权求和、与门限比较、再进行非线性运算,得到网络的输出。在此情况下,网络输出为“1”和“0”的概率各为50%,也就是说是完全随机的。这时如果输出为“1”(结果正确),则使连接权值增大,以便使网络再次遇到“A”模式输入时,仍然能做出正确的判断。
如果输出为“0”(即为结果错误),则把网络连接权值朝着减小综合输入加权值的方向调整,其目的在于使网络下次再遇到“A”模式输入时,减小犯同样错误的可能性。如此操作调整,当给网络轮番输入若干个手写字母“A”、“B”后,经过网络按以上学习方法进行若干次学习后,网络判断的正确率将大大提高。这说明网络对这两个模式的学习已经获得了成功,它已将这两个模式分布地记忆在网络的各个连接权值上。当网络再次遇到其中任何一个模式时,能够做出迅速、准确的判断和识别。一般说来,网络中所含的神经元个数越多,则它能记忆、识别的模式也就越多。
4.2神经网络的学习与训练
人脑中一个典型神经元通过许多树突的精细结构,收集来自其它神经元的信息,神经元又通过轴突的一条长而细的轴突发出电活性脉冲。轴突分裂上千条分支,在每条分支末端,通过突触的结构把来自轴突的电活性变为电作用,从而使与之相连的各种神经元的活性受到抑制或兴奋。
当一个神经元收到兴奋输入,而兴奋输入又比神经元的抑制输入足够大时,神经元把电活性脉冲向下传到它的轴突,改变轴突的有效性,从而使一个神经元对另一个神经元的影响改变,便发生了学习行为。因此,可以认为神经网络学习的本质特征在于神经细胞特殊的突触结构所具有的可塑性连接,而如何调整连接权重就构成了不同的学习算法。
通过向环境学习获取知识并改进自身性能是NN的一个重要特点。在一般情况下,性能的改善是按某种预定的度量通过调节自身参数(如权值)随时间逐步达到的。学习方式[15](按照环境提供信息量的多少)有三种:
1.监督学习(有教师学习)
为了使神经网络在实际应用中解决各种问题,必须对它进行训练,就是从应用环境中选出一些样本数据,通过不断地调整权矩阵,直到得到合适的输入输出关系为止,这个过程就是对神经网络的训练过程,这种训练的过程需要有教师示教,提供训练数据,又称样本数据。在训练过程中又需教师的监督,故这种有教师的学习又称为监督式学习。
有教师学习方法虽然简单,但是要求教师对环境和网络的结构应该比较熟悉,当系统复杂,环境变化时,就变得困难。为了适应环境变化就要重新调整加权值,这样,当学习到新知识的同时,也容易忘掉已学过的旧知识,这一些是有教师学习方法的缺点。
2.非监督学习(无教师学习)
非监督学习时不存在外部教师,学习系统完全按照环境提供数据的某些统计规律来调节自身参数或结构(这是一种自组织过程),以表示出外部输入的某种固有特性(如聚类或某种统计上的分布特征)。无教师学习的训练数据集中,只有输入而没有目标输出,训练过程神经网络自动地将各输入数据的特征提取出来,并将其分成若干类。经过训练好的网络能够识别训练数据集以外的新的输入类别,并相应获得不同的输出。显然,无教师的训练方式可使网络具有自组织和自学习的功能。
3.再励学习(强化学习)
这种学习介于上述两种情况之间,外部环境对系统输出结果只给出评价信息(奖或惩)而不是给出正确答案。学习系统通过强化那些受奖的动作来改善自身的性能。
4.3 BP神经网络
4.3.1 BP算法
自1985年Rumelhart提出BP算法[16]以来,神经网络的研究和应用已经迅速发展并渗透到各个学科,神经网络算法已不再是只供研究,而在实际的生产中开始了广泛的应用。如:数据库系统的数据挖掘、产品的自动分捡系统的图像识别等。对应地在计算机辅助设计的软件开发中,神经网络算法的设计也越来越多。
神经网络以其快速的并行处理能力和其强有力的学习能力而获得越来越广泛的重视,其中应用最多的是BP神经网络。BP学习算法,即反向传播(back propagation)学习算法是一种有导师的示例学习算法。这种学习算法在模式识别领域中,尤其在字符识别的研究中被广泛使用。其原因是BP算法学习规则的坚韧性和学习能力很强,当给定模式与BP网络学会的模式很相似时,BP网络能很好的完成识别任务。
BP算法是一种有监督式的学习算法。其主要思想是:输入学习样本,使用反向传播算法对网络的权值和偏差进行反复的调整训练,通过误差的反向传播,使输出的向量与期望向量尽可能地接近,当网络输出层的误差平方和小于指定的误差时训练完成,保存网络的权值和偏差。
BP 算法由两部分组成:信息的正向传递与误差的反向传播。在正向传播过程中,输入信息从输入层经过隐含层逐层计算传向输出层,每一层神经元的状态只影响下一层神经元的状态。如果在输出层没有得到期望的输出,则计算输出层的误差变化值,然后转向反向传播,通过网络将误差信号沿着原来的连接通路反传回来,通过修改各层神经元的权值使得误差减小,直至达到期望目标。
4.3.2 BP网络的一般学习算法
BP网络是一种有监督的前馈运行的神经网络,它由输入层i、隐含层h、输出层k以及各层之间的节点的连接权所组成。它又分为正向和反向传播两种,以下对各层进行详细介绍。
1、 正向传播过程
输入层
输入值一般为样本各分量输入值,输出值一般等于输入值。
隐含层
对于节点j,其输入值
为其前一层各节点输出值
的加权和:
(4.1)
输出值
(4.2)
式中
称为激励函数或者作用函数。一般采用sigmoid函数:
(4.3)
式中
称为阙值,λ称为温度系数。
隐含层可为一层或者多层,但是随着隐含层的增多,网格的复杂程度也随之增加,学习速度减慢,另外网络的推导能力也有可能下降,即所谓的“over fitting”现象。网络隐含层以及节点数目的选取是BP网络学习算法有待解决的一个问题。
输出层
输出层的输入
与输出
与隐含层类似,分别为:
(4.4)
(4.5)
2、 反向传播过程
BP学习算法的误差函数一般定义为实际输出与期望输出的均方误差和。通过使误差函数最小化的过程不断的改变权重,完成从输入到输出的非线性映射。
设网络输入模式样本为
,期望输出为
,均方误差函数
为:
(4.6)
而对于所有的学习样本,系统的均方误差为:
(4.7)
为了达到学习目的,要根据误差函数来相应地调整网络间的连接权值。一般来说经典的BP学习算法采用最快速梯度下降法调整权值,每次调整的增量为:
(4.8)
式中0<η<1称为学习率。
从(4.8)式可推出下列连接权值的修正量公式
(4.9)
对于输出节点:
(4.10)
对于隐节点:
(4.11)
4.3.3 BP网络的设计
BP网络的设计主要包括输入层,隐层,输出层及各层之间的传输函数几个方面。
1、网络层数
大多数通用的神经网络都预先预定了网络的层数,而BP网络可以包含不同的隐层。对多层BP神经网络,隐层层数至少为1层或1层以上,每个隐层的神经元个数至少为1个或1个以上,否则与多层网络的命题矛盾而不成立。
2、输入层的节点数
网络的输入个数应等于应用问题的输入数,MATLAB的BP网络的建立是通过函数newff或newcf实现的.如图4.1所示的程序设计截图。
图4.1使用newff函数建立一个新的BP神经网络
3、网络数据的预处理[17]
预处理方法有归一化处理、标准化处理和主成分分析。常采用的是归一化处理,即将输入、输出数据映射到[-1,1]范围内,训练结束后再反映射到原数据范围。
4、输出层的节点数
输出层节点数取决于两个方面,输出数据类型和表示该类型所需要的数据大小。
5、隐层的节点数
根据经验,可以参考以下公式进行设计:
或者
(4.12)
(1)式中:n为隐层节点数; 为输入节点数; 为输出节点数;a为1~10之间的常数。
(2)改变n,用同一样本集训练,从中确定网络误差最小时对应的隐层节点数。
6、传输函数
BP网络中传输函数常采用S(sigmoid)型函数.在某些特定情况下,还可能采用纯线性(Pureline)函数。
7、训练方法及其参数选择[18]
net.trainParam.show= ; %显示训练结果的间隔步数
net.trainParam.epochs= ; %最大训练步数
net.trainParam.goal= ; %训练目标误差
net.trainParam.mu = ; %学习系数的初始值,Marquardt调整参数
net.trainParam.mu_dec= ; %学习系数的下降因子
net.trainParam.mu_inc= ; %学习系数的上升因子
net.trainParam.mu_max= ; %学习系数的最大值
net.trainParam.min_grad=;%训练中最小允许梯度值
如图4.2本例中所用参数。
图4.2本例所用参数
通过以上处理后,将得到的特征向量输入到设计好的神经网络进行测试,下面的图4.3和4.4分别给出了网络的某次训练过程及结果,由图可以看出结果还是很令人满意的。
图4.3 BP网络的训练过程
图4.4 BP网络的训练结果
4.4 BP学习算法的局限性与对策
BP学习算法解决了多层前馈网络的训练与非线性映射问题,在实际应用中具有重大意义,在应用BP学习算法的过程中,人们逐渐发现它存在的某些缺陷,存在局部极小值、学习速度慢、网络隐节点和初始权值的选取只能凭经验、新加入的样本要影响已经学完的样本,并且每个样本的输入样本的特征数目也要求必须相同;学习过程能否收敛,什么时候收敛已经学习后所生成的权重空间的分布状况等,这些至今还是一个未知数。
BP学习算法存在的局限性
BP学习算法存在的局限性总结如下:
(1)归纳能力
基于BP学习算法的神经网络具有较强的归纳能力。这里,归纳是指当用一组同类型的样本集训练时,BP网络能将一些不相关的信息忽略掉,而学习样本集中共同的特征,通过这样的学习,BP网络很容易记住了这一类型的样本。然而,BP学习算法对不同类型微小特征差异的样本缺乏足够的归纳能力。
(2)外推能力
和归纳能力相对,BP网络的外推能力是指BP网络对一类样本训练完后,对其它非训练样本测试其识别能力。实验结果表明,外推能力与训练样本的种类和数量有关。只有将各种不同类型的充足的样本训练后,才能对各种样本的测试达到较好的推广能力。
(3)学习速度
BP神经网络的学习过程是一种超大规模的反复的浮点数值运算过程,因此,无论从学习算法本身考虑,还是从使用的微机设备上考虑,学习速度一般是较慢的。
(4)收敛性
BP学习算法的收敛性至今没能用完整的理论来证明它。网络学习过程中极易陷入局部极小点。一旦网络的权重陷入一个极小点,无论是全局极小点还是局部极小点,学习均告终止。如果在该点的状态下所要求的问题解是正确的,那么,该点是局部的还是全局的极小点就显得不那么重要了。但若所求问题的解是不正确的,那么只有再次调整权值,直到找到另一个极小点对所求问题的解是正确时为止,即要逃离原来的局部极小点。
(5)解释能力
神经网络对自身解决问题的方式不能形成一个规范的推导过程。它通过学习所形成的“自我认识”对人来说是透明的。这对有导师训练的BP学习算法而言,大大阻碍了指导人与被指导对象的交流。
4.5 对BP算法的改进
经典的BP算法采用梯度下降法。当误差曲面为窄长型时,该算法在谷的两壁跳来跳去,影响了网络的收敛速度。最普通的改进方法为附加动量法,将公式(4.9)改为:
(4.13)
式中
称为动量因子。
利用附加的动量项可以起到平滑梯度方向的剧烈变化。更进一步可以在学习过程中动态地调整η和α的值,使η随系统总误差E不断的变化,以避免出现
W取值过小,尤其是在接近系统最小值的时候。
实验中发现,η越大,学习速度会越快,但过大时会引起振荡效应;而α取的过大可能导致发散,过小则收敛速度太慢;η取0.2~0.5,α取0.90~0.98时有较快的收敛速度。动态调整η和α值,收到良好效果。
根据优化理论还有很多种优化方法。这些方法一般都可以应用到改进BP算法中。例如同伦方法、梯度法、共轭梯度法以及牛顿法。事实证明采用较好的优化方法可以提高网络的收敛速度、避免陷入局部极小。寻求一种适合BP算法使用的新的优化算法也是一个很有价值的研究课题。
利用附加的动量项可以起到平滑梯度方向的剧烈变化。更进一步可以在学习过程中动态地调整η和α的值,使η随系统总误差E不断的变化,以避免出现
W取值过小,尤其是在接近系统最小值的时候。
实验中发现,η越大,学习速度会越快,但过大时会引起振荡效应;而α取的过大可能导致发散,过小则收敛速度太慢;η取0.2~0.5,α取0.90~0.98时有较快的收敛速度。动态调整η和α值,收到良好效果。
根据优化理论还有很多种优化方法。这些方法一般都可以应用到改进BP算法中。例如同伦方法、梯度法、共轭梯度法以及牛顿法。事实证明采用较好的优化方法可以提高网络的收敛速度、避免陷入局部极小。寻求一种适合BP算法使用的新的优化算法也是一个很有价值的研究课题。
第五章 系统的实现与结果分析
5.1 软件开发平台
5.1.1 MATLAB简介
MATLAB 是美国MathWorks公司出品的商业数学软件,用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simulink两大部分。
MATLAB是矩阵实验室(Matrix Laboratory)的简称,和Mathematical、Maple并称为三大数学软件。它在数学类科技应用软件中在数值计算方面首屈一指。MATLAB可以进行矩阵运算、绘制函数和数据、实现算法、创建用户界面、连接其他编程语言的程序等,主要应用于工程计算、控制设计、信号处理与通讯、图像处理、信号检测、金融建模设计与分析等领域。
MATLAB 的应用范围非常广,包括信号和图像处理、通讯、控制系统设计、测试和测量、财务建模和分析以及计算生物学等众多应用领域。附加的工具箱(单独提供的专用 MATLAB 函数集)扩展了 MATLAB 环境,以解决这些应用领域内特定类型的问题。
5.1.2 MATLAB的特点
(1) 此高级语言可用于技术计算
(2) 此开发环境可对代码、文件和数据进行管理
(3) 交互式工具可以按迭代的方式探查、设计及求解问题
(4) 数学函数可用于线性代数、统计、傅立叶分析、筛选、优化以及数值积分等二维和三维图形函数可用于可视化数据
(5) 各种工具可用于构建自定义的图形用户界面
(6) 各种函数可将基于MATLAB的算法与外部应用程序和语言(如 C、C++、Fortran、Java、COM 以及 Microsoft Excel)集成
5.1.3 使用MATLAB的优势
(1) 友好的工作平台和编程环境
(2) 简单易用的程序语言
(3) 强大的科学计算机数据处理能力
(4) 出色的图形处理功能
(5) 应用广泛的模块集合工具箱
(6) 实用的程序接口和发布平台
(7) 应用软件开发(包括用户界面)
5.2 系统设计思路
本设计主要分为三大步骤:第一阶段,图像预处理;第二阶段,特征提取;第三阶段,设计BP神经网络并对输入样本进行训练和测试。具体分为以下五步:
(1)对手写体数字图像进行预处理,包括去噪、二值化、归一化、细化等;
(2)对手写体数字图像进行小波分解,对分解的系数进行分析;
(3)特征提取,采用统计特征、结构特征和笔画特征提取,取得输入样本;
(4)构建BP神经网络并对样本数据进行学习和训练;
(5)对构建好的人工神经网络对性测试和分析。
5.3 系统流程图
该系统分为识别过程和训练过程,这两个过程又都包括图像预处理、特征提取和分类识别。如图5.1是本系统的流程图。
图5.1 系统流程图
5.4 MATLAB程序设计
本次设计使用MATLAB语言实现该系统,其用户界面分别介绍如下。
读入图像,这里有多组测试图片可以用来测试,选择其中一张,
读入图像的用户界面如图5.2所示。
图5.2 读入测试图片
然后用MATLAB 中图象处理工具箱读入bmp 文件,并将其转化为二值数据, 其中使用imread , im2double , rgb2gray ,mat2gray ,im2bw 等函数。之后取得单个的数字图像文件,使用imcrop 函数进行剪裁。
选取图片中的任意数字:比如5,如图5.3。
图5.3 选取数字5进行各种操作
经过平滑去噪、二值化、规范化、细化等过程预处理以后,识别出选取的数字,如图5.4。
图5.4 识别出数字5
5.5 实验数据及结果分析
实验数据部分综合了十张不同的测试图像,每张图像分别有五个0-9,并对每个数字进行识别,如表格5-5是实验数据的记录表。
表格5-5实验数据
数 字 0 |
数 字 1 |
数 字 2 |
数 字 3 |
数 字 4 |
数 字 5 |
数 字 6 |
数 字 7 |
数 字 8 |
数 字 9 |
|
识为0 |
40 |
1 |
2 |
2 |
1 |
1 |
3 |
2 |
2 |
3 |
识为1 |
1 |
40 |
1 |
0 |
2 |
0 |
0 |
4 |
2 |
1 |
识为2 |
2 |
1 |
35 |
3 |
1 |
3 |
1 |
3 |
2 |
1 |
识为3 |
0 |
1 |
0 |
34 |
0 |
4 |
2 |
2 |
1 |
3 |
识为4 |
1 |
2 |
1 |
2 |
29 |
1 |
1 |
1 |
3 |
2 |
识为5 |
1 |
0 |
3 |
3 |
2 |
37 |
2 |
0 |
1 |
2 |
识为6 |
3 |
0 |
0 |
1 |
7 |
2 |
36 |
0 |
1 |
2 |
识为7 |
0 |
3 |
5 |
1 |
0 |
1 |
0 |
35 |
0 |
2 |
识为8 |
0 |
1 |
1 |
2 |
0 |
1 |
3 |
1 |
37 |
2 |
识为9 |
2 |
1 |
2 |
2 |
3 |
0 |
2 |
2 |
1 |
32 |
正确 |
40 |
40 |
35 |
34 |
29 |
37 |
36 |
35 |
37 |
32 |
正确率 |
80% |
80% |
70% |
68% |
58% |
74% |
72% |
70% |
74% |
64% |
由表格可以看到,数字“0”和“1”的识别结果最好,都达到了 80%;其次,数字“2”,“5”,“6”“7”和“8”的识别精度也都达到70%以上;数字“4”的识别结果不理想,识别精度不到60%,4 被误识为 6的次数较多。所有测试样本的平均识别正确率为71%。
结 论
神经网络是性能良好的特征识别器,它与正确的特征提取方法相结合,会达到让人满意的识别效果。
本文对手写体数字识别的基本原理及方法作了介绍,设计的时候使用BP神经网络进行学习和训练,并用MATLAB工具实现了自由手写体数字识别系统。实验结果表明,基于所用结构模型和知识库的识别方法对规范手写体数字是可行的,也可以识别一定条件下的自由手写体数字。为了提高识别率和可靠性,除了要增强对噪声的滤除能力外,还要增大知识库,以解决细化中出现的结构畸变问题,这些都有待我们进一步的研究。
另外,针对 BP 网络收敛速度慢,计算量大等缺点,改进了网络的初始值,保证网络稳定快速收敛。还介绍了一种 BP 神经网络的改进训练算法,利用 MATLAB 神经网络工具箱提供的丰富的训练函数,对几种典型的 BP 网络训练算法的训练速度进行了比较。仿真结果表明本文提出的用于手写体数字识别的 BP 神经网络模型具有一定的识别能力,其算法可操作性强,只要相关参数选择得当,系统就能够得到较好的识别效果。本文的手写体数字识别正确率为71%。
今后工作展望:手写体数字的特征提取是一个非常复杂的问题,可以考虑先用比较适合于特征提取的自组织特征映射网络提取样本特征,然后再用 BP 神经网络完成分类,充分利用两种网络的优点可能达到更好的识别效果。
参 考 文 献
[1]Yang J M, Kao C Y, A robust evolutionary algorithm for training neural networks. Neural Computing and Application[M], 2001.10 214~230.
[2] Ciaccio E. J., Dunn S.M, Akay M, Binominal Pattern Recognition and interpretation Systems (Review of Applications), IEEE Engineering in Medicine and Biology Magazine[M],1994, 13 .2:269~ 273, 283.
[3] 吴佑寿,丁晓青. 汉字识别原理方法与实现[M].北京:高等教育出版社,1992.105~121.
[4] 张立明.人工神经网络的模型及其应用[M].上海:复旦大学出版社,1992.156~170.
[5] 蔡元明.神经网络识别手写体数字预处理后样本空间凸集性研究,中国科学院半导体所硕士学位论文[D].保存地点:华中科技大学图书馆,1995.6.
[6]崔屹.图像处理与分析--数学形态学方法及应用[M].北京: 科学出版社,2002.
[7] 金忠等.手写体数字有效鉴别特征的抽取与识别,计算机研究与发展,36(12),1999,1484~1489.
[8] 飞思科技产品研发中心. MATLAB6.5辅助图像处理.北京:电子工业出版社,2002.212~220.
[9] 飞思科技产品研发中心. MATLAB6.5辅助小波分析与应用.北京:电子工业出版社,2002.
[10] 胡小峰.四维科技.Visual C++/MATLAB 图像处理与识别实用案例精选.北京:人民邮电出版社,2004:32~35.
[11] MATLAB,信号处理的小波导引.北京:机械工业出版社,2002:58~59.
[12] 孙即祥等.模式识别中的特征提取与计算机视觉不变量.国防工业出版社,2001.9:115~140.
[13]黄心哗,王茂祥,富煌清,陆估人.基于结构分析的手写体数字识别算法.电子工程师[J],1999年第11期.
[14] Bernhard R. C,Shi Y,Evolving artificial neural networks,In: Proc of 1998 Int'l Conf. on neural networks and brain pp. PL5-PL13. Beijing,P. R. China,1998.
[15]Hu, J., Yan, H., A model-based segmentation method for handwritten numeral strings,Computer Vision and Image Understanding [N] ,70(3),1998,383~403.
[16] 从爽.面向MATLAB工具箱的神经网络理论与应用.中国科学技术大学出版社[M],2003: 19~35.
[17] 飞思科技产品研发中心,神经网络理论与MATLAB7实现.北京:电子工业出版社[M],2005: 42~51.
附 录
附录1 预处理
%% 数字识别 (I):Image Pre-processing
%% Manual Cropping
img = imread('sample.bmp');
imshow(img)
imgGray = rgb2gray(img);
imgCrop = imcrop(imgGray);
imshow(imgCrop)
imgLGE = imresize(imgCrop, 5, 'bicubic');
imshow(imgLGE)
imgRTE = imrotate(imgLGE, 35);
imshow(imgRTE)
imgBW = im2bw(imgLGE, 0.90455);
imshow(imgBW)
附录2
%% 数字识别 (II):Automating Image Pre-processing
I = imread('sample.bmp');
imshow(I)
pause;
Igray = rgb2gray(I);
imshow(Igray)
pause;
Ibw = im2bw(Igray,graythresh(Igray));
imshow(Ibw)
pause;
Iedge = edge(uint8(Ibw));
imshow(Iedge)
pause;
se = strel('square',2);
Iedge2 = imdilate(Iedge, se);
imshow(Iedge2);
pause;
Ifill= imfill(Iedge2,'holes');
imshow(Ifill)
pause;
[Ilabel num] = bwlabel(Ifill);
disp(num);
Iprops = regionprops(Ilabel);
Ibox = [Iprops.BoundingBox];
Ibox = reshape(Ibox,[4 50]);
imshow(I)
pause;
hold on;
for cnt = 1:50
rectangle('position',Ibox(:,cnt),'edgecolor','r');
end
附录3
%% 神经网络的设计与训练ining a Simple NN for
%% classification
I = imread('sample.bmp');
img = edu_imgpreprocess(I);
for cnt = 1:50
bw2 = edu_imgcrop(img{cnt});
charvec = edu_imgresize(bw2);
out(:,cnt) = charvec;
end
P = out(:,1:40);
T = [eye(10) eye(10) eye(10) eye(10)];
Ptest = out(:,41:50);
net = edu_createnn(P,T);
[a,b]=max(sim(net,Ptest));
disp(b);
附录4
%%图形界面
function varargout = charGUI(varargin)
% CHARGUI M- charGUI.fig
% CHARGUI, by itself, creates a new CHARGUI or raises the existing
% singleton*.
% H = CHARGUI returns the handle to a new CHARGUI or the handle to
% the existing singleton*.
% CHARGUI('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in CHARGUI.M with the given input arguments.
% CHARGUI('Property','Value',...) creates a new CHARGUI or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before charGUI_OpeningFunction gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to charGUI_OpeningFcn via varargin.
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help charGUI
% Last Modified by GUIDE v2.5 03-Jul-2008 17:55:35
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', m, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @charGUI_OpeningFcn, ...
'gui_OutputFcn', @charGUI_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before charGUI is made visible.
function charGUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to charGUI (see VARARGIN)
load data;
assignin('base','net',net);
% Choose default command line output for charGUI
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes charGUI wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = charGUI_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in pbLoad.
function pbLoad_Callback(hObject, eventdata, handles)
% hObject handle to pbLoad (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[, pathname] = uigetfile({'*.bmp';'*.jpg';'*.gif';'*.*'}, 'Pick an Image File');
S = imread([pathname,]);
axes(handles.axes1);
imshow(S);
handles.S = S;
guidata(hObject, handles);
% --- Executes on button press in pbSelect.
function pbSelect_Callback(hObject, eventdata, handles)
% hObject handle to pbSelect (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
S = handles.S;
axes(handles.axes1);
img_crop = imcrop(S);
axes(handles.axes2);
imshow(img_crop);
handles.img_crop = img_crop;
guidata(hObject, handles);
% --- Executes on button press in pbPreprocess.
function pbPreprocess_Callback(hObject, eventdata, handles)
% hObject handle to pbPreprocess (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
img_crop = handles.img_crop;
imgGray = rgb2gray(img_crop);
bw = im2bw(img_crop,graythresh(imgGray));
axes(handles.axes3);
imshow(bw);
bw2 = edu_imgcrop(bw);
axes(handles.axes4);
imshow(bw2);
handles.bw2 = bw2;
guidata(hObject, handles);
% --- Executes on button press in pbExtract.
function pbExtract_Callback(hObject, eventdata, handles)
% hObject handle to pbExtract (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
bw2 = handles.bw2;
charvec = edu_imgresize(bw2);
axes(handles.axes5);
plotchar(charvec);
handles.charvec = charvec;
guidata(hObject, handles);
% --- Executes on button press in pbRecognize.
function pbRecognize_Callback(hObject, eventdata, handles)
% hObject handle to pbRecognize (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
charvec = handles.charvec;
selected_net = get(handles.editNN,'string');
selected_net = evalin('base',selected_net);
result = sim(selected_net,charvec);
[val, num] = max(result);
set(handles.editResult, 'string',num);
% --- Executes on button press in pbNN.
function pbNN_Callback(hObject, eventdata, handles)
% hObject handle to pbNN (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
function editNN_Callback(hObject, eventdata, handles)
% hObject handle to editNN (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of editNN as text
% str2double(get(hObject,'String')) returns contents of editNN as a double
% --- Executes during object creation, after setting all properties.
function editNN_CreateFcn(hObject, eventdata, handles)
% hObject handle to editNN (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function editResult_Callback(hObject, eventdata, handles)
% hObject handle to editResult (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of editResult as text
% str2double(get(hObject,'String')) returns contents of editResult as a double
% --- Executes during object creation, after setting all properties.
function editResult_CreateFcn(hObject, eventdata, handles)
% hObject handle to editResult (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% --- Executes on button press in pbCrop.
function pbCrop_Callback(hObject, eventdata, handles)
% hObject handle to pbCrop (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
附录5 运行界面
%% Rearranging CHARGUI to Make it Resizable and Dockable
% This script reverse-engineers |charGUI| and rebuilds it in a way that is
% both resizable and dockable. It does so using |uipanel| and positioning
% with normalized units.
%% Create a New CHARGUI
% First, create a new instance of |charGUI|.
f = charGUI;
%% Cache the Major GUI Components
% Next, find the major GUI components: |axes|, |uipanel|, and |uicontrol|.
% Keeping references to these items will allow us to lay them out later.
% In the meantime, turn off their visiblity so that the steps taken below
% appear clearly in the GUI.
axs = findobj(f,'type','axes');
pans = findobj(f,'type','uipanel');
uis = findobj(f,'type','uicontrol');
set(axs,'visible','off');
set(pans,'visible','off');
set(uis,'visible','off');
%% Construct a New Layout Framework
% Use |uipanel| to create the framework for the new GUI layout. Divide the
% space into three portions using normalized units. The first, occupying
% the upper left-hand portion of the GUI, will contain the main axes. The
% second, occupying the right-hand quarter of the GUI, will contain the
% every |uicontrol|. The third, occupuying the bottom 30% of the GUI in
% the left-hand 75%, will contain the processing |axes|.
newpans = zeros(1,3);
for i = 1:3
newpans(i) = uipanel('parent',f,'units','normalized');
end
set(newpans(1),'position',[0 .3 .75 .7]);
set(newpans(2),'position',[.75 0 .25 1]);
set(newpans(3),'position',[0 0 .75 .3]);
%% Populate the First Panel
% By putting the main set of |axes| into a |uipanel|, it can be laid out
% relative to the panel, as opposed to the whole GUI. Use normalized
% units to make sure that the |axes| grow when the |uipanel| grows.
% Position it starting 10% up from the bottom and 10% right from the
% left-hand side of the GUI and have it occupy 80% of the horizontal and
% vertical |uipanel| space.
set(axs(1),'parent',newpans(1),'units','normalized',...
'position',[.1 .1 .8 .8]);
set(get(newpans(1),'children'),'visible','on');
%% Populate the Second Panel
% Parent the |uicontrol| items to the second |uipanel|. Maintain the
% use of characters units so that each |uicontrol| will not grow and shrink
% along with the |uipanel|. Instead, each will maintain the same size and
% placement.
set(uis,'parent',newpans(2));
newuipos = get(uis(1),'position');
newuipos(1:2) = [2 1];
set(uis(1),'position',newuipos);
newuipos = get(uis(3),'position');
newuipos(1:2) = [2 14];
set(uis(3),'position',newuipos);
newuipos(1:2) = [2 18];
set(uis(4),'position',newuipos);
newuipos(1:2) = [2 22];
set(uis(5),'position',newuipos);
newuipos(1:2) = [2 26];
set(uis(6),'position',newuipos);
newuipos(1:2) = [2 30];
set(uis(2),'position',newuipos);
newuipos(1:2) = [2 34];
set(uis(7),'position',newuipos);
set(get(newpans(2),'children'),'visible','on');
%% Populate the Third Panel
% Each processing |axes| are already contained within a |uipanel|, which
% merely needs to be positioned within one containing |uipanel|. Again,
% use normalized units so that these will grow and shrink with the
% containing |uipanel|.
%
% Also apply normalized units and new positions to the |axes| contained in
% the subpanels. Doing so will fill in the GUI space and allow us, as the
% GUI grows, to see more detail in the processing.
set(pans,'parent',newpans(3),'units','normalized');
set(pans(4),'position',[.01 .025 .23 .95]);
set(pans(3),'position',[.26 .025 .23 .95]);
set(pans(2),'position',[.51 .025 .23 .95]);
set(pans(1),'position',[.76 .025 .23 .95]);
set(axs(2:5),'units','normalized','position',[.05 .05 .9 .9]);
set(get(newpans(3),'children'),'visible','on');
%% Touch Up the GUI and Make it Resizable
% Put the finishing touches on the GUI. Apply the same background colors
% that exsited before to each new |uipanel| and remove the border. The
% |figure| can now be made resizable. Try docking it by setting its
% |windowstyle| property!
for i = 1:3
set(newpans(i),'backgroundcolor',get(pans(1),'backgroundcolor'),...
'bordertype','none');
end
set(f,'resize','on');