使用OpenCV的ANN_MLP神经网络实现数字识别
生活随笔
收集整理的这篇文章主要介绍了
使用OpenCV的ANN_MLP神经网络实现数字识别
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
前言
1.OpenCV中的ML模块实现了前馈人工神经网络,具体地说是多层感知器(MLP),是最常用的神经网络类型。 MLP由输入层,输出层和一个或多个隐藏层组成。 MLP的每一层包括一个或多个与来自上一层和下一层的神经元定向连接的神经元。关于ANN_MLP的具体说明可以看opencv的官方文档。
2.我这里要是使用ANN_MLP神经网络来实现0到9的印刷数字识别,使用的OpenCV版本是3.30,IDE是VS2015,实现语言是C++,还使用了boost来进行文件读取的相关操作。
样本准备
1.先准备0到9的样本,分别放在相应的文件目录下,这是我保存的格式:
2.每个目录下放着对的样本,我这里每个字母都有50个样本,对应的文件没有特殊要求。
代码
1.训练代码
//训练函数 //root_path样本地址 //model_path保存模型路径加文件名,后续为xml void trainChar(string &root_path, string &model_path) {vector<string> dir_path;int dir_number;getFileNameFromDir(root_path, dir_path, dir_number);//图像的行const int image_rows = 8;//图像的列const int image_cols = 16;//要训练的类别const int class_sum = 10;//每个类别的样本个数const int images_sum = 50;if (dir_number != class_sum){cout << "要训练的种类与当前目录下的种类和差异!" << endl;return;}//每一行一个训练样本float trainingData[class_sum*images_sum][image_rows*image_cols] = { { 0 } };//训练样本标签float labels[class_sum*images_sum][class_sum] = { { 0 } };Mat src, resize_img, train_img;//这里读文件的方式不是很好,用boost会好一些for (int i = 0; i < dir_path.size(); i++){//cout << dir_path.at(i) << endl;int k = 0;fs::directory_iterator begin_iter(dir_path.at(i));fs::directory_iterator end_iter;//获取该目录下的所有文件名for (; begin_iter != end_iter; ++begin_iter){string image_path = begin_iter->path().string();src = imread(image_path, 0);if (src.empty()){cerr << "can not load image \n" << std::endl;exit(0);}//更改尺寸resize(src, resize_img, Size(image_rows, image_cols), (0, 0), (0, 0), INTER_AREA);//二值化threshold(resize_img, train_img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);for (int j = 0; j < image_rows*image_cols; j++){trainingData[i*images_sum + k][j] = (float)resize_img.data[j];}// 设置标签数据for (int j = 0; j < class_sum; j++){if (j == i){labels[i*images_sum + k][j] = 1;}else{labels[i*images_sum + k][j] = 0;}}k++;}Mat labelsMat(class_sum*images_sum, class_sum, CV_32FC1, labels);}//训练数据及标签Mat trainingDataMat(class_sum*images_sum, image_rows*image_cols, CV_32FC1, trainingData);Mat labelsMat(class_sum*images_sum, class_sum, CV_32FC1, labels);//设置参数Ptr<ANN_MLP>model = ANN_MLP::create();Mat layerSizes = (Mat_<int>(1, 5) << image_rows*image_cols, 128, 128, 128, class_sum);model->setLayerSizes(layerSizes);//训练方法为反向传播(这个跟深度学习的反向转播是一个道理)model->setTrainMethod(ANN_MLP::BACKPROP, 0.001, 0.1);// 激活函数设置为 sigmoidmodel->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1.0, 1.0);model->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, 10000, 0.0001));cout << "开始训练!" << endl;Ptr<TrainData> trainData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);model->train(trainData);//保存模型model->save(model_path);cout << "训练完成" << endl; }//得到路径下第一层的文件夹的绝对路径 void getFileNameFromDir(string &root_path,vector<string> &dir_path, int &class_sum) {class_sum = 0;vector<string> dir_name;fs::path dir(root_path);// 判断路径是否存在if (fs::exists(dir)){fs::directory_iterator itEnd;fs::directory_iterator itDir(dir);string file_name;// 遍历路径下所有文件for (; itDir != itEnd; itDir++){file_name = itDir->path().string();// 判断文件是否是文件夹if (boost::filesystem::is_directory(file_name.c_str())){dir_path.push_back(file_name);class_sum++; }}} }训练代码调用方式:
//保存字符集的主目录 string char_path = "C:/code/DigitalRecognition/DigitalRecognition/numberChar/"; //训练好的模型保存的路径和文件名 string model_path = "C:/code/DigitalRecognition/DigitalRecognition/numberCharModel.xml"; trainChar(char_path,model_path);2.测试代码
//测试模型 //src是要识别的图像 //model_path模型的路径 void useModel(Mat &src, string &model_path) {if (src.empty()){cout << "当前传入的图像为空!" << endl;return;}if (src.channels() > 1){cvtColor(src, src, CV_BGR2GRAY);}Mat dst;//图像的行const int image_rows = 8;//图像的列const int image_cols = 16;Ptr<ANN_MLP>model = ANN_MLP::create();model = cv::Algorithm::load<cv::ml::ANN_MLP>(model_path);//将测试图像转化为1*128的向量resize(src, src, Size(image_rows, image_cols), (0, 0), (0, 0), INTER_AREA);threshold(src, src, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);Mat_<float> testMat(1, image_rows*image_cols);for (int i = 0; i < image_rows*image_cols; i++){testMat.at<float>(0, i) = (float)src.at<uchar>(i / 8, i % 8);}//使用训练好的MLP model预测测试图像,把预测到的值放到dst里面model->predict(testMat, dst);cout << "dst:" << dst << endl;//选出最大值double maxVal = 0;Point maxLoc;minMaxLoc(dst, NULL, &maxVal, NULL, &maxLoc);cout << "测试结果:" << maxLoc.x << "置信度:" << maxVal * 100 << "%" << endl; }测试代码调用方式:
//训练好的模型保存的路径和文件名 string model_path = "C:/code/DigitalRecognition/DigitalRecognition/numberCharModel.xml"; //读取图像 Mat src = imread("src.png"); useModel(src,model_path);运行结果:
结语
1.上面的所用到的样本,可以从我的资源上传那里得到。
2.如果在运行中有什么bug,可以找我之前的博客,下面有推荐的群,互相讨论学习。
总结
以上是生活随笔为你收集整理的使用OpenCV的ANN_MLP神经网络实现数字识别的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: OpenCV图像增强(三)——自适应对数
- 下一篇: 使用OpenCV进行身份证号码字符进行分