您的位置:首页 > 运维架构

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都为我们封装好了算法,提供了一个可供调用的类,使用起来,必然是比较简单的。大部分的精力和代码,都花在得到标准化的数据上。

话不多说,先上一部分代码吧

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平凡之路下载。

请原谅我这种赚取积分的行为。毕竟,人生已经如此的艰难。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: