数字识别模式

第1章绪论

1.1数字识别概述

模式识别是六十年代初迅速发展起来的一门学科。由于它研究的是如何用机器来实现人(及某些动物)对事物的学习、识别和判断能力,因而受到了很多科技领域研究人员的注意,成为人工智能研究的一个重要方面。

字符识别是模式识别的一个传统研究领域。从50年代开始,许多的研究者就在这一研究领域开展了广泛的探索,并为模式识别的发展产生了积极的影响。

字符识别一般可以分为两类:1.联机字符识别;2.光学字符识别(Optical Chara- cter Recognition,OCR)或称离线字符识别。在联机字符识别中,计算机能够通过与计算机相连的输入设备获得输入字符笔划的顺序、笔划的方向以及字符的形状,所以相对OCR来说它更容易识别一些。但联机字符识别有一个重要的不足就是要求输入者必须在指定的设备上书写,然而人们在生活中大部分的书写情况是不满足这一要求的,比如人们填写各种表格资料,开具支票等。如果需要计算机去认识这些己经成为文字的东西,就需要OCR技术。比起联机字符识别来,OCR不要求书写者在特定输入设备上书写,它可以与平常一样书写,所以OCR的应用更为广泛。OCR所使用的输入设备可以是任何一种图像采集设备,如CCD、扫描仪、数字相机等。通过使用这类采集设备,OCR系统将书写者已写好的文字作为图像输入到计算机中,然后由计算机去识别。由于OCR的输入只是简单的一副图像,它就不能像联机输入那样比较容易的从物理特性上获得字符笔划的顺序信息,因此OCR是一个更具挑战性的问题。

数字识别是多年来的研究热点,也是字符识别中的一个特别问题,它是本文研究的重点。数字识别在特定的环境下应用特别广泛,如邮政编码自动识别系统,税表和银行支票自动处理系统等。一般情况下,当涉及到数字识别时,人们往往要求识别器有很高的识别可靠性,特别是有关金额的数字识别时,如支票中填写的金额部分,更是如此。因此针对这类问题的处理系统设计的关键环节之一就是设计出高可靠性和高识别率的数字识别方法。然而可以说还没有哪个数字识别器达到完美的识别效果。

在过去的数十年中,研究者们提出了许许多多的识别方法。按使用的特征不同,这些方法可以分为两类:基于结构特征的方法和基于统计特征的方法。结构特征通常包括圆、端点、交叉点、笔划、轮廓等,统计特征通常包括点密度的测量、矩、特征区域等,一般来说,两类特征各有优势。例如,使用统计特征的分类器易于训练,而且对于使用统计特征的分类器,在给定的训练集上能够得到相对较高的识别率,而结构特征的主要优点之一是能描述字符的结构,在识别过程中能有效地结合几何和结构的知识,因此能够得到可靠性较高的识别结果。

1.2神经网络在数字识别中的应用

神经网络模型用于模拟人脑神经元活动的过程。其中包括对信息的加工、处理、存储和搜索等过程,它具有如下基本特点:

1、神经网络具有分布式存储信息的特点。它存储信息的方式与传统的计算机的思维方式是不同的,一个信息不是存在一个地方,而是分布在不同的位置。网络的某一部分也不只存储一个信息,它的信息是分布式存储的。神经网络是用大量神经元之间的连接及对各连接权值的分布来表示特定的信息。因此,这种分布式存储方式即使当局部网络受损时,仍具有能够恢复原来信息的优点。

2、神经网络对信息的处理及推理的过程具有并行的特点。每个神经元都可以根据接收到的信息作独立的运算和处理,然后将结果传输出去,这体现了一种并行处理。神经网络对于一个特定的输入模式,通过前向计算产生一个输出模式,各个输出节点代表的逻辑概念被同时计算出来。在输出模式中,通过输出节点的比较和本身信号的强弱而得到特定的解,同时排出其余的解。这体现了神经网络并行推理的特点。

3、神经网络对信息的处理具有自组织、自学习的特点。神经网络中各神经元之间的连接强度用权值大小来表示,这种权值可以事先定出,也可以为适应周围环境而不断地变化,这种过程称为神经元的学习过程。神经网络所具有的自学习过程模拟了人的形象思维方法,这是与传统符号逻辑完全不同的一种非逻辑非语言的方法。

在神经网络研究的历史进程中,它在模式识别方面的应用一直是最活跃和最成功的领域。神经网络与它在模式识别中的应用是息息相关,密不可分的。几乎可以说,神经网络模式识别研究的发展史贯穿了整个神经网络的研究历程。

目前, 随着计算机的迅速发展,性能价格比的不断提高,模式识别技术己经从理论探讨为主发展到大量的实际应用,人们将更多的注意力开始转向那些用于语音,图像、机器人以及人工智能等的模式识别实际问题。解决这些问题的关键是需要进行复杂而庞大的实时数据处理,而现有计算机的存贮容量及计算复杂性的局限,使得真正实时化的应用受阻。

这种面向实时应用的模式识别问题促使人们开始将并行处理的神经网络应到模式识别,而神经网络模式识别技术又将模式识别实时应用推进了一大步,数字识别就是这种应用的一个很重要的领域。

数字识别是一项极具研究价值的课题,随着神经网络和模糊逻辑技术的发展,人们对这一问题的研究又采用了许多新的方法和手段,也使得这一古老的课题焕发出新的生命力.目前国际上有相当多的学者在研究这一课题,它包括了模式识别领域中所有典型的问题:数据的采集、处理及选择、输入样本表达的选择、模式识别分类器的选择以及用样本集对识别器的有指导的训练。人工神经网络为数字识别提供了新的手段。正是神经网络所具有的这种自组织自学习能力、推广能力、非线性和运算高度并行的能力使得模式识别成为目前神经网络最为成功的应用领域。

1.3数字图像处理的应用

数字图像处理主要研究的内容有以下几个方面:

1、图像变换。由于图像阵列很大,直接在空间域中进行处理,涉及计算量很大。因此,往往采用各种图像变换的方法,如傅立叶变换、沃尔什变换、离散余弦变换等间接处理技术,将空间域的处理转换为变换域处理,不仅可减少计算量,而且可获得更有效的处理(如傅立叶变换可在频域中进行数字滤波处理)。目前新兴研究的小波变换在时域和频域中都具有良好的局部化特性,它在图像处理中也有着广泛而有效的应用。

2、图像编码压缩。图像编码压缩技术可减少描述图像的数据量(即比特数),以便节省图像传输、处理时间和减少所占用的存储器容量。压缩可以在不失真的前提下获得,也可以在允许的失真条件下进行。编码是压缩技术中最重要的方法,它在图像处理技术中是发展最早且比较成熟的技术。

3、图像增强和复原。图像增强和复原的目的是为了提高图像的质量,如去除噪声,提高图像的清晰度等。图像增强不考虑图像降质的原因,突出图像中所感兴趣的部分。如强化图像高频分量,可使图像中物体轮廓清晰,细节明显;强化低频分量可减少图像中噪声影响。图像复原要求对图像降质的原因有一定的了解,一般讲应根据降质过程建立“降质模型”,再采用某种滤波方法,恢复或重建原来的图像。     

4、意义的特征部分提取出来,其有意义的特征有图像中的边缘、区域等,这是进一步进行图像识别、分析和理解的基础。虽然目前已研究出不少边缘提取、区域分割的方法,但还没有一种普遍适用于各种图像的有效方法。因此,对图像分割的研究还在不断深入之中,是目前图像处理中研究的热点之一。

5、图像描述。图像描述是图像识别和理解的必要前提。作为最简单的二值图像可采用其几何特性描述物体的特性,一般图像的描述方法采用二维形状描述,它有边界描述和区域描述两类方法。对于特殊的纹理图像可采用二维纹理特征描述。随着图像处理研究的深入发展,已经开始进行三维物体描述的研究,提出了体积描述、表面描述、广义圆柱体描述等方法。

6、图像分类(识别)。图像分类(识别)属于模式识别的范畴,其主要内容是图像经过某些预处理(增强、复原、压缩)后,进行图像分割和特征提取,从而进行判决分类。图像分类常采用经典的模式识别方法,有统计模式分类和句法(结构)模式分类,近年来新发展起来的模糊模式识别和人工神经网络模式分类在图像识别中也越来越受到重视。

在数字识别中分类识别之前要利用数字图象处理和计算机图形学的知识进行图象的预处理以便进行下面的特征提取以及识别。图象的预处理包括二值化、图象的增强、图象的锐化以及图象的分割等。

1.4 本论文所做的工作

本论文在数字识别及预处理方面做了如下工作:

1、介绍了数字识别广阔的应用前景和常用的识别方法,通过分析指出数字识别的难点在于无法建立精确的数学模型和做出简单可行的识别系统。

2、本文第二、三章介绍了人工神经元网络基本原理和它的BP学习算法,然后论述了模式识别的方法和有关概念,指出了神经网络之所以能够用于数字识别的内在机理和独特优势。

3、第四章分析了常规数字识别的基本步骤,并指出数字识别的关键步骤是预处理和特征提取。详细了图像预处理的步骤及BP神经网络在数字识别中的应用。

第2章模式识别及人工神经网络概述

2.1模式识别简述

在观察各种事物或接受各种客观现象时,人们总是不断地进行模式识别。各种具有相似的特征又不完全相同的事物和现象组成不同的类别。在同一类别中,事物和现象不尽相同,但它们总是表现出某些方面的相近之处。例如,每个人写出来的数字“8”可能千差万别,但它们的共同之处在于,它们都属于数字,“8”这个范畴。也就是说,这些千差万别的数字“8”的共性是它们具有相同的属性特征。

