int main() { const int sampleTypeCount = 7; //共有几种字体 const int sampleCount = 50; //每种字体的样本数 const int sampleAllCount = sampleCount*sampleTypeCount; const int featureCount = 256; //特征维数 CvANN_MLP bp;// = CvANN_MLP(layerSizes,CvANN_MLP::SIGMOID_SYM,1,1); string str_dir[sampleTypeCount]; str_dir[0] = "A水滴渍"; str_dir[1] = "B水纹"; str_dir[2] = "C指纹"; str_dir[3] = "D釉面凹凸"; str_dir[4] = "X凹点"; str_dir[5] = "Y杂质"; str_dir[6] = "Z划痕"; float trainingData[sampleAllCount][featureCount] = { 0 }; float outputData[sampleAllCount][sampleTypeCount] = { 0 }; int itemIndex = 0; for (int index = 0; index < 7; index++) { for (int i = 1; i <= 50; i++) { outputData[itemIndex][index] = 1; cout << str_dir[index] << "_" << i << endl; stringstream ss; char num[4]; sprintf(num, "%03d", i); ss << "特征样本库\\" << str_dir[index] << "\\" << num << ".jpg"; string path; ss >> path; //读取灰度图像以便计算灰度直方图 cv::Mat f = cv::imread(path, 0); cv::Mat grayHist; // 设定bin数目,也就是灰度级别,这里选择的是0-255灰度 int histSize = 256; //cv::equalizeHist(f, f); cv::normalize(f, f, histSize, 0, cv::NORM_MINMAX); //cv::bitwise_xor(f, cv::Scalar(255), f);//反相 FeatureMaker::GetGrayHist(f, grayHist, histSize); for (int j = 0; j < 256; j++) { trainingData[itemIndex][j] = grayHist.ptr<float>(j)[0]; } itemIndex++; } } //创建一个网络 cv::Mat layerSizes = (cv::Mat_<int>(1, 3) << featureCount, 25, sampleTypeCount);//创建一个featureCount输入 IDC_EDIT_YinCangCount隐藏 sampleTypeCount输出的三层网络 CvANN_MLP_TrainParams param; param.term_crit = cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 50000, 0.002); param.train_method = CvANN_MLP_TrainParams::BACKPROP; param.bp_dw_scale = 0.01;//权值更新率 param.bp_moment_scale = 0.03;//权值更新冲量 cv::Mat inputs(sampleAllCount, featureCount, CV_32FC1, trainingData);//样品总数,特征维数,储存的数据类型 cv::Mat outputs(sampleAllCount, sampleTypeCount, CV_32FC1, outputData); bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM); bp.train(inputs, outputs, cv::Mat(), cv::Mat(), param); bp.save("ANN_mlp.xml"); itemIndex = 0; int zhengque = 0; for (int index = 0; index < 7; index++) { for (int i = 1; i <= 50; i++) { cv::Mat sampleMat(1, featureCount, CV_32FC1, trainingData[itemIndex]);//样品总数,特征维数,储存的数据类型 cv::Mat nearest(1, sampleTypeCount, CV_32FC1, cv::Scalar(0)); bp.predict(sampleMat, nearest); float possibility = -1; int outindex = 0; for (int i = 0; i < nearest.size().width; i++){ float x = nearest.at<float>(0, i); if (x>possibility){ possibility = x; outindex = i; } } if (outindex == index) zhengque++; cout << str_dir[index] << "_" << i << ":" << outindex << "->" << possibility << "->" << str_dir[outindex] << endl; itemIndex++; } } cout << "正确率" << ((double)zhengque / (double)sampleAllCount); return 0; }
QList<int> Skeleton::possibleNumbers(QList<int> digitsOnField){ QList<int> list; /*if (listHoles.size() > 2 || listJunctions.size() > 5 || listLineEnds.size() > 5){ // certainly a bad 'catch' } if (listHoles.size() == 0){ if (listLineEnds.size() >= 2){ if (listLineEnds[0].x < 0.3 && listLineEnds[0].y < 0.3 && listLineEnds[1].x > 0.7 && listLineEnds[1].y > 0.7){ list.push_back(2); } else if (listLineEnds[0].x > 0.7 && listLineEnds[0].y < 0.3 && listLineEnds[1].y > 0.5){ list.push_back(5); } else if (listLineEnds[1].x < 0.4){ list.push_back(7); } else { list.push_back(1); } } else { list.push_back(1); list.push_back(2); list.push_back(5); list.push_back(7); } } else if (listHoles.size() == 1){ if (listHoles[0].x > 0.35 && listHoles[0].x < 0.65 && listHoles[0].y > 0.35 && listHoles[0].y < 0.65){ if (listJunctions.size() + listLineEnds.size() < 3){ list.push_back(0); } else { list.push_back(4); } } else if (listHoles.size() == 1 && listJunctions.size() >= 1 && listLineEnds.size() >= 1){ if (listHoles[0].y > listLineEnds[0].y){ list.push_back(6); } else { list.push_back(9); } } else { list.push_back(0); list.push_back(4); list.push_back(6); list.push_back(9); } } else if (listHoles.size() == 2){ list.push_back(8); } else { // if the 'number' is close to a 'normal' number, but not a perfect match, we try all of them for (int i = 0; i < TEMPLATES_COUNT; i++){ list.push_back(i); } }*/ if (HOLE_SEPARATION){ if (listHoles.size() == 0){ QList<int> zeroHole; zeroHole.push_back(1); zeroHole.push_back(2); zeroHole.push_back(3); zeroHole.push_back(5); zeroHole.push_back(7); int dim = Skeleton::getDim(M0); QList<double> vect = vectorization(M0); float sampleData[dim]; for (int i = 0; i < dim; i++){ sampleData[i] = vect[i]; } cv::Mat sampleMat(1, dim, CV_32FC1, sampleData); int maxVote = 0; int intMaxVote = -1; for (int i = 0; i < 10; i++){ int vote = 0; for (int j = 0; j < 10; j++){ if (i != j && zeroHole.contains(i) && zeroHole.contains(j)){ float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat); if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){ vote++; } } } //qDebug() << i << ": " << vote; if (vote > maxVote){ maxVote = vote; intMaxVote = i; } } if (intMaxVote == -1){ qDebug() << "Error : No vote is greater than 0"; } else { list.push_back(intMaxVote); } } else if (listHoles.size() == 1){ QList<int> oneHole; oneHole.push_back(0); oneHole.push_back(4); oneHole.push_back(6); oneHole.push_back(9); int dim = Skeleton::getDim(M1); QList<double> vect = vectorization(M1); float sampleData[dim]; for (int i = 0; i < dim; i++){ sampleData[i] = vect[i]; } cv::Mat sampleMat(1, dim, CV_32FC1, sampleData); int maxVote = 0; int intMaxVote = -1; for (int i = 0; i < 10; i++){ int vote = 0; for (int j = 0; j < 10; j++){ if (i != j && oneHole.contains(i) && oneHole.contains(j)){ float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat); if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){ vote++; } } } //qDebug() << i << ": " << vote; if (vote > maxVote){ maxVote = vote; intMaxVote = i; } } if (intMaxVote == -1){ qDebug() << "Error : No vote is greater than 0"; } else { list.push_back(intMaxVote); } } else if (listHoles.size() == 2){ list.push_back(8); } else { // if the 'number' is close to a 'normal' number, but not a perfect match, we try all of them for (int i = 0; i < TEMPLATES_COUNT; i++){ list.push_back(i); } } } else { int dim = Skeleton::getDim(M0); QList<double> vect = vectorization(M0); float sampleData[dim]; for (int i = 0; i < dim; i++){ sampleData[i] = vect[i]; } cv::Mat sampleMat(1, dim, CV_32FC1, sampleData); int maxVote = 0; int intMaxVote = -1; for (int i = 0; i < 10; i++){ int vote = 0; for (int j = 0; j < 10; j++){ if (i != j && digitsOnField.contains(i) && digitsOnField.contains(j)) { float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat); if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){ vote++; } } } //qDebug() << i << ": " << vote; if (vote > maxVote){ maxVote = vote; intMaxVote = i; } } if (intMaxVote == -1){ qDebug() << "Error : No vote is greater than 0"; } else { list.push_back(intMaxVote); } } return list; }
int main() { const int sampleTypeCount = 7; //共有几种字体 const int sampleCount = 50; //每种字体的样本数 const int sampleAllCount = sampleCount*sampleTypeCount; const int featureCount = 256; //特征维数 CvANN_MLP bp;// = CvANN_MLP(layerSizes,CvANN_MLP::SIGMOID_SYM,1,1); string str_dir[sampleTypeCount]; str_dir[0] = "A水滴渍"; str_dir[1] = "B水纹"; str_dir[2] = "C指纹"; str_dir[3] = "D釉面凹凸"; str_dir[4] = "X凹点"; str_dir[5] = "Y杂质"; str_dir[6] = "Z划痕"; float trainingData[sampleAllCount][featureCount] = { 0 }; float outputData[sampleAllCount][sampleTypeCount] = { 0 }; int itemIndex = 0; for (int index = 0; index < 7; index++) { for (int i = 1; i <= 50; i++) { outputData[itemIndex][index] = 1; cout << str_dir[index] << "_" << i << endl; stringstream ss; char num[4]; sprintf(num, "%03d", i); ss << "特征样本库\\" << str_dir[index] << "\\" << num << ".jpg"; string path; ss >> path; //读取灰度图像以便计算灰度直方图 cv::Mat f = cv::imread(path, 0); cv::Mat grayHist; // 设定bin数目,也就是灰度级别,这里选择的是0-255灰度 int histSize = 63; //cv::equalizeHist(f, f); cv::normalize(f, f, histSize, 0, cv::NORM_MINMAX); //cv::bitwise_xor(f, cv::Scalar(255), f);//反相 // 设定取值范围,设定每级灰度的范围。 float range[] = { 0, 255 }; const float* histRange = { range }; bool uniform = true; bool accumulate = false; cv::calcHist(&f, 1, 0, cv::Mat(), grayHist, 1, &histSize, &histRange, uniform, accumulate); for (int j = 0; j < 256; j++) { trainingData[itemIndex][j] = grayHist.ptr<float>(0)[0]; } itemIndex++; /* // 创建直方图画布 int hist_w = 400; int hist_h = 400; int bin_w = cvRound((double)hist_w / histSize); cv::Mat histImage(hist_w, hist_h, CV_8UC3, cv::Scalar(0, 0, 0)); /// 将直方图归一化到范围 [ 0, histImage.rows ] cv::normalize(grayHist, grayHist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat()); /// 在直方图画布上画出直方图 for (int i = 1; i < histSize; i++) { line(histImage, cv::Point(bin_w*(i - 1), hist_h - cvRound(grayHist.at<float>(i - 1))), cv::Point(bin_w*(i), hist_h - cvRound(grayHist.at<float>(i))), cv::Scalar(0, 0, 255), 2, 8, 0); } stringstream s; s << "samples\\反相正规化直方图\\" << str_dir[index] << "\\"; //s << "samples\\正规化直方图\\" << str_dir[index] << "\\"; //s << "samples\\均衡化直方图\\" << str_dir[index] << "\\"; //s << "samples\\直方图\\" << str_dir[index] << "\\"; //string dir = s.str(); //char* c; //int len = dir.length(); //c = new char[len + 1]; //strcpy(c, dir.c_str()); //CheckDir(c); s << "" << num << ".jpg"; s >> path; cv::imwrite(path, histImage); s.clear(); s << "samples\\反相正规化直方图\\" << str_dir[index] << "\\" << "Hist_" << num << ".jpg"; //s << "samples\\正规化直方图\\" << str_dir[index] << "\\" << "Hist_" << num << ".jpg"; //s << "samples\\均衡化直方图\\" << str_dir[index] << "\\" << "Hist_" << num << ".jpg"; //s << "samples\\直方图\\" << str_dir[index] << "\\" << "Hist_" << num << ".jpg"; s >> path; cv::imwrite(path, grayHist); /// 显示直方图 //cv::namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE); //cv::imshow("calcHist Demo", histImage); //cv::waitKey(0); */ } } //创建一个网络 cv::Mat layerSizes = (cv::Mat_<int>(1, 3) << featureCount, 25, sampleTypeCount);//创建一个featureCount输入 IDC_EDIT_YinCangCount隐藏 sampleTypeCount输出的三层网络 CvANN_MLP_TrainParams param; param.term_crit = cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 5000, 0.01); param.train_method = CvANN_MLP_TrainParams::BACKPROP; param.bp_dw_scale = 0.2; param.bp_moment_scale = 0.1; cv::Mat inputs(sampleAllCount, featureCount, CV_32FC1, trainingData);//样品总数,特征维数,储存的数据类型 cv::Mat outputs(sampleAllCount, sampleTypeCount, CV_32FC1, outputData); bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM); bp.train(inputs, outputs, cv::Mat(), cv::Mat(), param); bp.save("ANN_mlp.xml"); itemIndex = 0; for (int index = 0; index < 7; index++) { for (int i = 1; i <= 50; i++) { cv::Mat sampleMat(1, featureCount, CV_32FC1, trainingData[itemIndex]);//样品总数,特征维数,储存的数据类型 cv::Mat nearest(1, sampleTypeCount, CV_32FC1, cv::Scalar(0)); bp.predict(sampleMat, nearest); float possibility = -1; int outindex = 0; for (int i = 0; i < nearest.size().width; i++){ float x = nearest.at<float>(0, i); if (x>possibility){ possibility = x; outindex = i; } } cout << str_dir[index] << "_" << i << ":" << outindex << "->" << possibility << "->" << str_dir[outindex] << endl; itemIndex++; } } return 0; }