【opencv3--ANN神經網路訓練識別OCR資料集】
阿新 • • 發佈:2018-11-05
#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