人的思维可以对初次见到的事物进行分类。比如,即使人们初到一个城市,也可以轻易地辨认出“街道”、“房屋”、“汽车”这样的事物。同样,看到另外一种写法的“8”,人们仍然可以清楚地知道它的含义。正是人脑的这种推广能力,使得人们利用见到过的有限事物和现象,形成各种事物类别的概念。这些有限的、个别的事物和现象就可以称为模式,而整个类别的现象和事物则可以称为模式类,或者简称为类。人们根据所见模式的特性,将其划归为某一类的过程,实际上就是模式识别的过程。

模式识别这个词既可以是指人对事物的,一个分析、描述、判断和识别的过程,也可以是指利用计算机对某些物理对象进行分类的这门学科。模式和集合的概念是分不开的,模式可以看作是集合论中的元素,而类则可以看作是子集。

2.2 人工神经网络模式识别

具体的模式识别是多种多样的,如果从识别的基本方法上划分,传统的模式识别大体分为统计模式识别和句法模式识别,在识别系统中引入神经网络是一种近年来发展起来的新的模式识别方法。尽管引入神经网络的方法和引入网络的结构可以各不相同,但都可称为神经网络模式识别。而且这些识别方法在解决传统方法较难处理的某些问题上带来了新的进展和突破,因而得到了人们越来越多的重视和研究。

人工神经元网络(Artificial Neural Network)简称神经网络,是基于日前人们对自然神经系统的认识而提出的一些神经系统的模型,一般是由一系列被称为神经元的具有某种简单计算功能的节点经过广泛连接构成的一定网络结构,而其网络连接的权值根据某种学习规则在外界输入的作用下不断调节,最后使网络具有某种期望的输出特性。神经网络的这种可以根据输入样本学习的功能使得它非常适合于用来解决模式识别问题,这也是神经网络目前最成功的应用领域之一。

神经网络模式识别的基本方法是,首先用己知样本训练神经网络,使之对不同类别的己知样本给出所希望的不同输出,然后用该网络识别未知的样本,根据各样本所对应的网络输出情况来划分未知样本的类别。神经网络进行模式识别的一般步骤如图2-1所示,分为如下几个部分。

图 2-1 神经网络模式识别基本构成

1、样本获取

这一步骤主要是为了得到一定数量的用于训练和识别的样本。

2、常规处理

其作用相当于传统模式识别中的数据获取和常规处理两步的功能。即通过对识别对象的有效观测、进行采样量化,获得一系列数据,再经过去除噪声、加强有用信息等工作获得尽量逼真的原始数据。通过这一步骤,得到了样本的原始表达。

3、特征变换

在原始样本表达的基础上,进行适当的变换,得到适合神经网络进行识别的样本的特征表达。以上两步构成了神经网络模式识别中的预处理过程。

这一步骤与传统模式识别的特征提取选择的位置很相似,不同的是,神经网络可以对原始样本直接进行处理,因此这种变换在神经网络模式识别中不象传统模式识别的特征提取选择那样必不可少,神经网络对预处理的要求与传统模式识别对特征提取选择的要求也有所不同。

4、神经网络识别

根据识别对象和研究问题的不同,选用不同的网络结构并采用适当的学习算法,用已知样本作为训练集对神经网络进行训练,使其网络连接的权值不断调整,直到网络的输出特性与期望的相符合。

训练过程结束以后,网络相当于一个固定的映射器,新的输入样木(测试样本)通过网络映射到不同的类别。

神经网络能够应用于模式识别,关键在于它具有一般数学模型所不具有的诸多优点。

1、分布存储和容错性

一个信息不是存储在一个地方,而是按内容而分布在整个网络上,网络某一处不是只存储一个外部信息,而每个神经元存储多种信息的部分内容。网络的每部分对信息的存储有等势作用。这种分布式存储算法是存储区与运算区合为一体的。在神经网络中,要获得存储的知识则采用“联想”的办法,即当一个神经网络输入一个激励时,它要在己存的知识中寻找与该输入匹配最好的存储知识为其解。当然在信息输出时也还要经过一种处理。而不是直接从记忆中取出。这种存储方式的优点在于若部分信息不完全,就是说或者丢失或者损坏甚至有错误的信息,它仍能恢复出原来正确的完整的信息,系统仍能运行。这就是网络具有容错性和联想记忆功能,自然是表现出较强的鲁莽性。人的大脑的容错性是它的一种重要的智慧形式。

2、大规模并行处理

人工神经元网络在结构上是并行的,而且网络的各个单元可以同时进行类似的处理过程。因此,网络中的信息处理是在大量单元中平行而又有层次地进行,运算速度高,大大超过传统的序列式运算的数字机。虽然每个神经元的信息传递(神经脉冲)速度是以毫秒计算的,比普通序列式计算机要慢很多,但是人通常能在1秒内即可作出对外界事物的判断和决策、这就是能神奇地完成所谓“百步”决策。这按照现有传统的计算机及人工智能技术目前还是做不到的。

3、自学习、自组织和自适应性

学习和适应要求在时间过程中系统内部结构和联系方式有改变,神经元网络是一种变结构系统,恰好能完成对环境的活应和对外界事物的学习能力。神经元之间的连接有多种多样,各神经元之间连接强度具有一定的可塑性,相当于突触传递信息能力的变化,这样,网络可以通过学习和训练进行自组织以适应不同信息处理的要求。

神经元网络是大量神经元的集体行为,并不是各单元行为的简单的相加,而表现出一般复杂非线性动态系统的特性。如不可预测性、不可逆性、有各种类型的吸引子(信息正是“存储”在定点吸引子)和出现混沌现象等。

正是由于神经网络具有这些特点,所以可以处理一些环境信息十分复杂、知识背景不清楚和推理规则不明确的问题。例如语音识别和识别、医学诊断以及市场估计等,都是具有复杂非线性和不确定性对象的控制。在那里,信源提供的模式丰富多彩,有的互相间存在矛盾,而判定决策原则又无条理可循。通过神经元网络学习(按照学习法则),从典型事例中学会处理具体事例,给出比较满意的解答。

2.3 人工神经网络的基本原理

2.3.1神经细胞以及人工神经元的组成

神经系统的基本构造单元是神经细胞,也称神经元。它和人体中其他细胞的关键区别在于具有产生、处理和传递信号的功能。每个神经元都包括三个主要部分:细胞体、树突和轴突。树突的作用是向四方收集由其他神经细胞传来的信息,轴突的功能是传出从细胞体送来的信息。每个神经细胞所产生和传递的基本信息是兴奋或抑制。在两个神经细胞之间的相互接触点称为突触。简单神经元网络及其简化结构如图2-2所示。

从信息的传递过程来看,一个神经细胞的树突,在突触处从其他神经细胞接受信号。这些信号可能是兴奋性的,也可能是抑制性的。所有树突接受到的信号都传到细胞体进行综合处理,如果在一个时间间隔内,某一细胞接受到的兴奋性信号量足够大,以致于使该细胞被激活,而产生一个脉冲信号。这个信号将沿着该细胞的轴突传送出去,并通过突触传给其他神经细胞.神经细胞通过突触的联接形成神经网络。

(1)细胞体(2)树突(3)轴突(4)突触

图2-2 简单神经元网络及其简化结构图

人们正是通过对人脑神经系统的初步认识,尝试构造出人工神经元以组成人工神经网络系统来对人的智能,甚至是思维行为进行研究:尝试从理性角度阐明大脑的高级机能。经过几十年的努力与发展,己涌现出上百种人工神经网络模型,它们的网络结构、性能、算法及应用领域各异,但均是根据生物学事实衍生出来的。由于其基本处理单元是对生物神经元的近似仿真,因而被称之为人工神经元。它用于仿效生物神经细胞最基本的特性,与生物原型相对应。

人工神经元的主要结构单元是信号的输入、综合处理和输出,其输出信号的强度大小反映了该单元对相邻单元影响的强弱。人工神经元之间通过互相联接形成网络,称为人工神经网络。神经元之间相互联接的方式称为联接模式,相互之间的联接度由联接权值体现在人工神经网络中,改变信息处理过程及其能力,就是修改网络权值的过程。

目前多数人工神经网络的构造大体上都采用如下的一些原则:

1、由一定数量的基本单元分层联接构成;

2、每个单元的输入、输出信号以及综合处理内容都比较简单;

3、网络的学习和知识存储体现在各单元之间的联接强度上。

2.3.2人工神经元的模型

神经元是人工神经网络的基本处理单元,它一般是一个多输入/单输出的非线性元件。神经元输出除受输入信号的影响外,同时也受到神经元内部其它因素的影响,所以在人工神经元的建模中,常常还加有一个额外输入信号、称为偏差(bais),有时也称为阈值或门限值。一个具有r个输入分量的神经元如图2-2所示。其中,输入分量

通过与和它相乘的权值分量

相连,以

的形式求和后,形成激活函数f()的输入。激活函数的另一个输入是神经元的偏差b,权值Wj和输入分量的矩阵形式可以由W的行矢量以及P的列矢量来表示:

         

  

                                      (2.1)

2.4神经网络的结构与学习规则

2.4.1神经网络的联接形式

