OpenCV手写数字字符识别(基于k近邻算法)

 

摘要

本程序主要参照论文,《基于OpenCV的脱机手写字符识别技术》实现了,对于手写阿拉伯数字的识别工作。识别工作分为三大步骤:预处理,特征提取,分类识别。预处理过程主要找到图像的ROI部分子图像并进行大小的归一化处理,特征提取将图像转化为特征向量,分类识别采用k-近邻分类方法进行分类处理,最后根据分类结果完成识别工作。

程序采用Microsoft Visual Studio 2010与OpenCV2.4.4在Windows 7-64位旗舰版系统下开发完成。并在Windows xp-32位系统下测试可用。

主流程图

 

细化流程图:

 

 

 

1.   预处理

预处理的过程就是找到图像的ROI区域的过程,如下图所示:

 

首先找到数字的边界框,然后大小归一化数字图片,主要流程如下图所示:

 

 

 

主要代码:

IplImagepreprocessing(IplImage*imgSrc,intnew_width,intnew_height)

{

      
IplImage* result;

      
IplImage* scaledResult;

 

      
CvMat data;

      
CvMat dataA;

      CvRectbb;//bounding box

      CvRectbba;//boundinb box maintain aspect ratio

      

      //Find bounding box找到边界框

      
bb=findBB(imgSrc);

      
cvGetSubRect(imgSrc, &data,cvRect(bb.x,bb.y,bb.width,bb.height));

      
int size=(bb.width>bb.height)?bb.width:bb.height;

      
result=cvCreateImage(
cvSize( size, size ), 8, 1 );

      
cvSet(result,CV_RGB(255,255,255),NULL);

      //将图像放中间,大小归一化

      
int x=(int)floor((float)(size-bb.width)/2.0f);

      
int y=(int)floor((float)(size-bb.height)/2.0f);

      
cvGetSubRect(result, &dataA,cvRect(x,y,bb.width,bb.height));

      
cvCopy(&data, &dataA,NULL);

      //Scale result

      
scaledResult=cvCreateImage(
cvSize( new_width,
new_height ), 8, 1 );

      
cvResize(result,
scaledResult, CV_INTER_NN);

      

      //Return processed data

      return *scaledResult;//直接返回处理后的图片

      

}

 

 

2.   特征提取

在拿到ROI图像减少了信息量之后,就可以直接用图片作为向量矩阵作为输入:

voidbasicOCR::getData()

{

      
IplImage* src_image;

      
IplImage prs_image;

      
CvMat row,data;

      
char file[255];

      
int i,j;

      
for(i =0; i<classes;i++)//总共10个数字

       {

             for(j = 0;
j<train_samples;j++)//每个数字50个样本

              {

                    

                    //加载所有的样本pbm格式图像作为训练

                    if(j<10)

                           sprintf(file,"%s%d/%d0%d.pbm",file_path,i,i
, j);

                    else

                           sprintf(file,"%s%d/%d%d.pbm",file_path,i,i
, j);

                    src_image =cvLoadImage(file,0);

                    if(!src_image)

                     {

                           printf("Error: Cant load image %s\n",file);

                           //exit(-1);

                     }

                    //process file

                    prs_image =preprocessing(src_image,size,size);

                    //生成训练矩阵,每个图像作为一个向量

                    cvGetRow(trainClasses, &row,i*train_samples
+j);

                    cvSet(&row,cvRealScalar(i));

                    //Set data

                    cvGetRow(trainData, &row,i*train_samples
+j);

 

                    IplImage*img =
cvCreateImage(cvSize(
size, size ),

IPL_DEPTH_32F, 1 );

                    //转换换 8 bits image to 32位浮点数图片取值区间为[0,1]

                    //scale = 0.0039215 = 1/255; 

                    cvConvertScale(&prs_image,img, 0.0039215, 0);

 

                    cvGetSubRect(img, &data,cvRect(0,0,size,size));

                    

                    CvMatrow_header, *row1;

                    //convert data matrix sizexsize to vecor

                    row1 =cvReshape( &data, &row_header,
0, 1 );

                    cvCopy(row1, &row,NULL);

              }

       }

}

 

 

3.   分类识别

识别方法采用knn近邻分类法。这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值。这种方法有时候被称作“基于样本的学习”,即为了预测,我们对于给定的输入搜索最近的已知其相应的特征向量。

K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。

识别工作主要有以下几个步骤:

1. 初始化机器学习算法,及其训练

knn=new CvKNearest( trainData, trainClasses, 0, false, K );

因为trainData, trainClasses数据已得到。训练在CvKNearest算法初始化中已经完成

2. 识别

获取识别测试的数据,testData

result=knn->find_nearest(testData,K,0,0,nearest,0);

result为返回的识别的结果

 

 

4.   实验结果

在knn参数k=5,子图像向量大小选取128*128像素,训练样本50副图片,测试样本50副图片,系统误识率为7.4%。对于用户手写阿拉伯数字2的识别结果为2,识别比较准确。

 

 

 

5.   未来的工作

