在GetFeature类中定义了pattern结构体,保存某个汉字的所有样品特征。pattern结构如下:
struct pattern//pattern结构体,保存某个汉字的所有样品特征
{
int number;//该手写汉字样品个数
double feature[200][25];
};
GetFeature类定义如下:
class GetFeature : public CDib
{
public:
double pipei(double s1[],double s2[]);
int LeastDistance();
pattern pattern[10];//手写汉字样品特征库
double testsample[25];//待测的手写汉字
int width;//手写汉字的宽
int height;//手写汉字的高
int LineBytes;
void Save(int cls);//将手写的汉字保存到cls(0~9)类别中
double Cal(int row, int col);//计算分割好的5×5小区域中,黑像素所占
//的比例
void SetFeature();//计算手写汉字的特征,赋值给testsample
void GetPosition();//获得手写汉字的位置
GetFeature();
virtual ~GetFeature();
protected:
int bottom;//手写汉字的底部
int top;//手写汉字的顶部
int left;//手写汉字的左边
int right;//手写汉字的右边
};
函数的具体实现见附件。
4.4系统的设计流程及功能的具体实现
系统设计的第一部分为标准样品输入、特征提取、样品库建立和保存,这一部分是有监督的训练学习过程;第二部分为用户手写输入一个汉字及识别功能。设计流程如图4-1设计流程图所示:
图4-1设计流程图
具体功能实现方法如下:
1.手写汉字输入:系统中画笔的直径设置为8个像素,画图的区域被限制在视图客户区(0,0),(240,240)矩形内,画笔的位置和图像的数据指针相关联,设鼠标焦点的坐标为(x,y),m_pData 为位图的数据指针,则数据指针应变换为:m_pData+LineBytes*(height-y)+x,鼠标的被按下时以鼠标焦点为中心,4像素为半径的区域内的像素值都赋值为0,同时刷新视图。实际效果如图4-2汉字输入效果:
图4-2汉字输入效果
2.汉字的打开和保存:利用CFile类可以很容易的实现汉字的打开与保存。在打开图象时调用CMapView::OnFileOpen()函数,得到位图的基本信息,在CMapView::OnDraw(CDC* pDC)函数中,首先将位图的调色板作为当前的调色板,再调用::StretchDIBits()函数显示位图;保存汉字图象可以直接调用CDib类中的CDib::SaveFile(const CString filename)函数实现。
3.特征提取、保存及查看样品库:直接执行菜单“图像操作”“保存特征”,系统将调用函数CMapView::OnGet(),得到图像中汉字的位置,然后把图像平均分割为25份,按照每一区域中黑像素的多少提取5*5=25维的特征,然后出现如图4-3保存样品示意图。用户只要输入各个汉字对应的序号,就可以把当前图像特征保存到样品库。在保存的过程中用到了串行化的技术,程序首先包含了一个template.dat文件,然后定义了一个CArchive类的对象,利用这个对象把当前图像的特征保存到template.dat文件中,永久地保存在磁盘中。
图4-3保存样品示意图
用户可单击“查看”“查看样品”可以查看当前样品库中各个汉字具有的样品数,在这一过程中利用CArchive类的对象从template.dat文件中读取当前汉字库中的特征值,并显示出每个汉字的样品数,效果如图4-4查看样品所示:
图4-4查看样品
4.汉字识别
用户只要在视图的灰色区域中输入合法的汉字,然后单击“图像操作”“识别”,系统就回自动提取汉字的特征,与样品库中汉字特征按照最小距离算法识别手写汉字。实际效果如图4-5汉字识别示意图所示。
图4-5汉字识别示意图
程序中用到的函数的具体代码请参看附录。
4.5实验结果和分析
用模板匹配法识别汉字的结果如下表:
表4-1识别结果
待识别汉字 识别次数 成功次数 成功率
中 20 19 95%
华 20 18 90%
人 20 18 90%
民 20 17 85%
共 20 19 95%
和 20 18 90%
国 20 18 90%
万 20 19 95%
岁 20 19 95%
! 20 17 85%
结果分析:识别正确率虽然很高,在识别的过程中有误判情况的发生,经分析原因有以下几种:
1.每个汉字特征的维数只有25,所以只能把图象分割为25份精度不高。
2.每个汉字的样品数只有5个,较少,不能覆盖大多数手写汉字的分布情况。
3.在输入手写汉字时,有时太小或者不规范,在特征提取时就会发生差错。例如下图:
图4-6误判示意图
结束语
本文主要介绍了模式识别的基本理论和方法,并实现了用最小距离算法
识别10个汉字字符的程序。在本系统设计中所涉及的技术如下:
1、 模式与图象识别技术。
2、 分类器的设计方法。
3、 VC++6.0的界面设计。
归纳起来,在做毕业设计的过程中,我主要做了以下工作:
第一阶段:收集、阅读和分析有关模式识别及手写汉字识别的书籍,从
中找到一种合理的设计方法。
第二阶段:学习VC++6.0界面设计的方法,掌握了MFC的基本构架,文
档视图结构,消息映射,对话框的使用等知识。
第三阶段:在VC的开发环境中编写实现汉字识别的代码,功能有位图的浏览和存储,特征提取、保存,模板匹配等,并对各个部分进行了调试。
第四阶段:撰写论文。
限于我的水平有限,知识掌握不足,本系统还有许多有待改进的地方:
1、 图形界面还不完善,能够支持的操作比较少。
2、 汉字字符较少,只有10个,不具有代表性。
3、 实现手写汉字识别的算法比较多,例如:基于概率统计的贝叶斯算法,神经网络,分形几何等算法,由于时间关系,只用了最简单的方法。
模式识别是一门综合性、交叉性学科,在理论上它涉及代数学、矩阵论、概率论、图论、模糊数学、最优化理论等等众多学科的知识,在应用上又与其他许多领域的工程技术密切相关,其内涵可以概括为信息处理、分析与决策。在模式识别学科中,并没有一种普遍适应的算法,模式识别的算法要根据具体的识别对象和任务来确定,所以模式识别学科中还有很多创新性的工作,我打算在研究生学习阶段在这方面做深入的研究。
致谢词
本论文是在王典洪教授的亲切关怀与精心指导下完成的,感谢我的导师王典洪教授,他在我做毕业设计过程中,从选题到具体实施都给予我很多的帮助和指导,他循循善诱的教导和不拘一格的思路给予我无尽的启迪。
真诚感谢机电学院的领导和老师,感谢电信教研室的各位老师,他们在我平常的学习与日常生活中,给了我许多关心与帮助。在此我表示深深的感谢!
感谢我的室友们,从遥远的家来到这个陌生的城市里,是你们和我共同维系着彼此之间兄弟般的感情,维系着寝室那份家的融洽。
感谢我的父亲母亲,焉得谖草,言树之背,养育之恩,无以回报,你们永远健康快乐是我最大的心愿。
在论文即将完成之际,我的心情无法平静,从开始进入课题到论文的顺利完成,有多少可敬的师长、同学、朋友给了我无言的帮助,在这里请接受我诚挚的谢意!
参考文献
[1]杨淑莹.图像模式识别----VC++技术实现.北京:清华大学出版社.2005
[2]徐士良.C常用算法程序集.北京:清华大学出版社.1996
[3]黄振华,吴诚一.模式识别原理.杭州:浙江大学出版社.1991
[4]沈清,汤霖.模式识别导轮.长沙:国防科技大学出版社.1991
[5]边肇祺,张学工.模式识别.北京:清华大学出版社.2000
[6]罗耀光,盛立东.模式识别.北京:人民邮电出版社.1989
[7]谭浩强.C程序设计.北京:清华大学出版社.2001
[8]郑莉,董渊.C++语言程序设计.北京:清华大学出版社.2002
[9]黄维通.Visual C++ 面向对象与可视化程序设计.
北京:清华大学出版社.2002
[10]王育坚. Visual C++ 面向对象编程教程. 北京:清华大学出版社.2004
[11]章毓晋.图象处理和分析. 北京:清华大学出版社.2001
[12]HildebrandTH, LiuW. Optical recognition of handwritten Chinese characters: advances since 1980[J]Pattern Recognition, 1993,26(2): 205-225
[13] Liao C W, Huang J S. Atransformation invariant matching algorithm for handwritten Chinesecharacter recognition [J]. Pattern Recognition, 1990, 23(11):1 167-1 188
[14]吴佑寿,丁晓青.汉字识别—原理方法与实现.高等教育出版社.1992.
[15]「英]厄尔曼.文字、图形识别技术.人民邮电出版社.1983.
[16] 孙伟.用Visual C++构造用于手写汉字识别的模拟系统.微处理机,2002.
[17] Carlos M. Travieso, Ciro R.Morales, Itziar G. Alonso, et al. Handwritten Digits Parameterizationfor HMM based recognition, Image Processing and its Applications. IEEE Conference Publication,1999, 465: 770-774.
附录
GetFeature类函数的具体实现
#include "stdafx.h"
#include "GetFeature.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
GetFeature::GetFeature()
{
}
GetFeature::~GetFeature()
{
}
/***************************************************************
* 函数名称:GetPosition()
* 函数类型:void
* 函数功能:搜索手写数字的位置,赋值给bottom,down,right,left
****************************************************************/
void GetFeature::GetPosition()
{
width=GetWidth();
height=GetHeight();
LineBytes=(width*8+31)/32*4;
int i,j;
BOOL flag;
for(j=0;j<height;j++)
{
flag=FALSE;
for(i=0;i<width;i++)
if(m_pData[j*LineBytes+i]==0)
{
flag=TRUE;
break;
}
if(flag)
break;
}
bottom=j;
for(j=height-1;j>0;j--)
{
flag=FALSE;
for(i=0;i<width;i++)
if(m_pData[j*LineBytes+i]==0)
{
flag=TRUE;
break;
}
if(flag)
break;
}
top=j;
for(i=0;i<width;i++)
{
flag=FALSE;
for(j=0;j<height;j++)
if(m_pData[j*LineBytes+i]==0)
{
flag=TRUE;
break;
}
if(flag)
break;
}
left=i; |