人脑中大量的神经细胞都不是孤立的,而是通过突触形式相互联系着,构成结构与功能十分复杂的神经网络系统。为了便于从结构出发模拟智能,因此必须将一定数量的神经元适当地联接成网络,从而形成多种神经网络模型。

通常所说的神经网络的结构,主要指它的联接方式。神经网络按照拓扑结构属于以神经元为节点,以及节点间有向连接为边的一种图,其结构大体上可分为层状和网状两大类。

层状结构的神经网络是由若干层组成,每层中有一定数量的神经元,相邻层中神经元单向联接,一般地同层内的神经元不能联接,网状结构的神经网络中,任何两个神经元之间都可能双向联接。

下面介绍几种网络结构:

1、前向网络

前向网络通常包含许多层,如图2-3所示为3层网络。这种网络特点是只有前后相邻两层之间神经元相互联接,各神经元之间没有反馈。每个神经元可以从前一层接收多个输入,并只有一个输出送给下一层的各神经元。三层前向网络分为输入层、隐层和输出层。在前向网络中有计算功能的节点称为计算单元,而输入节点无计算功能。

2、反馈网络

反馈网络从输出层到输入层有反馈。即每一个节点同时接收外来输入和来自其它节点的反馈输入,其中也包括神经元输出信号引回到本身输入构成的自环反馈,如图2-4所示。这种反馈网络每个节点都是一个计算单元。

图2-3前向网络                          图2-4反馈网络

3、相互结合型网络

相互结合型网络如图2-5所示,它是属于网状结构。构成网络中各个神经元都可能相互双向联接,所有的神经元既作输入,同时也用于输出。在这种网络中,如果在某一时刻从神经网络外部施加一个输入,各个神经元一边相互作用,一边进行信息处理,直到使网络所有神经元的活性度或输出值,收敛于某个平均值为止作为信息处理的结束。

图2-5网状结构网络                   图2-6混合型网络

4、混合型网络

上述的前向网络和相互结合型网络分别是典型的层状结构网络和网络结构网络,介于这两种网络中间的一种联接方式,如图2-6所示,在前向网络的同层间神经元有互联的结构,称为混合型网络。这种在同一层内的互联,目的是为了限制同层内神经元同时兴奋或抑制的神经元数目,以完成特定的功能。

2.4.2神经网络的学习和训练

人脑中一个典型神经元通过许多树突的精细结构,收集来自其它神经元的信息,神经元又通过轴突发出电活性脉冲。轴突分裂上千条分支,在每条分支末端,通过突触的结构把来自轴突的电活性变为电作用,从而使与之相连的各种神经元的活性受到抑制或兴奋。

当一个神经元收到兴奋输入,而兴奋输入又比神经元的抑制输入足够大时,神经元把电活性脉冲向下传到它的轴突,改变轴突的有效性,从而使一个神经元对另一个神经元的影响改变,便发生了学习行为。因此,可以认为神经网络学习的本质特征在于神经细胞特殊的突触结构所具有的可塑性连接,而如何调整连接权重就构成了不同的学习算法。

神经网络按学习方式分为有教师学习和无教师学习两大类。

1、有教师学习

为了使神经网络在实际应用中解决各种问题,必须对它进行训练,就是从应用环境中选出一些样本数据,通过不断地调整权值矩阵,直到得到合适的输入输出关系为止,这个过程就是对神经网络的训练过程,这种训练的过程需要有教师示范,提供训练数据,又称样本数据。在训练过程中又需教师的监督,故这种有教师的学习又称监督式学习。

有教师学习方法虽然简单,但是要求教师对环境和网络的结构应该比较熟悉,当系统复杂,环境变化时,就变得困难。为了适应环境变化就要重新调整加权值,这样,当学习到新知识的同时,也容易忘掉已学过的旧知识,这一些是有教师学习方法的缺点。

2、无教师学习

无教师学习的训练数据集中,只有输入而没有目标输出,训练过程神经网络自动地将各输入数据的特征提取出来,并将其分成若干类。经过训练好的网络能够识别训练数据集以外的新的输入类别,并相应获得不同的输出。显然,无教师的训练方式可使网络具有自组织和自学习的功能。

2.4.3神经网络的学习规则

人类高度发展的智能,主要是通过学习获得的。要模拟人脑神经系统的学习功能,必须使得人工神经网络具有学习功能。因此,有关神经网络的学习算法的研究一直占有特殊的地位。

神经网络中常用的有四种学习规则:

1、联想式学习Hebb规则。

2、误差传播式学习Delta学习规则。

3、概率式学习。

4、竞争式学习。

第3章前馈多层网络结构及其BP学习算法

3.1前向多层网络的结构及BP学习算法

前向网络是目前研究最多的网络形式之一。如图3-1所示,在此模式中,共有三层神经元,每层由若干节点组成,第k层的每个节点与第k+1层的每个节点连接。第一层为输入层;第二层为中间层,又称为隐层;最后一层为网络的输出层。其结构可以表示为:n-q-m网络,n为输入层节点数,q为隐含层节点数,m为输出层节点数。每个连接对应一个权值,通过修正这些权值“学习”或“训练”网络,从而修正输入到输出映射的网络函数。

输入单元的活性(状态)代表输入此网络中的原始信息。每个隐单元的活性取决于输入单元的活性及该输入单元与隐单元之间联接权值。同样输出单元的行为取决于隐单元的活性及隐单元和输出单元之何的权值。

上述网络的信息传播是由输入单元传到隐单元,最后传到输出单元。这种含有隐层的前向网络有一个重要特征,即隐单元可以任意构成它们自身的输入表示,输入单元和隐单元间的权值决定每个隐单元何时是活性的,因此,借修改这些权值,一个隐单元可以选择它代表什么。

                     图3-1 BP网络结构

BP(Back Propagation)算法是误差反向传播算法,网络的学习由四部分组成:

  1. 输入模式由输入层经向输出层的模式顺传播过程。
  2. 网络的希望输出与网络实际输出之间的误差信号,由输出层经中间层向输入层的误差逆传播过程。
  3. 由模式顺传播与误差逆传播反复交替进行的网络记忆训练过程。
  4. 网络趋向收敛即网络的全局误差趋向极小值的学习收敛过程。

3.2 BP网络误差反向传播学习算法的基本思想

为了研究神经网络是怎样从经验中学习的,我们应该首先向网络提供一些训练例子,并可以通过下述方法,能教会一个三层前向网络完成某个特定的任务。其方法步

骤如下:

(1)向网络提供训练例子,包括输入单元的活性模式和期望的输出单元活性模式;

(2)确定网络的实际输出与期望输出之间允许的误差;

(3)改变网络中所有联接权值,使网络产生的输出更接近于期望的输出,直到满足确定的允许误差。

下面以网络识别数字为例说明上述方法。比如使用64个传感器组成传感器阵列,每个传感器记录一个数字的一小部分面积内是否有笔写的墨迹存在。因此,网络需要64个输入单元(每个传感器一个),10个输出单元(每种数字一个)和许多隐单元。为便于传感器记录每种数字,网络应在适当的输出单元中产生高活性,并在其它输单元中产生低的活性。

为了训练此网络,提供一幅某个数字的图像并把10个输出单元的实际活性和期望活性加以比较,然后计算误差,将实际活性与期望活性差值的平方定义为误差。其次,改变网络中所有联接权值以减少误差。针对每种数字的多种不同图像重复训练,直到网络能对每个数字正确地归类为止。

实现上述训练过程的关键是必须改变的每个权值,且其变化量应正比于权值改变时误差的变化率,此量称权值的误差导数,简记为EW。但是,要对EW的有效计算是十分复杂棘手的问题。如果采取稍许扰动每个权值,并观察误差如何变化,这种方法效率太低,因为要求对每一个权值都要单独加扰动。

1979年前后,正在哈佛大学攻读博士的Werbos发明了一种高效的计算EW的方法,即误差反向传播算法,只因发明后多年来未受重视,也没有充分体会到它的用处,直到1985年Rumelhart和Parker两人各自再次发现该算法后才得以推广。

首先研究网络的单元是线性时误差反向传播的算法.

首先计算改变一个单元活性水平时误差的变化率EA,再计算每个权值的误差导数EW。对于输出单元,EA只是实际输出和期望输出间的差值。为计算在输出层前面一层的一个隐单元的Eel,首先辨别该隐单元和与它相联的那些输出用数字识别的BP神经网络单元间的所有权值,然后把这些权值乘以这些输出单元的EA并求和,此和值即为所选定的隐单元的EA。将所有隐单元的EA计算出后,可用类似的方法计算其它层的Eel值,计算的顺序恰好与活性专播过网络路径相反的方向逐层进行,故称为误差反向传播算法。计算出一个单元的EA后,再计算该单元每条输入联接的EW,EW是EA和经过该输入联接活性的乘积。

对于非线性单元,反向传播算法还包括另外一步,即在反向传播前,必须把FA变换为EI,EI是一个单元所收到的总输入变化时误差的变化率。

综上所述,为了训练前向网络完成某项任务,必须调整每个单元的权值,即减小期望输出与实际输出之间的误差,为此必须计算每个权值变化时误差的变化,即误差导数EW,而反向传播算法是一种确定EW使用的最有效的方法。误差反传学习算法一种改进算法可以用图3-2表示,它添加了多个隐层.

                图3-2误差反向传播学习算法网络结构图

在如图3.1所给出的前向多层BP网络,设单元j、i分别是输出层和它前面一层中的一个单元。为计算输出单元j的活性,首先计算总加权输入

