OpenCV手写数字字符识别(基于k近邻算法)
摘要
本程序主要参照论文,《基于OpenCV的脱机手写字符识别技术》实现了,对于手写阿拉伯数字的识别工作。识别工作分为三大步骤:预处理,特征提取,分类识别。预处理过程主要找到图像的ROI部分子图像并进行大小的归一化处理,特征提取将图像转化为特征向量,分类识别采用k-近邻分类方法进行分类处理,最后根据分类结果完成识别工作。
程序采用Microsoft Visual Studio 2010与OpenCV2.4.4在Windows 7-64位旗舰版系统下开发完成。并在Windows xp-32位系统下测试可用。
主流程图:
细化流程图:
预处理的过程就是找到图像的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近邻算法)的更多相关文章
- linux-基于tensorflow2.x的手写数字识别-基于MNIST数据集
数据集 数据集下载MNIST 首先读取数据集, 并打印相关信息 包括 图像的数量, 形状 像素的最大, 最小值 以及看一下第一张图片 path = 'MNIST/mnist.npz' with np. ...
- 手写数字识别——基于LeNet-5卷积网络模型
在<手写数字识别——利用Keras高层API快速搭建并优化网络模型>一文中,我们搭建了全连接层网络,准确率达到0.98,但是这种网络的参数量达到了近24万个.本文将搭建LeNet-5网络, ...
- 手写数字识别的k-近邻算法实现
(本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...
- 基于opencv的手写数字字符识别
摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...
- TensorFlow实战之Softmax Regression识别手写数字
关于本文说明,本人原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者于2018年02月21日 23:10:04所撰写内容(http://blog.c ...
- BP神经网络的手写数字识别
BP神经网络的手写数字识别 ANN 人工神经网络算法在实践中往往给人难以琢磨的印象,有句老话叫“出来混总是要还的”,大概是由于具有很强的非线性模拟和处理能力,因此作为代价上帝让它“黑盒”化了.作为一种 ...
- 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!
1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...
- 基于OpenCV的KNN算法实现手写数字识别
基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...
- KNN (K近邻算法) - 识别手写数字
KNN项目实战——手写数字识别 1. 介绍 k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法.它的工作原理是:存在一个 ...
随机推荐
- springMVC系列之(三) spring+springMVC集成(annotation方式)
个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助.不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想.实践出真知. 1.基本概念 1.1.Spring Spri ...
- Xcode7.2中如何添加一个Empty Application模板
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Xcode 6.0正式版之后已经没有所谓的Empty Appl ...
- Android多点触摸缩放图片-android学习之旅(四)
获取多触摸点 核心代码: 获取触摸点的个数和位置 public boolean onTouch(View v, MotionEvent event) { switch (event.getAction ...
- Dynamics CRM 2015Online Update1 new feature之 通过业务规则清空字段的值
自2013引入业务规则后很多的功能就不需要通过javascript来实现,业务人员直接通过配置就能解决.那随着版本的更新业务规则的功能也越来越强大,从之前很单纯的逻辑到后面的if..else,相信后面 ...
- Android的oom详解
Android的oom原因 1.资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM.资源性对象比如: 1-1,Cursor 1-2,调 ...
- C++ 对象的内存布局(上)
本文转载自haoel博主的博客:陈皓专栏 [空谷幽兰,心如皓月] 原文地址:C++ 对象的内存布局(上) C++ 对象的内存布局(上) 陈皓 http://blog.csdn.net/haoel 点击 ...
- linux 编译c程序与动态链接库
linux 下编译c程序与动态链接库 1 动态库h文件和c文件 1.1 h 文件: kaflog4c.h /** * kaflog4c.h */ #include <stdio.h> #i ...
- Chapter 3 Protecting the Data(1):理解权限
原文出处:http://blog.csdn.net/dba_huangzj/article/details/39548665,专题目录:http://blog.csdn.net/dba_huangzj ...
- sed-加速你在Linux的文件编辑
1. Sed简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中 ...
- 9.3、Libgdx手势检测
(官网:www.libgdx.cn) 触摸屏在输入的基础上增加了手势检测,比如两个手指实现缩放,单击或双击屏幕,长按屏幕等. Libgdx提供了GestureDetector来帮助你检测以下手势: t ...