|
|
|
|
// 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;
|
|
|
|
|
}
|