,即

   

                                                 (3.1)

其中Y是前面一层中第1个单元的活性水平,Wij是第i个单元和第j个单元的联接权值.

其次,为了利用上述求得的总加权输入Xi来计算Yi,必须使用某个函数来激活输入与输出函数。

一般常用S型函数: 

                                   (3.2)

在确定了所有输出单元的活性之后,利用下式计算网络的误差:

            

                                   (3.3)

式中Yj是输出层中第j个单元的活性水平,dj是第j个单元的期望输出

概括起来反向传播算法包括下列四个步骤:

(1)一个输出单元活性改变时的误差导数EA,即实际活性与期望活性的差值:

           

                                     (3.4)

(2)计算一个单元所接受总输入变化时的误差导数EI,EI实际上等于上述步骤(1)的结果乘以一个单元的总输入变化时其输出的变化率,即

          

                   (3.5)

(3)计算一个与输出单元联接权值改变时的误差变化率EW。

         

                           (3.6)

不难看出

等于上述步骤(2)的结果

,乘以与该输出单元相连接单元i的活性水平

(4)计算前面一层中一个单元活性改变时的误差变化率,前面一层中一个单元活性的改变会影响与该单元相连接的所有输出单元的活性。因此,为了计算对误差总的影响,把对各输出单元的所有单独影响相加.

         

                       (3.7)

运用步骤(2)和(4),可把一层单元的EA变成前面一层单元的FA,为了得到期望的前面各层的EA。可重复此计算步骤。当得到一个单元的EA后,可用步骤(2)和(3)来计算作用于它的输入联接上的EW。

3.3 BP算法的计算机实现流程

BP算法的计算机实现按下述步骤进行:

(1)初始化,对所有权值赋以随机任意小值,并对阀值设定初值;

(2)给定训练数据集,即提供输入向量x和期望输出y:

(3)计算实际输出y

   

        (3.8)

其中f函数为Sigmoid函数:

(4)调整权值,按误差反向传播方向,从输出节点开始返回到隐层按下式修正权值.

        

                                   (3.9)

其中

为大于0的增益,

为节点j的误差,

的计算根据节点j的形式不同,由下式分别计算:

        

                      (3.10)

(5)返回(2)步重复,直至误差满足要求为止。

3.4激活转移函数

激活函数(Activation transfer function)是一个神经元及网络的核心。网络解决问题的能力与功效除了与网络结构有关,在很大程度上取决于网络所采用的激活函数。

激活函数的基本作用是:

(1)控制输入对输出的激活作用;

(2)对输入、输出进行函数转换;

(3)可将可能无限域的输入变换成指定的有限范围内的输出。

在这个设计的BP神经网络中我们选择的是S型(Sigmod型)激活函数。

S型激活函数将任意输入值压缩到(0,1)的范围内,如图3-3所示。

   带有偏差的对数S型曲线                       带有偏差的双曲S型函数

                        图3-3 S型激活函数

此种激活函数常用对数或双曲正切等一类S形状的曲线来表示,如对数S型激活函数关系为:

                                  (3.12)

而双曲正切S型曲线的输入输出函数关系为:

                                 (3.13)

S型激活函数具有非线性放大增益,对任意输入的增益等于在输入/输出曲线中该输入点处的曲线斜率值。当输入由无穷增大到零时,其增益由0增至最大,然后当输入由0增加至正无穷时,其增益又由最大逐渐降低至0,并总为正值。利用该函数可以使同一神经网络既能处理小信号,也能处理大信号。因为该函数的中间高增益区解决了处理小信号的间题,而在伸向两边的低增益区正好适用于处理大信号的输入。

一般地,称一个神经网络是线性或非线性是由网络神经元中所具有的激活函数的线性或非线性来决定的。

第4章数字识别系统的设计与实现

4.1系统的流程

几种常用的解决问题的软件开发方法,一种是对问题追述的方法,也就是从问题的结果分析起一步一步找到问题的源头。另一种解决问题的方法是寻找容易解决的或者是己经解决的相关的问题转而应用到解决当前的问题来。但是当前软件开发中更为流行和常用的方法是逐步求精法。这种方法是一种由顶向下的方法,也就是由一般到特殊的方法,它的基本思想是将原始的问题分割成若干个子问题,子问题较整个大问题容易解决。

本文程序设计采用逐步求精法,将整个系统问题分割成若干个子问题来做,主要包括图像数据输入模块GetDIB()、二值化模块Threshold()、平滑滤波模块Smooth()、分割模块divide()、字符切分模块CharSegment()、字符识别模块CharRecognition()。首先分别对每个模块进行单元测试分析和模块测试,然后再组合成系统,进行系统测试。

图 4-1 系统逻辑模型流程图

此图为系统逻辑模型流程图,其中细箭头代表程序的进程,整个程序就是按上图所示流程编写的。

4.2系统的软件实现

面对琳琅满目的各种开发环境和开发软件,我没有使用MATLAB,最主要的原因是VC对内存的掌控很好,这对运算量极大的BP算法有着关键的作用,要知道,设计一个BP网络不难,难的是设计一个高效,高速,稳定的BP网络,这就需要我们来对内存进行优化,对算法进行最大程度的发掘.否则设计出来的BP算法将是不健壮、不稳定、不实用的.一定要注意在设计时尽可能多的释放掉不使用的内存.

Visua1C++6.0,是Microsoft公司开发的Visual Studio集成开发环境中功能最为强大、代码效率最高的开发工共。利用VisualC++6.0可以两种方式编写Win32应用程序,一种方式是基于Windows API的C编程方式,另一种是基于MFC的C++编程方式。C编程方式是传统的、久经考验的编程方式,代码的效率较高,但开发难度与开发的工作量都很大。而C++编程方式代码运行效率相对较低,其开发难度小、开发工作量小、源代码效率高,尤其Microsoft基础类库(Microsoft Foundation Class Library,MFC)为用户提供了Windows95/NT环境下面向对象的程序开发界面,它提供了大量预先编写好的类及支持代码,用于处理多数标准Windows编程任务,因此大大简化了Windows应用程序编写工作。

MFC类库的优越性表现在以下几个方面:

1、MFC几乎完整地封装了WindowsAPI函数。包括窗口函数、消息、控件、菜单、对话框、GDI对象、对象链接,以及多文档界面等。

2、MFC支持多线程,所有的应用至少有一个线程,这个线程由CWinApp类的对象创建,被称为“主”线程口为方便多线程编程,MFC还提供了同步对象类。

3、MFC库提供了自动消息处理功能。MFC库自动处理每一个Windows消息,且每一条Windows消息被直接映射到一个进行处理的成员函数。

4.2.1 BMP图像格式简介

程序中能够进行处理的是灰度图像。灰度图是只含亮度信息,不含色彩信息的图像,就像平时看到亮度由暗到明变化连续的黑白照片一样。因此要表示灰度图,就需要把亮度值进行量化,通常划分成0到255共256个级别,0最暗(全黑),255最亮(全白),并将所有灰度图像转化为DIB(Device-Independent Bitmap设备无关位图)位图文件格式。

位图(BMP)文件中DIB的结构由四部分组成:第1部分为位图文件头BITMAPFILEH -EADER,指定文件为BMP文件类型,并且指定了从文件头到实际位图数据的偏移字节数;第二部分为位图信息BITMAPINFOHEADER,其中说明了位图包含的基本信息,如大小,宽度,高度,颜色位数,水平和垂直分辨率等;第三部分调色板(Palette)保存颜色信息;第四部分就是实际的图像数据。由于DIB位图能独立的保存固有的图像信息,能在不同的系统中重现其图像,故成为Windows环境中的基本图像格式。由MFC中没有设计一处理DIB位图的类,因此,利用Visual C++进行DIB位图编程时只能使用“非面向对象”的方法,即直接调用Win32 SDK的有关API函数,这是一个很大的缺陷,弥补的最好方法就是定义一个处理DIB位图的专用类,比如一个名为CDib的类,在其中封装必需的DIB数据成员和处理函数。

但是在构建CDib类时会遇到许多的困难,因为Win32SDK没有提供多少直接处理DIB位图的API函数,仅支持一些重要的DIB访问,在实际应用时很不够,必须定义一套完整的DIB处理函数。但是Win32 SDK中的DIB API函数是定义DIB处理函数集的基础,因此,还是要分析Win32 SDK中的DIB API函数,如表4.1所示。

从这些函数中可以看出它们能完成DIB位图的一些最基本的功能,如能申请到内存,完成DIB位图的构造,能缩放显示DIB于显示器和打印机上,直接从磁盘文件中读入位图,返回该句柄,能设置和获取位图的颜色表。在构造自己的CDib类时,也要以这些函数和功能为基础。

表4-1 Win32 SDK中的DIBAPI函数

函数

功能

GetDIBits

从DDB中获取位图的图象位,用于将DDB转换为DIB格式

SetDIBits

设置DIB位图的图象位,用于将DIB转换为DDB形式

CreateDIBitmap

用指定的DIB来创建DDB,并用DIB信息初始化位图的图象位

SetDIBitsToDevice

直接将DIB位图的图象位输出到设备,用于显示DIB

StretchDIBits

将DIB位图映射输出到设备的一个矩形区域,位图可能被缩放

CreateDIBSection

创建一个可直接写入的DIB

GetDIBColorTable

获取DIB的颜色表

SetDIBColorTable

设置DIB的颜色表

4.2.2 CDib类的构造