本程序主要参照网上的一些实例完成了部署跟实验工作,虽然仅仅完成了手写阿拉伯数字的识别工作,但是字符识别的一些原理工作都是相同的,未来能够从一下几个方面进行提高:

1.      提高程序的识别准确率,从一些文献实现的结果来看,简单的模型结合大量的训练样本,往往效果比复杂的模型结合少量训练样本实现的效果好。

2.      扩展程序的功能,从实现简单的字符到最终实现识别手写汉字等。

3.      提高识别速度,改进算法为并行算法,实现如联机在线识别等。

 

 

6.主要参考文献:

http://blog.csdn.net/jackmacro/article/details/7026211

http://blog.damiles.com/2008/11/basic-ocr-in-opencv/

http://blog.csdn.net/zhubenfulovepoem/article/details/6803150

http://blog.csdn.net/firehood_/article/details/8433077

http://blog.csdn.net/viewcode/article/details/7943341

 

 

7.项目打包下载

http://download.csdn.net/detail/wangyaninglm/6631953

 

8.手写字符识别的复杂版本,这个增加了一些OpenGL技术,程序比较复杂

http://blog.csdn.net/wangyaninglm/article/details/41848019

时间: 2024-08-03 10:49:14

OpenCV手写数字字符识别(基于k近邻算法)的相关文章

k近邻 - 手写数字识别

# -*- coding: utf-8 -*- import numpy as np import operator from os import listdir # k近邻算法实现 def classify0(inX, dataSet, labels, k): # 得到数组的行数, 训练数据的大小 dataSetSize = dataSet.shape[0] # 将inX这一个数据, 扩充成dataSetSize个大小一样的数据集 # 减去dataSet, 得到一个差集的数据集 diffMat

C#中调用Matlab人工神经网络算法实现手写数字识别

手写数字识别实现 设计技术参数:通过由数字构成的图像,自动实现几个不同数字的识别,设计识别方法,有较高的识别率 关键字:二值化  投影  矩阵  目标定位  Matlab                                                               手写数字图像识别简介: 手写阿拉伯数字识别是图像内容识别中较为简单的一个应用领域,原因有被识别的模式数较少(只有0到9,10个阿拉伯数字).阿拉伯数字笔画少并且简单等.手写阿拉伯数字的识别采用的方法相对于

手把手,74行代码实现手写数字识别

1. 引言:不要站在岸上学游泳 "机器学习"是一个很实践的过程.就像刚开始学游泳,你在只在岸上比划一堆规定动作还不如先跳到水里熟悉水性学习来得快.以我们学习"机器学习"的经验来看,很多高大上的概念刚开始不懂也没关系,先写个东西来跑跑,有个感觉了之后再学习那些概念和理论就快多了.如果别人已经做好了轮子,直接拿过来用则更快.因此,本文直接用Michael Nielsen先生的代码(github地址: https://github.com/mnielsen/neural-

下载的手写数字识别matlab源代码调试不出来,求助

问题描述 下载的手写数字识别matlab源代码调试不出来,求助 源链接 求详细调试方法 解决方案 至少把报错贴出来吧? 那个chargui 文件使用GUI编辑打开运行报错是什么?

编程-如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别?

问题描述 如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别? 如何不使用Matlab已有命令编写BP神经网络基本原理,来实现手写数字识别? 解决方案 http://download.csdn.net/detail/aoxiangyuntian123/8472775

手写数字识别的几种实现方法

我使用了手写数字数据库MNIST的一个子集,并做了多种处理 程序中附有数据库,完整的数据库在这儿下载,程序在这儿下载   实现的算法有: 模板匹配 类中心欧式距离 贝叶斯分类算法 夹角余弦距离 奖惩算法 增量校正算法 LMSE算法   特征提取方法:图像分割为若干小块,计算笔画像素占小块总像素数的比例 每一个算法都在独立的cpp文件中, 我直接使用源数据库而未作处理,最初使用图像的5x5分割, 为了提高精度,后来又使用7x7分割, 下载程序中已经有这两种分割的特征数据   主程序使用函数指针调用

MNIST手写数字数据库

手写数字库很容易建立,但是总会很浪费时间.Google实验室的Corinna Cortes和纽约大学柯朗研究所的Yann LeCun建有一个手写数字数据库,训练库有60,000张手写数字图像,测试库有10,000张. 请访问原站 http://yann.lecun.com/exdb/mnist/ 该数据库在一个文件中包含了所有图像,使用起来有所不便.如果我把每个图像分别保存,成了图像各自独立的数据库. 并在Google Code中托管. 如果你有需要,欢迎在此下载: http://code.go

K近邻算法-KNN

K近邻算法-KNN 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居.为何要找邻居?打个比方来说,假设你来到一个陌生的村庄,现在你要找到与你有着相似特征的人群融入他们,所谓入伙. 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个

K近邻算法

什么是K近邻算法     何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻 居.为何要找邻居?打个比方来说,假设你来到一个陌生的村庄,现在你要找到与你有着相似特征的人群融入他们,所谓入伙.     用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居), 这K个