You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
EasyPR/train/ann_train.cpp

316 lines
8.2 KiB

// Main entry code OpenCV
#include <opencv/cv.h>
#include <opencv/cvaux.h>
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <windows.h>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#define HORIZONTAL 1
#define VERTICAL 0
using namespace std;
using namespace cv;
CvANN_MLP ann;
//<2F>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>
const char strCharacters[] = {'0','1','2','3','4','5',\
'6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* û<><C3BB>I */\
'J', 'K', 'L', 'M', 'N', /* û<><C3BB>O */ 'P', 'Q', 'R', 'S', 'T', \
'U','V', 'W', 'X', 'Y', 'Z'};
const int numCharacter = 34; /* û<><C3BB>I<EFBFBD><49>0,10<31><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>24<32><34>Ӣ<EFBFBD><D3A2><EFBFBD>ַ<EFBFBD>֮<EFBFBD><D6AE> */
//<2F><><EFBFBD><EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD>ѵ<EFBFBD><D1B5>ʱ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><E6A3AC>Щʡ<D0A9><CAA1>û<EFBFBD><C3BB>ѵ<EFBFBD><D1B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ַ<EFBFBD>
//<2F><>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>ı<EFBFBD>ʾ<EFBFBD><CABE>ѵ<EFBFBD><D1B5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>һ<EFBFBD>ֱ<EFBFBD><D6B1>Σ<EFBFBD>Ҳ<EFBFBD><D2B2>Ϊѵ<CEAA><D1B5><EFBFBD><EFBFBD><EFBFBD>ݴ洢
const string strChinese[] = {"zh_cuan" /* <20><> */, "zh_e" /* <20><> */, "zh_gan" /* <20><>*/, \
"zh_hei" /* <20><> */, "zh_hu" /* <20><> */, "zh_ji" /* <20><> */, \
"zh_jl" /* <20><> */, "zh_jin" /* <20><> */, "zh_jing" /* <20><> */, "zh_shan" /* <20><> */, \
"zh_liao" /* <20><> */, "zh_lu" /* ³ */, "zh_min" /* <20><> */, "zh_ning" /* <20><> */, \
"zh_su" /* <20><> */, "zh_sx" /* <20><> */, "zh_wan" /* <20><> */,\
"zh_yu" /* ԥ */, "zh_yue" /* <20><> */, "zh_zhe" /* <20><> */};
const int numChinese = 20;
const int numAll = 54; /* 34+20=54 */
const int numNeurons = 20;
const int predictSize = 10;
//create the accumulation histograms,img is a binary image, t is ˮƽ<CBAE><C6BD><EFBFBD><EFBFBD>ֱ
Mat ProjectedHistogram(Mat img, int t)
{
int sz=(t)?img.rows:img.cols;
Mat mhist=Mat::zeros(1,sz,CV_32F);
for(int j=0; j<sz; j++){
Mat data=(t)?img.row(j):img.col(j);
mhist.at<float>(j)=countNonZero(data); //ͳ<><CDB3><EFBFBD><EFBFBD>һ<EFBFBD>л<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĸ<D8B5><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>浽mhist<73><74>
}
//Normalize histogram
double min, max;
minMaxLoc(mhist, &min, &max);
if(max>0)
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//<2F><>mhistֱ<74><D6B1>ͼ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ֱ<EFBFBD><D6B1>ͼ
return mhist;
}
Mat features(Mat in, int sizeData){
//Histogram features
Mat vhist=ProjectedHistogram(in,VERTICAL);
Mat hhist=ProjectedHistogram(in,HORIZONTAL);
//Low data feature
Mat lowData;
resize(in, lowData, Size(sizeData, sizeData) );
//Last 10 is the number of moments components
int numCols=vhist.cols+hhist.cols+lowData.cols*lowData.cols;
Mat out=Mat::zeros(1,numCols,CV_32F);
//Asign values to feature,ANN<4E><4E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊˮƽ<CBAE><C6BD><EFBFBD><EFBFBD>ֱֱ<D6B1><D6B1>ͼ<EFBFBD>͵ͷֱ<CDB7><D6B1><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD>ʸ<EFBFBD><CAB8>
int j=0;
for(int i=0; i<vhist.cols; i++)
{
out.at<float>(j)=vhist.at<float>(i);
j++;
}
for(int i=0; i<hhist.cols; i++)
{
out.at<float>(j)=hhist.at<float>(i);
j++;
}
for(int x=0; x<lowData.cols; x++)
{
for(int y=0; y<lowData.rows; y++){
out.at<float>(j)=(float)lowData.at<unsigned char>(x,y);
j++;
}
}
//if(DEBUG)
// cout << out << "\n===========================================\n";
return out;
}
void getFiles(string path, vector<string>& files )
{
//<2F>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
long hFile = 0;
//<2F>ļ<EFBFBD><C4BC><EFBFBD>Ϣ
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1)
{
do
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼,<2C><><EFBFBD><EFBFBD>֮
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
if((fileinfo.attrib & _A_SUBDIR))
{
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0)
getFiles( p.assign(path).append("\\").append(fileinfo.name), files );
}
else
{
files.push_back(p.assign(path).append("\\").append(fileinfo.name) );
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
void annTrain(Mat TrainData, Mat classes, int nNeruns)
{
ann.clear();
Mat layers(1, 3, CV_32SC1);
layers.at<int>(0) = TrainData.cols;
layers.at<int>(1) = nNeruns;
layers.at<int>(2) = numAll;
ann.create(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);
//Prepare trainClases
//Create a mat with n trained data by m classes
Mat trainClasses;
trainClasses.create( TrainData.rows, numAll, CV_32FC1 );
for( int i = 0; i < trainClasses.rows; i++ )
{
for( int k = 0; k < trainClasses.cols; k++ )
{
//If class of data i is same than a k class
if( k == classes.at<int>(i) )
trainClasses.at<float>(i,k) = 1;
else
trainClasses.at<float>(i,k) = 0;
}
}
Mat weights( 1, TrainData.rows, CV_32FC1, Scalar::all(1) );
//Learn classifier
ann.train( TrainData, trainClasses, weights );
}
int saveTrainData()
{
cout << "Begin saveTrainData" << endl;
Mat classes;
Mat trainingDataf5;
Mat trainingDataf10;
Mat trainingDataf15;
Mat trainingDataf20;
vector<int> trainingLabels;
string path = "train/data/chars_recognise_ann/chars2/chars2";
for(int i = 0; i < numCharacter; i++)
{
cout << "Character: "<< strCharacters[i] << "\n";
stringstream ss(stringstream::in | stringstream::out);
ss << path << "/" << strCharacters[i];
vector<string> files;
getFiles(ss.str(), files);
int size = files.size();
for (int j = 0; j < size; j++)
{
cout << files[j].c_str() << endl;
Mat img = imread(files[j].c_str(), 0);
Mat f5=features(img, 5);
Mat f10=features(img, 10);
Mat f15=features(img, 15);
Mat f20=features(img, 20);
trainingDataf5.push_back(f5);
trainingDataf10.push_back(f10);
trainingDataf15.push_back(f15);
trainingDataf20.push_back(f20);
trainingLabels.push_back(i); //ÿһ<C3BF><D2BB><EFBFBD>ַ<EFBFBD>ͼƬ<CDBC><C6AC><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>
}
}
path = "train/data/chars_recognise_ann/charsChinese/charsChinese";
for (int i = 0; i < numChinese; i++)
{
cout << "Character: "<< strChinese[i] << "\n";
stringstream ss(stringstream::in | stringstream::out);
ss << path << "/" << strChinese[i];
vector<string> files;
getFiles(ss.str(), files);
int size = files.size();
for (int j = 0; j < size; j++)
{
cout << files[j].c_str() << endl;
Mat img = imread(files[j].c_str(), 0);
Mat f5=features(img, 5);
Mat f10=features(img, 10);
Mat f15=features(img, 15);
Mat f20=features(img, 20);
trainingDataf5.push_back(f5);
trainingDataf10.push_back(f10);
trainingDataf15.push_back(f15);
trainingDataf20.push_back(f20);
trainingLabels.push_back(i + numCharacter);
}
}
trainingDataf5.convertTo(trainingDataf5, CV_32FC1);
trainingDataf10.convertTo(trainingDataf10, CV_32FC1);
trainingDataf15.convertTo(trainingDataf15, CV_32FC1);
trainingDataf20.convertTo(trainingDataf20, CV_32FC1);
Mat(trainingLabels).copyTo(classes);
FileStorage fs("train/ann_data.xml", FileStorage::WRITE);
fs << "TrainingDataF5" << trainingDataf5;
fs << "TrainingDataF10" << trainingDataf10;
fs << "TrainingDataF15" << trainingDataf15;
fs << "TrainingDataF20" << trainingDataf20;
fs << "classes" << classes;
fs.release();
cout << "End saveTrainData" << endl;
return 0;
}
void saveModel(int _predictsize, int _neurons)
{
FileStorage fs;
fs.open("train/ann_data.xml", FileStorage::READ);
Mat TrainingData;
Mat Classes;
string training;
if(1)
{
stringstream ss(stringstream::in | stringstream::out);
ss << "TrainingDataF" << _predictsize;
training = ss.str();
}
fs[training] >> TrainingData;
fs["classes"] >> Classes;
//train the Ann
cout << "Begin to saveModelChar predictSize:" << _predictsize
<< " neurons:" << _neurons << endl;
double start = GetTickCount();
annTrain(TrainingData, Classes, _neurons);
double end = GetTickCount();
cout << "GetTickCount:" << (end-start)/1000 << endl;
cout << "End the saveModelChar" << endl;
string model_name = "train/ann.xml";
//if(1)
//{
// stringstream ss(stringstream::in | stringstream::out);
// ss << "ann_prd" << _predictsize << "_neu"<< _neurons << ".xml";
// model_name = ss.str();
//}
FileStorage fsTo(model_name, cv::FileStorage::WRITE);
ann.write(*fsTo, "ann");
}
int main()
{
cout << "To be begin." << endl;
saveTrainData();
//<2F>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD>Ҫѵ<D2AA><D1B5><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>predictSize<7A><65><EFBFBD><EFBFBD>neurons<6E><73>ANNģ<4E><C4A3>
//for (int i = 2; i <= 2; i ++)
//{
// int size = i * 5;
// for (int j = 5; j <= 10; j++)
// {
// int neurons = j * 10;
// saveModel(size, neurons);
// }
//}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾֻѵ<D6BB><D1B5>model<65>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>µ<EFBFBD>ann.xml<6D><6C><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>predictSize=10,neurons=40<34><30>ANNģ<4E>͡<EFBFBD>
//<2F><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD>IJ<EFBFBD>ͬ<EFBFBD><CDAC>ѵ<EFBFBD><D1B5>ʱ<EFBFBD>һ<E4B2BB><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ҫ10<31><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD><D2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ɡ<EFBFBD>
saveModel(10, 40);
cout << "To be end." << endl;
int end;
cin >> end;
return 0;
}