一、CDib类设计的目标

面向对象设计的重点是类的设计,而不是对象的设计,如果将对象比作房子,那么类就是房子的设计图纸。对于C++程序而言,设计孤立的类比较容易,难的是正确设置其基类及派生类。

1、功能

根据对DIB操作的分析,以及参照CBitmap的功能设计,CDib类的基本操作功能应该包括如下:

(1)多种形式的构造函数,包括创建空DIB,从DIB句柄创建,从DIB数据块指针创建及从屏幕或显示创建等。

(2)DIB文件的读写操作。

(3)DIB的显示和缩放显示。

(4)提供DIB的空间、颜色和格式特征等信息。

(5)DIB格式转换和调色板操作。

(6)能获取DIB位图数据的句柄并且生成DIB数据的拷贝。

2、父类

由于MFC中已有一个支持DDB操作的CBitmap类,因此容易想到以CBitmap类作为基类派生出CDib类。但是这样做有诸多的不适,首先,CBitmap类是为DDB的操作而设计的,其中没有处理DIB的功能,故CDib类不能从中继承任何可用的功能;其次,CBitmap类是从CGdiObject中派生出来的,CBitmap类以及它从CGdiObject类继承来的数据成员和功能函数对CDib来说都是不合适的,也是多余的。此外,CBitmap类没有提供有效的文件操作机制,而DIB主要是一种“外部”位图,即它主要以文件形式进行存储和交换,所以CDib类应该能很好的处理文件操作。

MFC中的CObject类是MFC中其他大多数类的基类。它不但提供许多有用的特性,还包括对文件串行化的支持,运行时的类信息和对象诊断的输出等。如果从CObject类来派生,则可以继承该类的这种特性。另外,CObject类具有最低限度的成员数据和函数,从CObject类派生的类所花的代价是最低的,因此,采用CObject类作为CDib类的基类是很合理的。

3、数据成员

数据成员很少,只有四个,都定义为公有变量public:

HDIB mhDib            //DIB位图句柄

CPalette *m_pPalette //位图调色板类成员对象指针

CBitmap * m_pBitmap  //bitmap类成员对象指针

VVin32 SDK使用句柄来表示操作内存对象,因此,这里也定义了一个DIB句柄来表示DIB的内存数据块:

# define HDIB HANDLE

HDIB 定义为存储BITMAPINFO结构和位图位数数据块的内存句柄,用GlobalLock锁定HDIB得到DIB数据块的地址指针,并可将该指针强制为LPBITMAPINF()或LPBITMAPINFOHEADER来使用,如

HDIB hDIB

LPBITMAPINFO lpbi;

LPBI TMAPINFOHEADER Ipbih;

Lpbi = (LPBITMAPINFO)G lobalLock(HDIB):

Lpbih = (LPBITMAPINFOHEADER)lp bi;

二、CDib类成员函数

以下介绍的Win32SDKAPI函数和CDib类的数据成员是砖石,现在可以开始构筑CDib类的成员函数也即DIB处理类的根基了,将定义的DIB处理函数分为以下几类:初始化函数类,属性函数类,显示函数类,操作函数类,调色板函数类。初始化函数类用来创建DIB,读入DIB数据,保存DIB文件和释放DIB内存空间等;属性函数是为了方便得到DIB的空间、颜色和图像数据方面的信息如图像的高度,宽度,数据块地址等;操作函数类定义了对DIB文件的各类实际操作和变换,这个类的函数可以改写DIB的数据所以是个核心函数类;调色板函数类完成对调色板的操作。DIB处理函数集的各个函数的名称和功能说明如表4-2所示:

表4-2 DIB处理函数集各个函数

函数类型

函数名称

功能

CreateDIB

创建一个空的DIB

CreateDefaultDIB

用当前的系统调色板创建一个空的DIB

DestroyDIB

释放DIB内存块

LoadDIB

从DIB文件装载DIB数据

SaveDIB

将DIB存到文件中

ReadDIBFile

读DIB文件到内存中

BytesPerLine

获取DIB每行所占的字节数

DIBlockSize

获取DIB数据块的大小

DIBHeight

获取DIB的高度

DIBWidth

获取DIB宽度

DIBNumColors

获取DIB的颜色数

DIBBitsCount

获取DIB的图象颜色位数

FindDIBBits

获取DIB数据块的地址(指针)

PaletteSize

获取DIB调色板的颜色表项数

DIBToDIBSection

将DIB数据块转换为DIBSELECTION

DIBSectionToDIB

将DIBSELECTION转换为DIB数据块

ConvertDIBFormat

修改DIB的格式

BitmapToDIB

将DDB转换为DIB

ChangeBitmapFormat

修改DDB的格式

DIBToBitmap

将DIB转换为DDB

ChangeDIBFormat

基于当前的系统调色板修改DIB的格式

Threshold

图象二值化

CharSegment

提取后的图象字符切分

Smooth

图象平滑

CharUniform

字符图象规格化

4.2.3程序设计相关内容介绍

1、首先建立一个用户界面的菜单。菜单项具备三个关键字段:ID,Caption(标题)和Prompt(提示)。每个菜单项所对应的ID是唯一的,Caption字段中包含实际显示在菜单中的文本,Prompt字段是用户“浏览”某个菜单项时希望显示在窗口底端状态栏中的文本。

MFC使用框架窗口类从应用程序资源中创建几个用户界面元素。MFC默认的菜单项是属于CMmainFrame类的,名称为IDR_MAINFRAME.

创建一个菜单资源后,下一步的运行ClassWizard,为各个菜单项创建代码,ClassWizard将各个菜单项作为一个由C++类表示的独立用户界面元素。对于各个菜单项,必须确定它们都应该分别由哪些类处理,然后确定是否需要为COMMAND菜单消息,UPDATE_COMMAND_UI菜单消息编写代码。在系统中设置了新类CChildview,子窗口菜单由此新类来处理。对应的代码都写入了文件CChildView.cpp,而其对应的算法函数写在文件mydiblib.h中,字符识别函数(Code Recognize)在文件BP.h中。

2、VC应用中很重要的一点是要学会如何调试程序,程序如此庞大如果不回调试程序,哪里出了错是很难找到的。要学会用断点来调试程序。VC++集成调试程序的两个重要特征是将断点插入到程序代码中的能力以及逐步执行(一次执行一条指令)程序代码的能力。

在代码中放置断点的最简单方式是将源代码窗口中的文本光标移动到希望放置断点的位置然后按F9设置此断点。Visual Studio在相应的行左边放置一个大红点来表示断点。

对于简单断点来说有两点是很重要的。首先,可以在源文件内的任意位置设置断点,如注释行,括号等,然而,当在注释行、括号等行设置断点后VC++并不执行编译。其次,VC++允许在Diassembly窗口内设置断点。

既可以启用断点,也可以禁用断点。当程序中寻找活动断点,同时程序以Debug(调试)模式执行时,Breakpoints对话框在该断点旁边显示对号。如果单击断点旁边这一对号,则断点被禁用。Visual Studio将被禁用的断点以空心红圈的形式显示在源代码窗口中。

除了使用断点外,还可以使用Debug菜单上的Break选项随时中断程序执行。然而,这样的中断从性质上讲是异步的,经常在一系列嵌套的的系统函数内中断程序,在这种情况下,可以使用Debug菜单上的Step Out(步出)选项,从系统函数中走出来,直到到达代码中的可标示位置。

Debug菜单中的很多分步命令都有快捷键,可简化程序的执行。下表列出了Debug菜单上Step命令的快捷键。

                 表4-3 单步执行命令的快捷键

命令

快捷键

Step Over

F10

Run to Cursor(运行到光标处)

Ctrl+F10

Step Into(步进到)

F11

Step Out(步出)

Shift+F11

4.3数字识别中的图像预处理

神经网络为数字识别提供一个强有力的手段。目前,在神经网络模式识别中根据对输入样本的表达方式的选择有下面两大类:一类是直接将数字图像经数值化处理之后得到的像素点原始样本作为神经网络的输入;另一类则是对这种原始像素点构成的原始输入样本再作进一步的预处理或变换。虽然,在某些情况下,人们采用第一类样本表达获得了较好的识别结果,但这种输入方式,通常使得网络分类器结构的复杂程度大大增加,所以,对原始样本进行预处理,已成为神经网络模式识别成功的一个很重要的方面。

对于数字的预处理,人们己作了许多工作,但归根结底有下面几步:

首先是将数字转化为n*n像素点矩阵形式,再经二值化处理,可以得到原始的输入表达方式。接下来,对原始样本表达进行一些常规变换,包括平滑、锐化、规格化和细化。而本文是通过大量的样本训练网络,以达到预期的识别率。

4.3.1 数值化

数字识别时,首先将印在纸上的数字经过光电扫描产生模拟信号,再通过模数转换变成表示灰度值的数字信号输入计算机。纸张薄厚、洁白度、光洁度、书写力度和笔划质量都要造成字形的变化,产生污点、飞白、断笔、交连等干扰。因此,一般由扫描得到的数值化的字符还需要多种进一步的处理。

4.3.2 二值化

二值化处理是将数字图像转化为由0和1表示的值像素矩阵形式,最简单也是最原始的作法是将整个数字所在区域用n*n网格划分,然后将数字笔划通过的网格内填1,不通过的网格内填0,这样就将整个数字变为一个由二值构成的矩阵。而在采用光电扫描仪对数字进行扫描输入时,通常是将数字转换为带灰度值的数字信号输入计算机。因而,二值化的工作不再是简单的笔划通过与否。

