【opencv3--ANN神经网络训练识别OCR数据集】


#include <string>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\ml.hpp>
#include<fstream>
using namespace std;
using namespace cv;
using namespace ml;
int main()
{
	////==========================读取图片创建训练数据==============================////
	//将所有图片大小统一转化为8*16
	const int imageRows = 8;
	const int imageCols = 16;
	//图片共有10类
	const int classSum = 10;
	//每类共20张图片
	const int imagesSum = 20;
	//每一行一个训练图片
	//float trainingData[classSum*imagesSum][imageRows*imageCols] = { { 0 } };
	Mat trainData0; // = Mat(classSum*imagesSum, imageRows*imageCols, CV_8UC1, Scalar::all(0));
					//训练样本标签
					//float labels[classSum*imagesSum] = { 0 };

	string img_path = "C:\\Users\\wangzhenlin\\Desktop\\ann\\Image\\";
	ifstream fin(img_path + "img.txt");
	string str;
	while (getline(fin, str)) {
		if (str.length()) {
			string imgname = img_path + str;
			//cout << imgname << endl;
			//getchar();

			Mat src = imread(imgname, 0);
			//imshow("aa", src);
			//waitKey(0);

			if (src.empty())
			{
				std::cout << "can not load image \n" << std::endl;
				return -9;
			}
			Mat  resizeImg, trainImg;
			int k = 0;
			//将所有图片大小统一转化为8*16
			resize(src, resizeImg, Size(imageRows, imageCols), (0, 0), (0, 0), INTER_AREA);
			//threshold(resizeImg, trainImg, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
			threshold(resizeImg, trainImg, 0, 1, cv::THRESH_BINARY | cv::THRESH_OTSU);

			Mat rowMat = trainImg.reshape(0, 1);
			trainData0.push_back(rowMat);

			//int m = 0;

			//for (int j = 0; j < trainImg.rows; j++) {
			//	uchar *p = trainImg.ptr<uchar>(j);
			//	for (int k = 0; k < trainImg.cols; k++) {
			//		int index = k * j + k;

			//		trainingData[m][index] = p[k];


			//	}
			//}
			//m++;

		}

	}


	// 设置标签数据
	Mat label0 = Mat(classSum*imagesSum, classSum, CV_8UC1, Scalar::all(0));
	//int a = 0;
	int b = 0;
	for (int i = 0; i < 200; i++)
	{
		b = i / 20;
		//labels[i] = (float)b;
		label0.at<uchar>(i, b) = 1.0;
		//a++;
	}

	//训练样本数据及对应标签
	//Mat trainingDataMat(classSum*imagesSum, imageRows*imageCols, CV_32FC1, trainingData);
	//Mat labelsMat(classSum*imagesSum, classSum, CV_32FC1, labels);
	//std::cout<<"trainingDataMat: \n"<<trainingDataMat<<"\n"<<std::endl;
	//std::cout<<"labelsMat: \n"<<labelsMat<<"\n"<<std::endl;
	////==========================训练部分==============================////

	Ptr<ANN_MLP>model = ANN_MLP::create();
	//Mat layerSizes = (Mat_<int>(1, 5) << imageRows * imageCols, 128, 128, 128, classSum);
	Mat layerSizes = (Mat_<int>(1, 3) << imageRows * imageCols, 500, classSum);
	model->setLayerSizes(layerSizes);
	model->setTrainMethod(ANN_MLP::BACKPROP, 0.001, 0.1);
	model->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1.0, 1.0);
	model->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 10000, 0.0001));

	Mat trainDataFloat, lebalFloat;
	trainData0.convertTo(trainDataFloat, CV_32FC1);
	label0.convertTo(lebalFloat, CV_32FC1);
	Ptr<TrainData> trainData = TrainData::create(trainDataFloat, ROW_SAMPLE, lebalFloat);
	model->train(trainData);
	//保存训练结果
	model->save("MLPModel.xml");

	////==========================预测部分==============================////
	//读取测试图像
	Mat test, dst;
	test = imread(img_path + "1475068321.png", 0);;
	//test = imread(img_path + "1475069602.png", 0);;
	if (test.empty())
	{
		std::cout << "can not load image \n" << std::endl;
		return -2;
	}
	
	resize(test, test, Size(imageRows, imageCols), (0, 0), (0, 0), INTER_AREA);
	threshold(test, test, 0, 1, cv::THRESH_BINARY | cv::THRESH_OTSU);
	Mat_<float> testMat(1, imageRows*imageCols);
	testMat = test.reshape(0, 1);
	//for (int i = 0; i < imageRows*imageCols; i++)
	//{
	//	testMat.at<float>(0, i) = (float)test.at<uchar>(i / 8, i % 8);
	//}
	model->save("123.xml");
	//使用训练好的MLP model预测测试图像
	model->predict(testMat, dst);

	std::cout << "testMat: \n" << testMat << "\n" << std::endl;
	std::cout << "dst: \n" << dst << "\n" << std::endl;
	double maxVal = 0;
	Point maxLoc;
	minMaxLoc(dst, NULL, &maxVal, NULL, &maxLoc);
	std::cout << "测试结果:" << maxLoc.x << "置信度:" << maxVal * 100 << "%" << std::endl;
	imshow("test", test);
	waitKey(0);
	return 0;
}

