test_sample = test_set.row(tsample);
//分类器的输出
nnetwork.predict(test_sample, classificationResult);
//输出向量中最大的值即为样本所属的类
// 以下的工作就是找到最大的数是哪个
int maxIndex = 0;
float value=0.0f;
float maxValue=classificationResult.at<float>(0,0);
for(int index=1;index<CLASSES;index++)
{
value = classificationResult.at<float>(0,index);
if(value>maxValue)
{
maxValue = value;
maxIndex=index;
}
}
printf("Testing Sample %i -> class result (digit %d)\n", tsample, maxIndex);
#include <opencv2/opencv.hpp>
#include <string.h>
#include <fstream>
#include <stdio.h>
using namespace std;
using namespace cv;
#define ATTRIBUTES 135 //每一个样本的像素总数.9X15
#define CLASSES 10
#define TRAINING_SAMPLES 460
#define TEST_SAMPLES 200
//将int型转为string型
string convertInt(int number)
{
stringstream ss;
ss << number;
return ss.str();
}
//将图像矩阵转为一个向量
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<uchar>(x,y)==255)?1:0;
i++;
}
}
}
//读取样本集,并将样本集按照一个样本一行的形式写入一个文件
void readFile(string datasetPath,int samplesPerClass,string outputfile )
{
fstream file(outputfile.c_str(),ios::out);
for(int sample = 1; sample<=samplesPerClass;sample++)
{
for(int digit=0;digit<10;digit++)
{ //构建图像路径
string imagePath = datasetPath+convertInt(digit)+"\\"+convertInt(sample)+".bmp";
Mat img = imread(imagePath,0);
Mat output;
int pixelValueArray[135];
//图像矩阵转为向量
convertToPixelValueArray(img,pixelValueArray);
//将这个向量写入文件
for(int d=0;d<135;d++){
file<<pixelValueArray[d]<<",";
}
//将所属类别写入文件(行尾)
file<<digit<<"\n";
}
}
file.close();
}
//从样本集生成的文件中读取数据
void read_dataset(char *filename, Mat &data, Mat &classes, int total_samples)
{
int label;
float pixelvalue;
FILE* inputfile = fopen( filename, "r" );
for(int row = 0; row < total_samples; row++)
{
for(int col = 0; col <=ATTRIBUTES; col++)
{
if (col < ATTRIBUTES){
fscanf(inputfile, "%f,", &pixelvalue);
data.at<float>(row,col) = pixelvalue;
}
else if (col == ATTRIBUTES){
//输出向量的结构是应属类别的位置赋值为1,其余赋值为0
fscanf(inputfile, "%i", &label);
classes.at<float>(row,label) = 1.0;
}
}
}
fclose(inputfile);
}
int main( int argc, char** argv )
{
readFile("E:\\workdir\\NN\\character_train\\",46,"E:\\workdir\\NN\\trainingset.txt");
readFile("E:\\workdir\\NN\\character_test\\",20,"E:\\workdir\\NN\\testset.txt");
//训练样本集构成的矩阵
Mat training_set(TRAINING_SAMPLES,ATTRIBUTES,CV_32F);
//训练样本集的标签(输出向量)构成的矩阵
Mat training_set_classifications(TRAINING_SAMPLES, CLASSES, CV_32F,Scalar(-1));
//测试样本集构成的矩阵
Mat test_set(TEST_SAMPLES,ATTRIBUTES,CV_32F);
//测试样本集的标签(输出向量)构成的矩阵
Mat test_set_classifications(TEST_SAMPLES,CLASSES,CV_32F,Scalar(-1));
//
Mat classificationResult(1, CLASSES, CV_32F);
read_dataset("E:\\workdir\\NN\\trainingset.txt", training_set, training_set_classifications, TRAINING_SAMPLES);
read_dataset("E:\\workdir\\NN\\testset.txt", test_set, test_set_classifications, TEST_SAMPLES);
// 定义MLP的结构
// 神经网络总共有三层
// - 135输入节点
// - 16 隐藏节点
// - 10 输出节点.
cv::Mat layers(3,1,CV_32S);
layers.at<int>(0,0) = ATTRIBUTES;//input layer
layers.at<int>(1,0)=16;//hidden layer
layers.at<int>(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);
// 对生成的模型进行测试.
cv::Mat test_sample;
int correct_class = 0;
int wrong_class = 0;
//分类矩阵记录某个样本分到某类的次数.
int classification_matrix[CLASSES][CLASSES]={{}};
for (int tsample = 0; tsample < TEST_SAMPLES; tsample++)
{
test_sample = test_set.row(tsample);
//分类器的输出
nnetwork.predict(test_sample, classificationResult);
//输出向量中最大的值即为样本所属的类
// 以下的工作就是找到最大的数是哪个
int maxIndex = 0;
float value=0.0f;
float maxValue=classificationResult.at<float>(0,0);
for(int index=1;index<CLASSES;index++)
{
value = classificationResult.at<float>(0,index);
if(value>maxValue)
{
maxValue = value;
maxIndex=index;
}
}
printf("Testing Sample %i -> class result (digit %d)\n", tsample, maxIndex);
//现在比较神经网络的预测结果与真实结果. 如果分类正确
//test_set_classifications[tsample][ maxIndex] 应该是 1.
//如果分类错误, 记录下来.
if (test_set_classifications.at<float>(tsample, maxIndex)!=1.0f)
{
wrong_class++;
//标记分类矩阵
for(int class_index=0;class_index<CLASSES;class_index++)
{
if(test_set_classifications.at<float>(tsample, class_index)==1.0f)
{
classification_matrix[class_index][maxIndex]++;// A class_index sample was wrongly classified as maxindex.
break;
}
}
}
else
{
correct_class++;
classification_matrix[maxIndex][maxIndex]++;
}
}
//输出测试结果
printf( "\nResults on the testing dataset\n"
"\tCorrect classification: %d (%g%%)\n"
"\tWrong classifications: %d (%g%%)\n",
correct_class, (double) correct_class*100/TEST_SAMPLES,
wrong_class, (double) wrong_class*100/TEST_SAMPLES);
cout<<" ";
for (int i = 0; i < CLASSES; i++)
{
cout<< i<<"\t";
}
cout<<"\n";
for(int row=0;row<CLASSES;row++)
{
cout<<row<<" ";
for(int col=0;col<CLASSES;col++)
{
cout<<classification_matrix[row][col]<<"\t";
}
cout<<"\n";
}
return 0;
}原文:http://blog.csdn.net/qq_18515405/article/details/43057545