在本设计中是先将256色位图转化为对应灰度值的灰度图,再将灰度图转化为二值黑白图象.

设像素点(i,j)的灰度为g(i,j)。有划的部分g(i,j)小,白背景部分g(i,j)大。二值化可以通过设定灰度阈值来完成,即当g(i,j)值比预定阈值大,看成背景,以0表示;否则看成笔划,以1表示。这样,经过二值化,各点重新表示为:

                         (4.1)

二值化的关键在于阈值T的选择。考虑到各个样本数字的灰度范围的差别,可以采用不同的阈值进行处理。本设计中二值化选择的阈值为250.常用于文字识别的阈值选择方法有整体阈值二值化、局部阈值二值化和动态阈值二值化等。根据数字的特点和扫描得到的数字图像的灰度差别,可以分别用上述不同确定阈值的方法进行二值化。

4.3.3 平滑

实际获得的图像在形成、传输、接受和处理的过程中,不可避免地存在着外部干扰和内部干扰,如光点转换过程中敏感元件灵敏度的不均匀性,数字化过程的量化噪声,传输过程中的误差以及人为因素等,均会使图像质量变差,使图像模糊。因此,消除噪声,恢复原始图像是图像处理中的一个重要内容。图像平滑的目的有两个:改善图像的质量和抽出对象的特征。

平滑的办法有中值滤波,均值滤波等很多方法,本设计选择的平滑技术是中值滤波法。

中值滤波是一种对干扰脉冲和点状噪声有良好抑制作用,而对图像边缘能较好保持的非现行图像增强技术。在一维形式下,中值滤波器是一个含有奇数个像素的滑动窗口,经排序后,窗口像素序列为

v=(L-1)/2,L为窗口长度,Fi即为窗口像素的中值滤波输出。记做

Med{*}表示取窗口中值。如一窗口长度为5,像素灰度分别为{20,10,30,15,25},则

若灰度级为30的像素为椒盐噪声(表现为黑图像上的白点,白图像上的黑点),在经过中值滤波后即被消除。

一维中值滤波的概念很容易推广到二维。这时取某种形式的二维窗口,将窗口内像素排序,生成单调二维数据序列{Fjk}.类似于一维,二维中值滤波被输出G(j,k)为

                                                (4.2)

一般来说,二维中值滤波器比一维滤波器更能抑制噪声。二维中值滤波器的窗口形状可以有多种,如线状,方形,十字形,圆形,菱形等(见图4-1)。不同形状的窗口产生不同的滤波效果,使用中必须根据图像的内容和不同的要求加以选择。从以往的经验看,方形或圆形窗口适宜于外廓线缴长的物体图像,十字形窗口优选与有尖顶角物体的图像。

          

图4-1 中值滤波器常用窗口

使用中值滤波器滤除噪声的方法有多种,且十分灵活。一种方法是先使用小尺寸窗口,后逐渐加大窗口尺寸,直到中值滤波器的坏处多于好处为止。另一种方法是一维滤波器和二维滤波器交替使用。此外还有叠代操作,就是对输入图像重复进行同样的中值滤波,直到它不再有变化为止。

中值滤波具有很多重要特性。

1、对离散阶跃信号,斜升信号不产生影响,连续个数小于窗口长度一半的高

                      图4-2 中值滤波示例

(a)阶跃(b)斜坡(c)单脉冲(d)双脉冲(e)三脉冲(f)三角形

离散脉冲将被平滑,三角函数的顶部平坦化(见图4-2)

2、令C为常数,则

     

                           (4.3)

3、中值滤波后,信号频谱基本不变。

4.3.4 锐化

图像的锐化处理主要用于增强图像中的轮廓边缘,细化以及灰度跳变部分,形成完整的物体边界,达到将物体从图像中分离出来或将表示同一物体表面的区域检测出来的目的。它是早期视觉理论和算法中的基本问题,也是中期和后期视觉成败的重要因素之一。与图像的平滑处理一样,图像的锐化也有很多处理方法,如针对平均或积分运算使图像模糊,可逆其道而采取微分运算,使用高通滤波器优化高频分量,抑制低频分量,提高图像边界清晰度等。

在设计中我选择使用了梯度锐化法.

对图像函数F(j,k),其在点(j,k)上的梯度定义为矢量

      

                                            (4.4)

G(j,k)的幅度为

                                     (4.5)

在后面的讨论中,均以上式为基础。现在约定把G[F(j,k)]叫做梯度,而不再说G[F(j,k)]是 G[F(j,k)]的幅度。

对离散图像而言,可用差分近似表示上式,一种常用的近似关系式是:

              (4.6)

为便于编程和提高运算精度,在某些场合可进一步简化为:

                   (4.7)

还有一种罗伯特梯度的算子,表达式是:

         (4.8)

对应的绝对值表达式是:

              (4.9)

(4.7)式和(4.8)式中各因子之间的关系分别如图 (a)(b)所描述。对照此图是很容易记住梯度差分表达式的。(4.7)式是沿水平轴和垂直轴两个方向的微分和,(4.8)是取正反旋转45度两个方向的微分的和。

    

         (a)水平梯度锐化法                   (b)罗伯特锐化法

图4-3  二维梯度的两种差分算法

知道了梯度G[F(j,k)]后,如何确定锐化输出G(j,k)呢?下面提供了几种思路:

1、直接以梯度值代替

          G(j,k)=G[F(j,k)]                                         (4.10)

这种方法直截了当,简单。但是F(j,k)均匀的区域,因梯度值G[F(j,k)]很小(极端情况下甚至为0),会表现出暗的特性,这在有些场合是不适宜的。

2、辅以门限判断

                           (4.11)

该方法基本上不破坏图像背景,又可增强图像边缘。

3、给边缘规定一个特定的灰度级,即

        

                        (4.12)

4、给背景规定特定的灰度级

       

                           (4.13)

5、二值图像

        

                          (4.14)

梯度是向量,各向同性,梯度方向对应与F(j,k)最大变化率方向上,即

         

                               (4.15)

梯度幅度比例于相邻像素的灰度级差值。在灰度陡变区域,梯度值大;在灰度相似区域,梯度值小;在灰度级为常数的区域,梯度为0。熟悉梯度的这些性质,根据不同的目的选择不同的算法,就能获得满意的锐化效果。

4.3.5 字符切分

数字识别常用于邮政编码的自动识别和支票的检验等。在这些应用中,给出的数字往往是互相牵连,并且常带有覆盖相交叉,所以为了获得可以进行识别的输入样本表达,必须进行数字之间的分离,消除不必要的记号和符号。经过文字切分得到的一个个独立的样本,可以用于进一步的处理。

通常可以依据两种原则进行分割。一是依据各个象素点的灰度不连续性进行分割;一是依据同一区域具有相似的灰度(或组织特性)这一特征,寻求不同区域之边界。前者称为基于点相关的分割技术,后者称为基于区域相关的分割技术。

本设计中选择使用基于灰度阈值的全局阈值化方法.

这是一种最常用、同时也是最简单的分割方法,它特别适用于对象和背景占据不同灰度级范围这类图像。此时,我们只要选取一个适当的灰度级阈值,然后将每个象素灰度和它进行比较。超过阈值的重新分配以最大灰度(例如255),低于阈值的分配以最小灰度(例如0),那么,我们就可以组成一个新的二值图像,并成功地把对象从背景中显露出来。在分割之前进行背景平滑和噪声消除,常常能改善分割的性能。

4.3.6 规格化

由于样本数字大小不一,为了便于提取数字特征,需要对样本进行尺寸大小规一化,或者说是将数字的长度和宽度都调整到充满整个n*n的网格之中。

4.3.7 细化

在传统的模式识别中,对于数字的特征提取往往是从字形结构的提取入手。因而人们认为在二值化的字符图像中,对识别有价值的字符特征主要集中在字符的轮廓或者骨架上。基于这种认识,在经过以上几个步骤的处理,得到干净、平滑、规范的样本集合之后,往往要进行细化。即将字符中的粗细不等的笔划变换成只有一层像素点构成的统一的笔划。

细化的基本原理都是从字的边界开始逐层移去黑点,直到寻找到一个集合,此集合与其边界相重合,这种方法被称为脱壳算法。关于细化及快速细化的算法有许多,比如快速细化算法QA,Rutorit算法(简称RA),Hildith算法(简称HA)等。

经过上面几个步骤的预处理变换,则可以获得一种简单像素点输入样本表达。对传统的识别系统,这种样本不能直接进行识别,以上的步骤只是为特征提取选择打下基础。而对于神经网络识别系统,这种简单样本表达可以直接输入进行模式识别。但是,这种简单的原始二值表达式在代表数字时有下面几点不足:

1、样本维数很大,而中间许多特征不一定有用;

2、没有将那些真正反映数字特点的特征突出出来;

3、对于不同数字的外围或边缘及主干特征并没有考虑进去,这样对一些有相似部分的数字容易出现误识。

由于上面三方面的原因,在神经网络模式识别中,我们要用带污染的输入量去训练神经网络,使其具有一定的抗干扰能力,这样对所要识别的数字,能达到更好的识别率。

4.4 BP网络在数字识别中的应用

BP算法的流程图如下图所示。

Y

                              N

N

                                                         Y

  图4-4 BP算法流程图

BP算法在数字识别中的应用流程图:

                     图4-5 BP算法在数字识别中的应用