结果输出:

还有一种是基于KNN与随机森林的:


#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;

int main()
{
	Mat img = imread("123.png");
	Mat gray;
	cvtColor(img, gray, CV_BGR2GRAY);
	int b = 20;
	int m = gray.rows / b;   //原图为1000*2000
	int n = gray.cols / b;   //裁剪为5000个20*20的小图块
	Mat data, labels;   //特征矩阵
	for (int i = 0; i < n; i++)
	{
		int offsetCol = i*b; //列上的偏移量
		for (int j = 0; j < m; j++)
		{
			int offsetRow = j*b;  //行上的偏移量
								  //截取20*20的小块
			Mat tmp;
			gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
			data.push_back(tmp.reshape(0, 1));  //序列化后放入特征矩阵
			labels.push_back((int)j / 5);  //对应的标注
		}

	}
	data.convertTo(data, CV_32F); //uchar型转换为cv_32f
	int samplesNum = data.rows;
	int trainNum = 3000;
	Mat trainData, trainLabels;
	trainData = data(Range(0, trainNum), Range::all());   //前3000个样本为训练数据
	trainLabels = labels(Range(0, trainNum), Range::all());



	//训练样本数据及对应标签
	//Mat trainingDataMat(classSum*imagesSum, imageRows*imageCols, CV_32FC1, trainingData);
	//Mat labelsMat(classSum*imagesSum, classSum, CV_32SC1, labels);
	//std::cout<<"trainingDataMat: \n"<<trainingDataMat<<"\n"<<std::endl;
	//std::cout<<"labelsMat: \n"<<labelsMat<<"\n"<<std::endl;
	////==========================训练部分==============================////
	Ptr<SVM> svm = SVM::create();//SVM分类器
	svm->setType(SVM::C_SVC);
	svm->setC(0.01);
	svm->setKernel(SVM::LINEAR);
	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 3000, 1e-6));
	std::cout << "Starting training..." << endl;
	svm->train(trainData, ROW_SAMPLE, trainLabels);//训练分类器 
	std::cout << "Finishing training..." << endl;






	//使用KNN算法
	int K = 5;
	Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabels);
	Ptr<KNearest> model = KNearest::create();
	model->setDefaultK(K);
	model->setIsClassifier(true);
	model->train(tData);

	double ktrain_hr = 0, ktest_hr = 0;
	
	// compute prediction error on train and test data
	for (int i = 0; i < samplesNum; i++)
	{
		Mat sample = data.row(i);
		float r = model->predict(sample);   //对所有行进行预测
											//预测结果与原结果相比,相等为1,不等为0
		r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;

		if (i < trainNum)
			ktrain_hr += r;  //累积正确数
		else
			ktest_hr += r;
	}

	ktest_hr /= samplesNum - trainNum;
	ktrain_hr = trainNum > 0 ? ktrain_hr / trainNum : 1.;

	printf("accuracy: train = %.1f%%, test = %.1f%%\n",
		ktrain_hr*100., ktest_hr*100.);





	//预测分类
	double train_hr = 0, test_hr = 0;

	// compute prediction error on train and test data
	for (int i = 0; i < samplesNum; i++)
	{
		Mat sample = data.row(i);
		float r = svm->predict(sample);   //对所有行进行预测
											//预测结果与原结果相比,相等为1,不等为0
		r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;

		if (i < trainNum)
			train_hr += r;  //累积正确数
		else
			test_hr += r;
	}

	test_hr /= samplesNum - trainNum;
	train_hr = trainNum > 0 ? train_hr / trainNum : 1.;

	printf("accuracy: train = %.1f%%, test = %.1f%%\n",
		train_hr*100., test_hr*100.);
	waitKey(0);
	getchar();
	return 0;
}
	




 参考链接:https://www.cnblogs.com/denny402/p/5032839.html

https://www.cnblogs.com/cheermyang/p/5624333.html

猜你喜欢

转载自blog.csdn.net/qq_35054151/article/details/83685461