摘要

本程序主要参照论文,《基于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

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

  1. linux-基于tensorflow2.x的手写数字识别-基于MNIST数据集

    数据集 数据集下载MNIST 首先读取数据集, 并打印相关信息 包括 图像的数量, 形状 像素的最大, 最小值 以及看一下第一张图片 path = 'MNIST/mnist.npz' with np. ...

  2. 手写数字识别——基于LeNet-5卷积网络模型

    在<手写数字识别——利用Keras高层API快速搭建并优化网络模型>一文中,我们搭建了全连接层网络,准确率达到0.98,但是这种网络的参数量达到了近24万个.本文将搭建LeNet-5网络, ...

  3. 手写数字识别的k-近邻算法实现

    (本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...

  4. 基于opencv的手写数字字符识别

    摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...

  5. TensorFlow实战之Softmax Regression识别手写数字

         关于本文说明,本人原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者于2018年02月21日 23:10:04所撰写内容(http://blog.c ...

  6. BP神经网络的手写数字识别

    BP神经网络的手写数字识别 ANN 人工神经网络算法在实践中往往给人难以琢磨的印象,有句老话叫“出来混总是要还的”,大概是由于具有很强的非线性模拟和处理能力,因此作为代价上帝让它“黑盒”化了.作为一种 ...

  7. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  8. 基于OpenCV的KNN算法实现手写数字识别

    基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...

  9. KNN (K近邻算法) - 识别手写数字

    KNN项目实战——手写数字识别 1. 介绍 k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法.它的工作原理是:存在一个 ...

随机推荐

  1. Python中使用rrdtool结合Django进行带宽监控

    我们有个网关需要做下带宽监控,能获取这个数据的唯一方法就是登录到管理界面查看.然后咱就写了个模拟登录的爬虫,定时抓取数据用rrdtool存储,最后通过Django来展示.这里就涉及了python的rr ...

  2. 6.4、Android Studio的GPU Monitor

    Android Monitor包含GPU Monitor,它将可视化的显示渲染窗体的时间.GPU Monitor可以帮助你: 1. 迅速查看UI窗体生成 2. 辨别是否渲染管道超出使用线程时间 在GP ...

  3. [maven学习笔记]第一节,认识maven,搭建maven开发环境,写第一个HelloWorld

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40142771 maven官网:http://maven.apache.org/ 学习视 ...

  4. 基于V4L2摄像头采集图片程序设计

    #ifndef __COMMON_H #define __COMMON_H //该头文件定义的是摄像头在屏幕上显示的宽度和高度 #include<stdio.h> #include< ...

  5. 排列熵算法简介及c#实现

    一.   排列熵算法简介: 排列熵算法(Permutation Entroy)为度量时间序列复杂性的一种方法,算法描述如下: 设一维时间序列: 采用相空间重构延迟坐标法对X中任一元素x(i)进行相空间 ...

  6. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(七)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 打开SpriteBuilder,在文件视图中新建一个文件夹Fon ...

  7. android的PackageManagerService详解

    PackageManagerService主要是一个包的管理服务,在开机的时候会解析以前保存的一些安装包的相关数据,android运行过程中新安装的apk也会保存到PackageManagerServ ...

  8. 不窃取用户隐私的搜索引擎: DuckDuckGo

    不窃取用户隐私的搜索引擎: DuckDuckGo https://duckduckgo.com/ 最近goggle不给力, baidu搜出来的很多都是垃圾, bing用久了很烦. 于是用上了DuckD ...

  9. 【翻译】Ext JS 5:为不同设备设置不同的主题

    原文:Sencha Ext JS 5: Supporting Different Themes for Different Devices 步骤1创建一个应用程序 步骤2定义主题 步骤3编辑Appjs ...

  10. Chipmunk僵尸物理对象的出现和解决(七)

    首先判断问题出现在Star的类方法doStickShorterWork中,于是逐步分词注释代码,最后剩下如下代码: +(void)doStickShorterWork:(Stick *)stick{ ...