4.4.1 BP神经网络的设计

将要识别的目标是从0到9的10个数字字符。每个字符被分成8*8的小块进行数字化,分别用一个向量来表示。10个含64个元素的输入向量被定义为一个输入向量矩阵,向量代表某个数字,其相应有数的位置值为1,而其他位置值为0。共有两类这样的数据作为输入:一类是在理想的状态下的信号;另一类是随机方式生成含有噪声的信号。如图4-6所示。

图4-6 理想信号(上) 含有噪音的信号(下)

网络通过输出一个具有10个元素的输出向量来区分这些数字字符,例如字符1对应的向量,其第一个位置的元素值为1,而随后位置的元素值都是0。确定好输入输出后可进行网络结构的设计。第1层为输入层,根据以待识别的数据分析可确定神经网络输入层有64个节点;第2层为隐含层,一般依靠经验和尝试的方法来确定节点数目,第3层为输出层,由目标输出为含有10个数据的向量可知该层有10个节点。

选择了开发环境就要设计网络。设计训练一个神经网络能够识别10个数字字母的网络,意味着每当给训练过的网络一个表示某一数字的输入时,网络能够正确地在输出指出该数字,那么很显然,该网络记忆住了所有10个数字。神经网络的训练应当是有监督地训练出输入端的10组分别表示数字0到9的数组,能够对应出输出端0到9的具体的位置。首先必须将每个数字进行数字化处理,以便构造输入样本。即首先要选择一种编码方式.在这里可以采用行编码和列编码,但经过大量的试验表明,这两种编码方式的抗干扰性能不佳。我最终选择的还是点阵直接0-1编码方式.比如,对于数字0,可以编码为:

00111110

00100010

00100010

00100010

00100010

00100010

00100010

00111110

这样很容易确定该BP网络的输入为64维.

当数字数据混入噪声时,可以看作是对0,1数据进行简单的随机反转.比如说,要加入7%的噪声,那就可以对4个0或者1进行反转,翻转哪一个这里是随即的.

经过干扰后0的编码为:

00111110

00100010

00100010

00100110

00100010

00100010

00111011

00111110

图中,斜体部分就是噪声.

另外一个很重要的需要考虑的因素是:所要设计的网络应当具有抗干扰能力,即设计出的网络应当能够处理嗓声。具有在由一定不规范的输入情况下辨识出正确的数字输入的能力。将干扰嗓声进行数字化处理后即变成具有平均值为0--0.2 之间变化的随机值。

接下来来确定输出层的神经元个数.在输出层,因为0-9共10个数字,最简单就是确定10个输出层.所以确定输出层有10 个神经元。

遵循一般的,我在隐层中使用了处处可微分的Sigmoid函数.Sigmoid函数已经在第三章中介绍过,这里不在赘述。

4.4.2 BP神经网络的实现

设计了BP神经网络,有64个输入层,10个输出层,激活函数使用Sigmoid函数。接下来就要确定网络的具体参数以实现最终的结果。

隐层神经元数目的确定,是BP算法设计的关键, 一般来说,在做类似于函数逼近的课题时,隐层的神经元越多,则逼近就越精确.但对于当前的这个模式分类的题目,隐层神经元的数目必须要适当的选取,即不能过多也不能过少,如果隐层的神经元过多,一来会大大的加大训练时间,二来,虽然神经元的增多可以更加精确的描述分类判别的空间的界限,但同时,也造成网络的容错能力下降。这对于我们当前这个0-9数字识别是极为不利的.当然,神经元数目过少的时候,又无法满足分类的要求.编程证明,当隐层神经元数目超过25的时候,网络的训练时间将无法忍受,同时抗噪声能力大大降低;当神经元数目低于5时,系统误差无法收敛到满意的值,又造成识别率过低。 

经过反复的试验测定,对比,我认为隐层的神经元的数目为8-15为佳。小于8个神经元的时候,网络输出误差就太大了,大于15个神经元的时候,识别率又过低。

系统误差是系统进行训练的目标。当系统的输出误差小于这个允许的误差的时候即停止训练。误差选择过大,将造成系统识别率过低;误差选择过小,会大大延长训练时间,是一种浪费。这里,也要通过多次的比较分析得到最佳的允许误差。

训练步长的选择也是BP网络设计的关键所在. 训练步长过长,则可能造成算法无法收敛;步长过短,一来加大了训练时间,二来很容易陷入所谓的局部极小值。

4.5 识别系统运行的结果

本系统软件是基于VC++6.0为开发平台下采用文档/视图结构来构建的,便于将数据的管理和显示隔离开来,其界面如下图4-7。能完成图像预处理、训练网络、字符识别等等。识别前先要确定归一化的长度和宽度,还要设定BP训练网络的参数,界面如图4-8、4-9所示。

图4-6 识别的界面

                        图4-7 归一化界面

                      图4-8 网络参数设置框

4.6 系统设计中遇到的问题与结果分析

1、数字图像规格化中如何确定规格化后数字的长宽取值是一个重要的问题。若长宽取得过小,规则化后的字符图像容易变形;相反取得过大,则使得后期的模板匹配和神经网络的特征提取量增加,另外长宽还要满足一定的比例。在设计中我选择的长宽比例为2:1。

2、数字图像识别网络中如何确定网络隐层个数也是一个重要的问题。隐层个数取的不对就可能训练不出来,导致识别结果也不正确。在设计中我选择10个隐层不变。

3、图像的去噪滤波问题。噪声在图像中不可避免,整个系统中有几次需要对图像进行降噪处理,例如二值化处理后,字符图像切分之前的降噪处理等。针对不同的情况采用了不同降噪的方法,如二值化后为了消除大量的斑点噪声而采用数学形态学的运算一方面完成降噪处理另一方面有利于后期定位分割处理。

4、参数的设置问题。识别结果总是不尽理想,由于参数设置的不同,结果总是有差异,经总结设置的误差越小,相关系数越小,训练样本的次数越多,当识别数字时的结果就越正确。当系数设置不好时,如误差过小,或相关系数过小,会导致训练时间过长或者网络训练陷入死循环,训练不出来。由于这是一个10类数字区分问题,最终决定使用十个隐层,允许误差在0.001-0.2之间,训练步长设定在0.01-0.3之间.

5、训练网络的问题。在数字识别时,要先训练网络,但系统中网络的训练不能一次到位,基本上训练一次网络之后最进的几次识别精度比较高,当识别几次之后,精度就在不断下降。这是一个未解决的问题。

总之,这个系统的识别结果有的时候不是很稳定,如不同的数字设置的参数就要不同,不能用同一个参数对所有的数字都达到很高的识别精度。但系统总的识别正确率在90%左右。这个系统还有很多不完善的地方,还有待于利用更好的算法进行改进。

4.7 系统设计的调试与心得

1、这是我第一次采用面向对象编程,心里感触颇多,也第一次真正体会到VC++功能的强大,用户界面设计简单高效,强大的类库支持,调试功能的强大,它采用断点技术动态跟踪程序的运行,极大地方便了程序员及时了解内存变化情况、变量值现况及每个语句对变量所产生的影响,其单步运行方式便于程序员及时准确的发现某些潜伏性的错误并现场更正。

2、提高程序效率。程序的效率包括两个方面一是时间效率,另一个是空间效率。程序的时间效率是指运行速度,空间效率是指程序占用内存或者外存的状况。提高程序效率先要优化数据结构和算法,在优化执行代码,在本程序中构造CDib类封装数据成员和成员函数使得操作DIB位图简捷明了。有时候时间效率和空间效率可能对立,此时应当分析哪个更为重要,做出适当的折衷。如有时需要多花费些内存来提高性能,同时不要一味地追求程序的效率,应当在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率。

3、编程的规范化。这包括命名和程序书写的规范。命名规范是由于Windows的程序一般很长,容易忘记所有变量的含义,为了帮助记忆,Windows中有个约定叫做匈牙利表示法(Hungarian notation).该命名规则的主要思想是“在变量和函数名中加入前缀以增进人们对程序的理解”。例如所有字符变量前均加ch前缀,若是整型变量则追加i的前缀。程序中不要出现标识符完全相同的局部变量和全局变量,容易使人误解等,也要尽量避免名字中出现数字编号。程序书写版式虽然不会影响程序的功能,但会影响可读性,程序的版式追求清晰、美观,是程序风格的重要构成因素。

4、面向对象程序设计的优势。C++是一种面向对象程序语言主要有封装性(Encapsulation)、继承性(Inheritance)、多态性(Polymorphism)等特点。封装把数据与操作结合成一体,使程序结构更加紧凑,同时避免了数据紊乱带来的调试与维护的困难;继承增强了软件的可扩充性,并为代码重用提供了强有力的手段;多态性使程序员在设计程序时可以对问题进行更好的抽象,以设计出实用性和维护性俱佳的程序,这些都显示了强大的优越性。

5、敢于尝试。没有任何一个程序员从刚开始设计程序时就万事精通,程序完美无缺,都是在不断修改错误的基础上不断进步的。刚开始按照流程图系统设计时,设计的切入点都找不到,将所有的东西都罗列起来,一团乱麻,一切都由摸索开始的。先从小的程序做起,一点点的做大,思维就会越来越开阔。有时候一个错误会困扰我很长时间,只有不断的想新方法去尝试最终都会得到解决,经验就在一次次克服错误中不断丰富。

第5章数字识别的发展与应用

