opencv 基于KNN的手写数字字符识别
2016-07-21 08:48
597 查看
楼主为武汉市某科技大学的机械小硕,由于某种原因,开始学习和使用opencv,所以算是半路出家和非科班出身,如有描述的不够专业地方,还请多多包涵和批评指正。
本文主要实现对手写数字字符的识别,主要用到的方法为k-近邻分类方法,用到opencv提供的KNearest类。
也是在网上看到的代码,觉得很好玩,然后下载了工程,原工程是opencv2早期版本,还是cvmat的时代,看起来很不方便和习惯。
楼主花了点儿时间,好好学习了下,然后修改成了opencv2后期mat时代的代码,opencv2.4.9-2.4.13应该都可以跑起来。
先讲下原理吧
1、得到训练的数据,一般都会是两个矩阵,一个矩阵存放着数据,另一个矩阵存放数据对应的标记(如数字0,1,2,3....)
2、训练数据,这一步,很简单,一个函数就可以搞定
3、根据需要识别的图片,预测其属于哪一类。
总结来讲:既然opencv都为我们封装好了算法,提供了一个可供调用的类,使用起来,必然是比较简单的。大部分的精力和代码,都花在得到标准化的数据上。
话不多说,先上一部分代码吧
得到数据矩阵和相应的标记矩阵。
好了,只贴部分代码吧,如需要完整的工程,可以到hust平凡之路下载。
请原谅我这种赚取积分的行为。毕竟,人生已经如此的艰难。
本文主要实现对手写数字字符的识别,主要用到的方法为k-近邻分类方法,用到opencv提供的KNearest类。
也是在网上看到的代码,觉得很好玩,然后下载了工程,原工程是opencv2早期版本,还是cvmat的时代,看起来很不方便和习惯。
楼主花了点儿时间,好好学习了下,然后修改成了opencv2后期mat时代的代码,opencv2.4.9-2.4.13应该都可以跑起来。
先讲下原理吧
1、得到训练的数据,一般都会是两个矩阵,一个矩阵存放着数据,另一个矩阵存放数据对应的标记(如数字0,1,2,3....)
2、训练数据,这一步,很简单,一个函数就可以搞定
3、根据需要识别的图片,预测其属于哪一类。
总结来讲:既然opencv都为我们封装好了算法,提供了一个可供调用的类,使用起来,必然是比较简单的。大部分的精力和代码,都花在得到标准化的数据上。
话不多说,先上一部分代码吧
class basicOCR { public: float classify(Mat img, int showResult); basicOCR(); void test(); private: char file_path[255]; int train_samples; int classes; Mat trainData; Mat trainClasses; int size; static const int K = 5;//最大邻居个数 KNearest *knn; void getData(); void train(); void preprocessing(Mat &srcimage, int new_width, int new_height); };封装成一个类
</pre><pre name="code" class="cpp">basicOCR::basicOCR()//构造函数 { //initial sprintf(file_path, "OCR/"); train_samples = 50;//训练样本,总共100个,50个训练,50个测试 classes = 10;//暂时识别十个数字 size = 128;// trainData.create(train_samples*classes, size*size, CV_32FC1);//训练数据的矩阵 trainClasses.create(train_samples*classes, 1, CV_32FC1); //Get data (get images and process it) getData(); //train train(); //Test test(); printf(" ------------------------------------------------------------------------\n"); printf("|\t识别结果\t|\t 测试精度\t|\t 准确率\t|\n"); printf(" ------------------------------------------------------------------------\n"); }类的构造函数,可以看到,存放训练数据的矩阵trainData和存放对应标记的矩阵trainClasses
void basicOCR::getData() { Mat src_image; char file[255]; int i, j; for (i = 0; i<classes; i++) { for (j = 0; j< train_samples; j++) { //加载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 = imread(file, 0); if (src_image.empty()) { printf("Error: Cant load image %s\n", file); //exit(-1); } //process file preprocessing(src_image, size, size); //Set data float* data1 = trainData.ptr<float>(i*train_samples+j); float* data2 = src_image.ptr<float>(0); for (int k = 0; k < src_image.cols; k++) { data1[k] = data2[k]; } //Set class label trainClasses.at<float>(i*train_samples + j, 0) = i; } } }
得到数据矩阵和相应的标记矩阵。
好了,只贴部分代码吧,如需要完整的工程,可以到hust平凡之路下载。
请原谅我这种赚取积分的行为。毕竟,人生已经如此的艰难。
相关文章推荐
- 虚拟化 - 每天5分钟玩转 OpenStack(2)
- 先安装windows7_64bit,再安装Centos7,windows7的启动项不出现
- OPenGL ES Shader
- u-boot与linux内核间的参数传递过程分析
- linux--文件编程(4)
- Linux内核驱动之主次编号
- linux内核中等待队列(wait_event,wake_up...)
- 制作Windows、Linux启动U盘
- zabbix3.0.3-源码安装
- Linux 中的定时任务crontab
- Ubuntu 14.04 How to disable automount-open for SD or USB
- ubuntu常见错误--could not get lock /var/lib/dpkg/lock -open
- Linux下配置两个或多个Tomcat启动
- centos下用yum方式配置MySQL
- 在Linux环境下查看目标文件生成过程
- Linux编程基础——GDB(入门)
- Linux编程基础——GDB(设置断点)
- linux-C编程-文件操作
- HDU 5730 Shell Necklace(FFT+分治)
- 如何隐藏你的Linux的命令行历史