使用MLP解决OCR问题(OpenCV)(上)


       在之前有关神经网络的文章中,大部分都是对神经网络的概念阐述以及一些公式的推导,比较枯燥且较难直接应用到实际中,今天就来介绍一下神经网络的一个简单的实际应用——解决OCR问题。LeCun等大神已经使用CNN算法解决了很多OCR问题,这里再去解决OCR的问题并不是要达到多好的效果,而是抛砖引玉让大家了解如何使用MLP算法。关于MLP的类库有很多,在本篇文章中使用的是偏重于图像处理的OpenCV。

使用MLP解决OCR问题(OpenCV)(上)_第1张图片

数据集:

       数据集的获得有很多渠道,我的方式比较简单也比较容易获得大量的数据集:首先就是使用文本编辑工具(比如word,Pdf)写上不同字体的数字若干。随后使用截屏工具获得包含各种字体的图片,最后使用图片处理工具(openCV之类的)将字体分割为一个个的小图片保存。如此获得的训练集量比较可控,分类器的输入样式也可控。如果只是想对单一字体的数字进行训练分类,也切忌不要单纯的把小图片进行复制获得大量的数据集,这样做没有任何意义。比较行之有效的方法是:1、同样字体的数字同样使用文本编辑器写若干个,由于最后生成的图像在边界处并不是每个数字都一样,也可以得到差异的图片。2、在进行图像分割的时候可以使用不同的阈值获得略微不同的字体图片。最终获得如下图所示的数据集

使用MLP解决OCR问题(OpenCV)(上)_第2张图片


预处理模块:

        由于MLP模型是不接受二维图像模型的输入,预处理模块就是将每个图像转换为MLP可以接受的输入。当然这个预处理的复杂程度根据所获得的数据集的样式而有所区别,但就对本文已经比较充分的处理过的数据集来说,预处理过程是很简单的,仅仅是将图片转为列向量,本文中得到的图像都是9*15的图像,所以这个向量的长度就是145。其中使用0代表图片中黑色的像素点,1代表白色的像素点。这样上图的0使用向量的形式表示为0,0,0,0,1,0,0,0,0,0,0,0,……,0,1,1,1,0,0,1,1,1,1,1,1,0。实现代码如下:
//将图像矩阵转为一个向量
void convertToPixelValueArray(Mat &img,int pixelarray[])
{
	int i =0;
	for(int x=0;x<15;x++)
	{  
		for(int y=0;y<9;y++)
		{
			pixelarray[i]=(img.at(x,y)==255)?1:0;
			i++;

		}

	}
}

训练模块:

       这一模块是根据输入(145维向量)以及输出(10维向量)构建一个MLP模型,随后通过训练集训练调整模型的参数。这部分训练基本属于BP算法的范畴,openCV类库中已有封装好的函数进行处理,如果想了解训练的具体原理的也可以参考博主之前的文章。
#define ATTRIBUTES 135  //每一个样本的像素总数.9X15
#define CLASSES 10 

cv::Mat layers(3,1,CV_32S);
	layers.at(0,0) = ATTRIBUTES;//input layer
	layers.at(1,0)=16;//hidden layer
	layers.at(2,0) =CLASSES;//output layer

	//创建神经网络
	//for more details check http://docs.opencv.org/modules/ml/doc/neural_networks.html
	CvANN_MLP nnetwork(layers, CvANN_MLP::SIGMOID_SYM,2.0/3.0,1);

	CvANN_MLP_TrainParams params(                                  

		// 终止训练在 1000 次迭代之后
		// 或者神经网络的权值某次迭代
		// 之后发生了很小的改变
		cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, 0.000001),
		// 使用BP算法训练
		CvANN_MLP_TrainParams::BACKPROP,
		// BP算法的系数
		// recommended values taken from http://docs.opencv.org/modules/ml/doc/neural_networks.html#cvann-mlp-trainparams
		0.1,
		0.1);

	// 训练神经网络

	printf( "\nUsing training dataset\n");
	int iterations = nnetwork.train(training_set, training_set_classifications,cv::Mat(),cv::Mat(),params);
	printf( "Training iterations: %i\n\n", iterations);

	// 保存模型到一个XML文件
	CvFileStorage* storage = cvOpenFileStorage( "E:\\workdir\\NN\\param.xml", 0, CV_STORAGE_WRITE );
	nnetwork.write(storage,"DigitOCR");
	cvReleaseFileStorage(&storage);






你可能感兴趣的:(OpenCV,Machine,Learning)