数字识别有着极为广泛的应用前景,这也正是它受到世界各国的研究工作者重视的一个主要原因。下面我将介绍基于数字识别的应用系统的特殊要求,以及一些以数字识别技术为基础的典型应用。

5.1 基于数字识别的应用系统的特殊要求

尽管数字识别与一般的文本(如:汉字,英文等)识别同属于光学识别(OCR)的大范畴,从应用的角度出发,数字识别系统有很多特殊的要求:

1、识别精度要达到较高的水平

在一般的文本识别中,信息的冗余较大,有充分的上下文信息,因而对识别的精度要求不是十分高96-99%就足够了。而在数字识别中,由于没有上下文关系,数据中的每一位数字都至关重要(试想:在财务报表中,把40,000元认成90,000元,从字符的角度仅认错了一个数字,但对用户而言,这是一个绝对不能容许的错误)。一般来说这类实用系统的精度至少应在99.9%以上。前面己经提到,高性能的自由数字识别是一个很困难的问题,至今为止还没有什么方法能与人的辨识能力相比,那么在目前的技术水平下,为了达到高精度,必须满足如下要求:

(1)要求书写者用规定的字型认真填写,避免使用某些容易造成混淆的变体。这个限制对用户可能是很不方便的,因为这意味着书写速度的降低和书写习惯的改变,但从整体上,系统识别水平将有大幅度的提高,能很大程度上提高系统的运行效率。

(2)提高拒识率。通过提高拒识率就可以减低误识率,直到达到指定的精度要求。当然,拒识的增多意味着操作人员的介入的增加,这对用户是极为不利的。

(3)加入逻辑校验。在通信系统中,人们常通过加校验码来保证数据的高质量传输,常见的校验码有:奇偶校验,汉明码等。在基于数字的应用系统中,我们也可以采用类似的方法。不过,这时校验方式应尽量简单,直观,利于填写人快速算出。

2、对处理速度也有很高的要求

数字识别面对的都是极其大量的数据报表,一般都要求达到每分钟几页到几十页的处理能力(包括扫描到完成识别的全过程)。而众所周知,处理速度与处理精度是一对矛盾,现在既要达到前面提到的高识别精度,又要有如此之高的速度,无疑增加了系统的设计难度,不过近年来,硬件水平提高很快,目前市场上己有较低价格,每分钟可扫描10-20页的高性能扫描仪,微机的运算速度飞快提高,这些都为高的处理速度定了坚实的基础。

3、要能批量自动作业

在一般的文本识别中,多是操作者一页页地送入文本,手工帮助机器进行版面分割(机器的自动分割能力往往是十分有限的)后再开始识别,很难准保证高质量的批量自动识别,而在数字识别系统中这是一个必须做到而且应能做到基本要求、原因如下:

(1)如果每页的处理都要人手工帮助完成,系统的综合处理速度无法达到要求。

(2)扫描仪的自动进纸技术已经十分成熟。

(3)处理对象在很多情况下是版面完全相同的大批格,很容易作到栏目的自动提取。

5.2 数字识别的典型应用

1、数字识别在大规模数据统计中的应用

在大规模的数据统计(如:行业年检、人口普查等)中,需要输入大量的数据,以前完全要手工输入,则需要耗费大量的人力和物力。近年来在这类工作中采用OCR技术己成为一种趋势。因为在这种应用中,数据的录入是集中组织的,所以往往可以通过专门设计表格和对书写施加限制以便于机器的自动识别。目前国内的大多数实用系统都要求用户按指定规范在方格内填写。另外,这些系统往往采用合适的用户界面对识别的结果作全面的检查,最终保证结果正确无误。可以看出,这是一类相对容易的应用,对识别核心算法的要求比较低,是目前国内很多单位应用开发的热点。

2、数字识别在财务、税金、金融领域中的应用

财务、税务、金融是数字识别大有可为的又一领域。随着我国经济的迅速发展,每天等待处理的财务、税务报表、支票、付款单等越来越多。如果能把它们用计算机自动处理.无疑可以节约大量的时间、金钱和劳力。与上面提到的统计报表处理相比,在这个领域的应用难度更大。原因有:1)识别的精度要求更高;2)处理的表格往往不止一种,一个系统应能智能地同时处理若干种表格;3)由于处理贯穿于整个日常工作之中。书写应尽量按一般习惯(如:不对书写者的写法做限定,书写时允许写连续的字串,而不是在固定的方格内书写),这样对识别及预处理的核心算法要求也提高了。

3、数字识别在邮件分拣中的应用

随着人们生活水平的提高,经济活动的发展,通信联系的需求使信函的互换量大幅度增加,虽然电子邮件被现代人广泛使用,但我国函件业务量也还在不断增长,一些大城市的中心邮局每天处理量将高达几百万件,业务量的急剧上升使得邮件的分拣自动化成为大势所趋,在邮件的自动分拣中,数字识别往往与光学条码识别,人工辅助识别等手段相结合,完成邮政编码的阅读。

总结

这次长达三个月的毕业设计即将随着我的论文的结束而接近尾声。整个设计的过程是很艰辛而又很有意义的。

我的设计题目是基于VC++的数字识别系统的设计与实现。数字识别技术发展到现在已经很成熟了,它的应用范围也很广泛。数字识别的实现是有很大实际意义的。在我所做的这个系统中主要应用到了三门学科:数字图象处理、模式识别与人工神经网络和VC++语言。由于设计时间的限制,要在三个月时间里学会三门不同的课程,对我来说是有很大挑战性的。所以我觉得这最后的半年真的是很紧张,但由于徐老师和同学们的帮助使我最终完成了这个设计。

这个系统总的来说可分为两部分来进行,第一部分就是图象的预处理,我直接处理的就是BMP形式位图。所以相对简单一点,不用进行图象格式的转换,但在现实应用中需要有图象格式转换这一步。图象的预处理就是将采集到图象通过一系列转换变成能够被BP网络训练的格式。第二部分就是网络的识别,首先确定网络的权值训练网络,通过误差反传不断的修正网络,使之具有很强的抗干扰性,最后达到高的识别精度。

在设计过程中,我觉的图象预处理部分相对简单一些,BP神经网络部分就有了一定的难度,查阅了很多的资料才将其理解。

再就是VC编程设计那一部分让我觉的很难,按照要求设置了流程图,但将其转化为程序就很困难,尤其是将各个函数的组装在一起的时候,函数与函数的接口,调用都极容易出错。这就要求设计人要有一定的耐心。

这个系统还有不是很完善的地方,就是它的识别精度还不是很高,而且系统不是很稳定,有的时候设置同样的参数前后识别的结果就不相同。这是一个还没有解决的问题。

总的来说,数字识别应用的技术还有很大的发展潜力,通过研究数字的识别进而发展到识别英文字符、汉字等,这些应用都是很广泛的。例如,公路上自动拍照就是通过识别车牌照完成功能的,车牌识别中就包括了数字、汉字和英文字符的识别,所以它是一个更为庞大的系统。

其次我们还可以借助其他算法理论,如矢量量化、小波分析、神经网络算法等理论研究和算法实现,力求找到一种识别率更高,实时性更好的算法。以丰富各方面的性能,拓宽数字识别可以应用的方面。

参考文献

[1] 马安鹏. Visual C++6程序设计导学.北京:清华大学出版社,2002

[2] David J.Kruglinski.Visual C++技术内幕.北京:清华大学出版社,2003

[3] David Simon(美)著,周愉萍等译.Visual C++ 6编程宝典.北京:电子工业出版社,2005.1

[4] 李朝晖.数字图像处理及应用.北京:机械工业出版社,2004

[5] 求是科技.VC++在数字图象处理中的应用.北京:电子工业出版社.2006

[6] 孙家广.计算机图形学.北京:清华大学出版社,1998

[7] 向世明.VC++数字图像与图形处理.北京:电子工业出版社,2002

[8] 边肇祺,张学工.模式识别.北京::清华大学出版社,2000.1

[9] Ajhijit S.Pandya and Robert B.Macy(美)著;徐勇等译.Pattern Recognition with Neural Networks.北京::电子工业出版社,1999.6

[10] 徐丽娜.神经网络控制.哈尔滨:哈尔滨工业大学出版社,1998

[11] 韩立群.人工神经网络理论、设计及开发.北京:北京化学工业出版社,2002

[12] 辛大欣,徐久成.BP神经网络算法在数字识别中的应用.西安工业学院学报.1995.15(1):72

[13] 张析中.汉字识别技术.北京:清华大学出版社,1992.

[14] 何玉彬,李新忠.神经网络控制技术及其应用北京:科学出版社,2000.

致谢

在论文完成之际,首先要感谢我的指导教师张一哲老师和辅导教师徐小君老师半年来给予我学习和生活中的关心、鼓励和教诲。张老师严谨的治学态度,广博的学识和平易近人的性格都深深地影响着我。徐老师良师益友般的教诲和帮助将使我终生受益,在此,谨向我的导师张一哲老师徐小君老师表示最衷心的感谢!

我还要感谢学院和电气系的各位老师,感谢他们四年来对我们的关心、帮助和支持。

同时,对同组的其他成员的大力帮助表示感谢。在这个团结奋斗,严谨求实的集体中,我获得了不断进取的动力。

父母之恩,无言以述,感谢他们这么多年来默默的操劳和奉献,是他们的支持,才使我能够有充裕的时间和充足的精力顺利完成学业。

最后,对给予我大力支持和帮助的各位老师、朋友和同学表示最衷心的感谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等天晴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值