OpenCV OpenGL手写字符识别
另外一篇文章地址:这个比较详细,但是程序略显简单,现在这个程序是比较复杂的
http://blog.csdn.net/wangyaninglm/article/details/17091901
整个项目下载地址:
http://download.csdn.net/detail/wangyaninglm/8244549
实现效果:
Finger.h
#ifndef __TOUCHSCREEN_FINGER__
#define __TOUCHSCREEN_FINGER__ #include <cxcore.h>
#include <vector> class Finger
{
public:
Finger()
{
area = 0.0f;
w=h=0;
};
public:
CvPoint center;
float area;
float w;
float h;
}; //typedef std::vector<Finger> FingerTrack; class FingerTrack
{
public:
FingerTrack()
{
states=0;
lostCount =0;
}
std::vector<Finger> track;
int states;
int lostCount; }; #endif
MachineLearning.h
#include <cxcore.h>
#include <cv.h>
#include <ml.h>
#include <string>
using namespace std ;
class MachineLearning
{
enum TraningMethod
{
RandomTrees,
Boosting,
NeuralNetworks,
SVM
}; public:
bool getCrossFeature(IplImage *img,float featureData[]);
bool predict(char &shape_type,float featureData[]);
bool load(const char *training_filename);
bool train(const char *data_filename,const char *save_filename);
MachineLearning(void);
void ExtractDFT(float pcadata[],const int featureData[],const int &dataWidth,const int &DFTwidth);
int DataCount; private:
static const int CROSS_COLS = 50;
static const int CROSS_ROWS = 50;
void getCrossFeatureData(IplImage *img_cross,int featureData[],const int &cols,const int &rows );
void getDistanceFeatureData(IplImage *img_cross,int featureData[],const int &cols,const int &rows );
void getCrossCenter(IplImage *img_cross,int &cx,int &cy);
void getCrossSpecifyArea(IplImage *img_cross,CvRect &specifie_rect);
void ExtractPCA(float pcadata[],const int featureData[],const int &dataWidth ); bool is_load_training_model;
TraningMethod traning_method;
int read_num_class_data( const char* filename, int var_count,CvMat** data, CvMat** responses);
int build_rtrees_classifier(const char* data_filename,const char* filename_to_save,const char* filename_to_load);
int build_boost_classifier( char* data_filename,char* filename_to_save, char* filename_to_load );
int build_mlp_classifier( char* data_filename,char* filename_to_save, char* filename_to_load );
int build_svm_classifier( char* data_filename,char* filename_to_save, char* filename_to_load ); CvRTrees forest;
int predict_rtrees_classifier(CvMat *sample_data,char &shape_type); };
machinelearning.cpp
/*************************************************
Copyright (C)
File name:
Author: Hardy
Version: 1.0
Date: 2007-3-5
Description: 模式识别部分,提取特征数据,训练模型,预测结果
Others:
Function List:
History:
1. Date:
Author:
Modification:
2. ...
************************************************/ #include "stdafx.h"
#include "MachineLearning.h"
#include <highgui.h>
#include <iostream>
#include <fstream> MachineLearning::MachineLearning(void)
{
is_load_training_model = false;
traning_method = RandomTrees;
} bool MachineLearning::getCrossFeature(IplImage *img,float pcaData[])
/*************************************************
Function:
Description: 样本数据载入
Date: 2007-3-5
Author:
Input:
Output:
Return:
Others:
*************************************************/
{ assert(img); ////计算图形所在矩形
//int cx,cy;
//getCrossCenter(img,cx,cy);
//CvRect roiRect;
//getCrossSpecifyArea(img,roiRect); //assert(roiRect.x>0);
//assert(roiRect.y>0);
//assert(roiRect.height>0 && roiRect.height < img->width);
//assert(roiRect.width>0 && roiRect.width < img->width );
//cvSetImageROI(img,roiRect); //IplImage *img_copy = cvCreateImage(cvSize(100,100) , 8, 1 );
//img_copy->origin = img->origin;
//cvZero(img_copy);
//cvResize(img,img_copy,CV_INTER_NN);
//cvResetImageROI(img); //计算形心
int cx,cy;
getCrossCenter(img,cx,cy); assert(cx<img->width);
assert(cx>0);
assert(cy<img->height);
assert(cy>0); int shift_x = img->width/2 - cx;
int shift_y = img->height/2 - cy; IplImage *img_copy = cvCreateImage(cvGetSize(img) , 8, 1 );
img_copy->origin = img->origin;
cvZero(img_copy); //移动图形到中心
for(int i = 0; i<img->width;i++)
{
for(int j = 0; j<img->height;j++)
{
CvScalar c = cvGetAt(img,j,i);
int v = (int)c.val[0];
if(v==255)
{
int nj=j+shift_y;
int ni=i+shift_x;
if(nj<img->height && ni<img->width)
if(nj>=0 && ni>=0)
cvSet2D(img_copy,nj,ni,c);
}
}
} //计算密度特征数据--------------
//int featureData[CROSS_ROWS + CROSS_COLS];
//memset(featureData,-1,sizeof(featureData));
//getCrossFeatureData(img_copy,featureData,CROSS_COLS,CROSS_ROWS);
////std::cout<<"--------------------------------------------"<<std::endl;
////cvShowImage("WIN1",img_copy);
////cvWaitKey(0);
//float CrossData[10];
//ExtractPCA(CrossData,featureData,CROSS_COLS+CROSS_ROWS);
// //计算距离特征数据
int featureDisData[2*CROSS_ROWS + CROSS_COLS];
memset(featureDisData,-1,sizeof(featureDisData));
getDistanceFeatureData(img_copy,featureDisData,CROSS_COLS,CROSS_ROWS);
float DistanceData[10];
ExtractPCA(DistanceData,featureDisData,CROSS_COLS+2*CROSS_ROWS); //合并特征数据
//for(int i=0;i<5;i++) pcaData[i] = CrossData[i];
//for(int i=5;i<10;i++) pcaData[i] = DistanceData[i-5];
for(int i=0;i<10;i++) pcaData[i] = DistanceData[i]; cvReleaseImage(&img_copy); return true;
} void MachineLearning::getCrossFeatureData(IplImage *img_cross,int featureData[],const int &cols,const int &rows)
/*************************************************
Function:
Description: 穿线得到特征数据
Date: 2007-3-5
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
const int CROSS_VALID_LENGTH = 6; //在6个象素内不计算穿越数目,避免噪音
CvScalar c; for(int cross_index=0;cross_index<rows;cross_index++)
{
int y = (int)(img_cross->height*((float)cross_index/rows)); //按照比例决定位置 int cross_count = 0;
int pre_v = -1;
int pre_x = 0;
for(int x =0;x<img_cross->width;x++)
{
c = cvGetAt(img_cross,y,x);
int v = (int)c.val[0];
if(pre_v==255 && v==0)
if((x-pre_x)>CROSS_VALID_LENGTH)
{
cross_count++;
pre_x = x;
}
pre_v = v; } //cout<<cross_count<<",";
featureData[cross_index] = cross_count; } for(int cross_index=0;cross_index<cols;cross_index++)
{
int x = (int)(img_cross->width*((float)cross_index/cols)); int cross_count = 0;
int pre_v = -1;
int pre_y = 0;
for(int y =0;y<img_cross->height;y++)
{ c = cvGetAt(img_cross,y,x);
int v = (int)c.val[0];
if(pre_v==255 && v==0)
if((y-pre_y)>CROSS_VALID_LENGTH)
{
cross_count++;
pre_y = y;
} pre_v = v;
} //cout<<cross_count<<",";
featureData[rows+cross_index] = cross_count;
} } void MachineLearning::getDistanceFeatureData(IplImage *img_cross,int featureData[],const int &cols,const int &rows)
/*************************************************
Function:
Description: 穿线得到距离特征数据
Date: 2007-3-9
Author:
Input:
Output:
Return:
Others:
*************************************************/
{ CvScalar c; //从左向右穿线
for(int cross_index=0;cross_index<rows;cross_index++)
{
int y = (int)(img_cross->height*((float)cross_index/rows)); //按照比例决定位置
int meet_x = 0;
for(int x =0;x<img_cross->width;x++)
{
c = cvGetAt(img_cross,y,x);
int v = (int)c.val[0];
if(v==255)
{
meet_x = x;
break;
}
}
//cout<<meet_x<<",";
featureData[cross_index] = meet_x;
} //从右向左穿线
for(int cross_index=rows;cross_index<2*rows;cross_index++)
{
int y = (int)(img_cross->height*((float)(cross_index-rows)/rows)); //按照比例决定位置
int meet_x = 0;
for(int x =(img_cross->width-1);x>-1;x--)
{
c = cvGetAt(img_cross,y,x);
int v = (int)c.val[0];
if(v==255)
{
meet_x = x;
break;
}
}
//cout<<meet_x<<",";
featureData[cross_index] = meet_x;
} //从下向上穿线
for(int cross_index=0;cross_index<cols;cross_index++)
{
int x = (int)(img_cross->width*((float)cross_index/cols)); int meet_y = 0;
for(int y =(img_cross->height-1);y>-1;y--)
{ c = cvGetAt(img_cross,y,x);
int v = (int)c.val[0];
if(v==255)
{
meet_y = y;
break;
}
}
//cout<<meet_y<<",";
featureData[2*rows+cross_index] = meet_y;
} } void MachineLearning::getCrossSpecifyArea(IplImage *img,CvRect &specifie_rect)
/*************************************************
Function:
Description: 获得图像矩形
Date: 2007-3-7
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
CvRect res_rect = cvRect(0,0,0,0);
const int fix =0;
CvMemStorage* mt_storage = cvCreateMemStorage(0);
CvSeq* mt_contour = NULL;
int ApproxCount = 2; //轮廓优化等级
IplImage *frame_copy = cvCreateImage(cvGetSize(img) , 8, 1 );
frame_copy->origin = img->origin;
cvCopy(img,frame_copy,0);
cvFindContours( frame_copy, mt_storage, &mt_contour, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
if(mt_contour)
{
CvSeqReader reader;
int i;
CvPoint left_top_pt=cvPoint(img->width,img->height);
CvPoint right_bottom_pt=cvPoint(0,0); CvPoint pt;
CvSeq *contour2 = mt_contour; for (; contour2 != NULL; contour2 = contour2->h_next)
{
cvStartReadSeq(contour2, &reader);
int N = contour2->total;
if(N<10) continue; for (i = 0; i < N; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
if(left_top_pt.x>pt.x)left_top_pt.x = pt.x;
if(left_top_pt.y>pt.y)left_top_pt.y = pt.y;
if(right_bottom_pt.x<pt.x)right_bottom_pt.x = pt.x;
if(right_bottom_pt.y<pt.y)right_bottom_pt.y = pt.y; }
res_rect = cvRect(abs(left_top_pt.x-fix),abs(left_top_pt.y-fix),(right_bottom_pt.x-left_top_pt.x+2*fix),(right_bottom_pt.y-left_top_pt.y+2*fix));
specifie_rect = res_rect;
break;
}
} cvClearMemStorage(mt_storage);
cvReleaseImage(&frame_copy);
} void MachineLearning::getCrossCenter(IplImage *img,int &cx,int &cy)
/*************************************************
Function:
Description: 获得图像平移到中心
Date: 2007-3-5
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
CvMemStorage* mt_storage = cvCreateMemStorage(0);
CvSeq* mt_contour = NULL;
int ApproxCount = 2; //轮廓优化等级
IplImage *frame_copy = cvCreateImage(cvGetSize(img) , 8, 1 );
frame_copy->origin = img->origin;
cvCopy(img,frame_copy,0);
cvFindContours( frame_copy, mt_storage, &mt_contour, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
if(mt_contour)
{
CvSeqReader reader;
int i;
int total_x = 0;
int total_y = 0; CvPoint pt;
CvSeq *contour2 = mt_contour; for (; contour2 != NULL; contour2 = contour2->h_next)
{
cvStartReadSeq(contour2, &reader);
int N = contour2->total;
if(N<10) continue; for (i = 0; i < N; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
total_x += pt.x;
total_y += pt.y;
}
cx = total_x/N;
cy = total_y/N;
break;
}
}
cvReleaseMemStorage(&mt_storage);
cvReleaseImage(&frame_copy);
} void MachineLearning::ExtractPCA(float pcadata[],const int featureData[],const int &dataWidth )
/*************************************************
Function:
Description: 采用fourier transfer 得到降维的数据
Date: 2007-3-5
Author:
Input:
Output:
Return:
Others:
*************************************************/
{ //int dataWidth = cols + rows;
//CvMat* pData = cvCreateMat(2,dataWidth, CV_32FC1);
//for(int i = 0; i < dataWidth; i++)
//{
// cvSet2D(pData, 0, i,cvRealScalar(i));
// cvSet2D(pData, 1, i,cvRealScalar(featureData[i]));
//} //CvMat* pMean = cvCreateMat(2, dataWidth, CV_32FC1);
//CvMat* pEigVals = cvCreateMat(2, dataWidth, CV_32FC1);
//CvMat* pEigVecs = cvCreateMat(2, dataWidth, CV_32FC1); //cvCalcPCA(pData, pMean, pEigVals, pEigVecs, CV_PCA_DATA_AS_ROW ); //float pp[100];
//memcpy(pp,pEigVals->data.fl,100 );
//memcpy(pp,pEigVecs->data.fl,100 );
//memcpy(pp,pMean->data.fl,100 ); CvMat* s = cvCreateMat(1,dataWidth,CV_32FC1);
memcpy(s->data.i,featureData,sizeof(featureData));
for(int i=0;i<dataWidth;i++)
cvSetReal2D(s,0,i,featureData[i]); //for(int i=0;i<dataWidth;i++)
// printf("%6.2f\t",cvGetReal2D(s,0,i));
//printf("\n"); CvMat* d = cvCreateMat(1,dataWidth,CV_32FC1); cvDFT(s,d,CV_DXT_FORWARD|CV_DXT_SCALE); //for(int i=0;i<dataWidth;i++)
// printf("%6.2f\t",cvGetReal2D(d,0,i));
//printf("\n"); for(int i=0;i<10;i++)
{
pcadata[i] = (float)cvGetReal2D(d,0,i);
} cvReleaseMat(&s);
cvReleaseMat(&d);
} void MachineLearning::ExtractDFT(float pcadata[],const int featureData[],const int &dataWidth,const int &DFTwidth )
/*************************************************
Function:
Description: 采用fourier transfer 得到降维的数据
Date: 2007-3-5
Author:
Input:
Output:
Return:
Others:
*************************************************/
{ CvMat* s = cvCreateMat(1,dataWidth,CV_32FC1);
memcpy(s->data.i,featureData,sizeof(featureData));
for(int i=0;i<dataWidth;i++)
cvSetReal2D(s,0,i,featureData[i]); //for(int i=0;i<dataWidth;i++)
// printf("%6.2f\t",cvGetReal2D(s,0,i));
//printf("\n"); CvMat* d = cvCreateMat(1,dataWidth,CV_32FC1); cvDFT(s,d,CV_DXT_FORWARD|CV_DXT_SCALE); //for(int i=0;i<dataWidth;i++)
// printf("%6.2f\t",cvGetReal2D(d,0,i));
//printf("\n"); for(int i=0;i<DFTwidth;i++)
{
pcadata[i] = (float)cvGetReal2D(d,0,i);
} cvReleaseMat(&s);
cvReleaseMat(&d);
} int MachineLearning::read_num_class_data( const char* filename, int var_count,CvMat** data, CvMat** responses )
{
const int M = 1024;
FILE* f = fopen( filename, "rt" );
CvMemStorage* storage;
CvSeq* seq;
char buf[M+2];
float* el_ptr;
CvSeqReader reader;
int i, j; if( !f )
return 0; el_ptr = new float[var_count+1];
storage = cvCreateMemStorage();
seq = cvCreateSeq( 0, sizeof(*seq), (var_count+1)*sizeof(float), storage ); for(;;)
{
char* ptr;
if( !fgets( buf, M, f ) || !strchr( buf, ',' ) )
break;
el_ptr[0] = buf[0];
ptr = buf+2;
for( i = 1; i <= var_count; i++ )
{
int n = 0;
sscanf( ptr, "%f%n", el_ptr + i, &n );
ptr += n + 1;
}
if( i <= var_count )
break;
cvSeqPush( seq, el_ptr );
}
fclose(f); *data = cvCreateMat( seq->total, var_count, CV_32F );
*responses = cvCreateMat( seq->total, 1, CV_32F ); cvStartReadSeq( seq, &reader ); for( i = 0; i < seq->total; i++ )
{
const float* sdata = (float*)reader.ptr + 1;
float* ddata = data[0]->data.fl + var_count*i;
float* dr = responses[0]->data.fl + i; for( j = 0; j < var_count; j++ )
ddata[j] = sdata[j];
*dr = sdata[-1];
CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
} cvReleaseMemStorage( &storage );
delete el_ptr;
return 1;
} int MachineLearning::build_rtrees_classifier(const char* data_filename,
const char* filename_to_save, const char* filename_to_load )
{
CvMat* data = 0;
CvMat* responses = 0;
CvMat* var_type = 0;
CvMat* sample_idx = 0; // Create or load Random Trees classifier
if( filename_to_load )
{
// load classifier from the specified file
forest.load( filename_to_load );
if( forest.get_tree_count() == 0 )
{
printf( "Could not read the classifier %s\n", filename_to_load );
return -1;
}
printf( "The classifier %s is loaded.\n", data_filename );
}
else
{
int ok = read_num_class_data( data_filename, DataCount, &data, &responses );
int nsamples_all = 0, ntrain_samples = 0;
int i = 0;
double train_hr = 0, test_hr = 0; CvMat* var_importance = 0; if( !ok )
{
printf( "Could not read the database %s\n", data_filename );
return -1;
} printf( "The database %s is loaded.\n", data_filename );
nsamples_all = data->rows;
ntrain_samples = (int)(nsamples_all*0.8); int ntrain_tests = -1; // create classifier by using <data> and <responses>
printf( "Training the classifier ..."); // 1. create type mask
var_type = cvCreateMat( data->cols + 1, 1, CV_8U );
cvSet( var_type, cvScalarAll(CV_VAR_ORDERED) );
cvSetReal1D( var_type, data->cols, CV_VAR_CATEGORICAL );
//00000000001 // 2. create sample_idx
sample_idx = cvCreateMat( 1, nsamples_all, CV_8UC1 );
{
CvMat mat;
cvGetCols( sample_idx, &mat, 0, nsamples_all );
cvSet( &mat, cvRealScalar(1) ); for(int i=0;i<nsamples_all;i++)
{
if((i%5)==0)
{
cvSet2D(sample_idx,0,i,cvRealScalar(0));
ntrain_tests++;
}
}
} // 3. train classifier
forest.train( data, CV_ROW_SAMPLE, responses, 0, sample_idx, var_type, 0,
CvRTParams(10,10,0,false,15,0,true,4,100,0.01f,CV_TERMCRIT_ITER));
printf( "\n"); // compute prediction error on train and test data
int test_count=0;
int train_count=0;
for(int i = 0; i < nsamples_all; i++ )
{
double r;
CvMat sample;
cvGetRow( data, &sample, i ); r = forest.predict( &sample );
double abs_r = fabs((float)r - responses->data.fl[i]) <= FLT_EPSILON ? 1.0 : 0.0; if(abs_r < FLT_EPSILON)
{
printf( "data error with lines %d '%c' %f \n",i,(char)responses->data.fl[i],fabs((float)r - responses->data.fl[i]));
} if((i%5)==0)
{
test_hr += abs_r;
}
else
{
train_hr += abs_r;
} } test_hr /= (double)(ntrain_tests);
train_hr /= (double)(nsamples_all-ntrain_tests);
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. ); //printf( "Number of trees: %d\n", forest.get_tree_count() );
} //// Save Random Trees classifier to file if needed
if( filename_to_save )
forest.save( filename_to_save );
//forest.save("..//data//rTreeResult.xml"); cvReleaseMat( &sample_idx );
cvReleaseMat( &var_type );
cvReleaseMat( &data );
cvReleaseMat( &responses ); return 0;
} int MachineLearning::build_boost_classifier( char* data_filename,
char* filename_to_save, char* filename_to_load )
{
const int class_count = 3;
CvMat* data = 0;
CvMat* responses = 0;
CvMat* var_type = 0;
CvMat* temp_sample = 0;
CvMat* weak_responses = 0; int ok = read_num_class_data( data_filename, 13, &data, &responses );
int nsamples_all = 0, ntrain_samples = 0;
int var_count;
int i, j, k;
double train_hr = 0, test_hr = 0;
CvBoost boost; if( !ok )
{
printf( "Could not read the database %s\n", data_filename );
return -1;
} printf( "The database %s is loaded.\n", data_filename );
nsamples_all = data->rows;
ntrain_samples = (int)(nsamples_all*0.9);
var_count = data->cols; // Create or load Boosted Tree classifier
if( filename_to_load )
{
// load classifier from the specified file
boost.load( filename_to_load );
ntrain_samples = 0;
if( !boost.get_weak_predictors() )
{
printf( "Could not read the classifier %s\n", filename_to_load );
return -1;
}
printf( "The classifier %s is loaded.\n", data_filename );
}
else
{
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// As currently boosted tree classifier in MLL can only be trained
// for 2-class problems, we transform the training database by
// "unrolling" each training sample as many times as the number of
// classes (26) that we have.
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CvMat* new_data = cvCreateMat( ntrain_samples*class_count, var_count + 1, CV_32F );
CvMat* new_responses = cvCreateMat( ntrain_samples*class_count, 1, CV_32S ); // 1. unroll the database type mask
printf( "Unrolling the database...\n");
for( i = 0; i < ntrain_samples; i++ )
{
float* data_row = (float*)(data->data.ptr + data->step*i);
for( j = 0; j < class_count; j++ )
{
float* new_data_row = (float*)(new_data->data.ptr +
new_data->step*(i*class_count+j));
for( k = 0; k < var_count; k++ )
new_data_row[k] = data_row[k];
new_data_row[var_count] = (float)j;
new_responses->data.i[i*class_count + j] = responses->data.fl[i] == j+'A';
}
} // 2. create type mask
var_type = cvCreateMat( var_count + 2, 1, CV_8U );
cvSet( var_type, cvScalarAll(CV_VAR_ORDERED) );
// the last indicator variable, as well
// as the new (binary) response are categorical
cvSetReal1D( var_type, var_count, CV_VAR_CATEGORICAL );
cvSetReal1D( var_type, var_count+1, CV_VAR_CATEGORICAL ); // 3. train classifier
printf( "Training the classifier (may take a few minutes)...");
boost.train( new_data, CV_ROW_SAMPLE, new_responses, 0, 0, var_type, 0,
CvBoostParams(CvBoost::REAL, 100, 0.95, 5, false, 0 ));
cvReleaseMat( &new_data );
cvReleaseMat( &new_responses );
printf("\n");
} temp_sample = cvCreateMat( 1, var_count + 1, CV_32F );
weak_responses = cvCreateMat( 1, boost.get_weak_predictors()->total, CV_32F ); // compute prediction error on train and test data
for( i = 0; i < nsamples_all; i++ )
{
int best_class = 0;
double max_sum = -DBL_MAX;
double r;
CvMat sample;
cvGetRow( data, &sample, i );
for( k = 0; k < var_count; k++ )
temp_sample->data.fl[k] = sample.data.fl[k]; for( j = 0; j < class_count; j++ )
{
temp_sample->data.fl[var_count] = (float)j;
boost.predict( temp_sample, 0, weak_responses );
double sum = cvSum( weak_responses ).val[0];
if( max_sum < sum )
{
max_sum = sum;
best_class = j + 'A';
}
} r = fabs(best_class - responses->data.fl[i]) < FLT_EPSILON ? 1 : 0; if( i < ntrain_samples )
train_hr += r;
else
test_hr += r;
} test_hr /= (double)(nsamples_all-ntrain_samples);
train_hr /= (double)ntrain_samples;
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. ); printf( "Number of trees: %d\n", boost.get_weak_predictors()->total ); // Save classifier to file if needed
if( filename_to_save )
boost.save( filename_to_save ); cvReleaseMat( &temp_sample );
cvReleaseMat( &weak_responses );
cvReleaseMat( &var_type );
cvReleaseMat( &data );
cvReleaseMat( &responses ); return 0;
} int MachineLearning::build_mlp_classifier( char* data_filename,
char* filename_to_save, char* filename_to_load )
{
const int class_count = 3;
CvMat* data = 0;
CvMat train_data;
CvMat* responses = 0;
CvMat* mlp_response = 0; int ok = read_num_class_data( data_filename, 13, &data, &responses );
int nsamples_all = 0, ntrain_samples = 0;
int i, j;
double train_hr = 0, test_hr = 0;
CvANN_MLP mlp; if( !ok )
{
printf( "Could not read the database %s\n", data_filename );
return -1;
} printf( "The database %s is loaded.\n", data_filename );
nsamples_all = data->rows;
ntrain_samples = (int)(nsamples_all*0.9); // Create or load MLP classifier
if( filename_to_load )
{
// load classifier from the specified file
mlp.load( filename_to_load );
ntrain_samples = 0;
if( !mlp.get_layer_count() )
{
printf( "Could not read the classifier %s\n", filename_to_load );
return -1;
}
printf( "The classifier %s is loaded.\n", data_filename );
}
else
{
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// MLP does not support categorical variables by explicitly.
// So, instead of the output class label, we will use
// a binary vector of <class_count> components for training and,
// therefore, MLP will give us a vector of "probabilities" at the
// prediction stage
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CvMat* new_responses = cvCreateMat( ntrain_samples, class_count, CV_32F ); // 1. unroll the responses
printf( "Unrolling the responses...\n");
for( i = 0; i < ntrain_samples; i++ )
{
int cls_label = cvRound(responses->data.fl[i]) - 'A';
float* bit_vec = (float*)(new_responses->data.ptr + i*new_responses->step);
for( j = 0; j < class_count; j++ )
bit_vec[j] = 0.f;
bit_vec[cls_label] = 1.f;
}
cvGetRows( data, &train_data, 0, ntrain_samples ); // 2. train classifier
int layer_sz[] = { data->cols, 100, 100, class_count };
CvMat layer_sizes =
cvMat( 1, (int)(sizeof(layer_sz)/sizeof(layer_sz[0])), CV_32S, layer_sz );
mlp.create( &layer_sizes );
printf( "Training the classifier (may take a few minutes)...");
mlp.train( &train_data, new_responses, 0, 0,
CvANN_MLP_TrainParams(cvTermCriteria(CV_TERMCRIT_ITER,300,0.01),
CvANN_MLP_TrainParams::RPROP,0.01));
cvReleaseMat( &new_responses );
printf("\n");
} mlp_response = cvCreateMat( 1, class_count, CV_32F ); // compute prediction error on train and test data
for( i = 0; i < nsamples_all; i++ )
{
int best_class;
CvMat sample;
cvGetRow( data, &sample, i );
CvPoint max_loc = {0,0};
mlp.predict( &sample, mlp_response );
cvMinMaxLoc( mlp_response, 0, 0, 0, &max_loc, 0 );
best_class = max_loc.x + 'A'; int r = fabs((double)best_class - responses->data.fl[i]) < FLT_EPSILON ? 1 : 0; if( i < ntrain_samples )
train_hr += r;
else
test_hr += r;
} test_hr /= (double)(nsamples_all-ntrain_samples);
train_hr /= (double)ntrain_samples;
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. ); // Save classifier to file if needed
if( filename_to_save )
mlp.save( filename_to_save ); cvReleaseMat( &mlp_response );
cvReleaseMat( &data );
cvReleaseMat( &responses ); return 0;
} int MachineLearning::build_svm_classifier( char* data_filename,
char* filename_to_save, char* filename_to_load )
{ CvMat* data = 0;
//CvMat train_data;
CvMat* responses = 0;
CvMat* mlp_response = 0;
CvMat* var_type = 0;
CvMat* sample_idx = 0; int ok = read_num_class_data( data_filename, 10, &data, &responses ); float kk[100];
memcpy(kk,data->data.fl,100);
int nsamples_all = 0, ntrain_samples = 0;
int i;
double train_hr = 0, test_hr = 0;
CvSVM svm; if( !ok )
{
printf( "Could not read the database %s\n", data_filename );
return -1;
} printf( "The database %s is loaded.\n", data_filename );
nsamples_all = data->rows;
ntrain_samples = (int)(nsamples_all*0.9); // Create or load svm classifier
if( filename_to_load )
{
// load classifier from the specified file
svm.load( filename_to_load );
ntrain_samples = 0; if( !svm.get_support_vector_count() )
{
printf( "Could not read the classifier %s\n", filename_to_load );
return -1;
}
printf( "The classifier %s is loaded.\n", filename_to_load );
}
else
{
printf( "The classifier is in tranning...\n" );
// 1. create type mask var_type = cvCreateMat( data->cols, 1, CV_8U );
cvSet( var_type, cvScalarAll(CV_VAR_CATEGORICAL) );
//1111111111 // 2. create sample_idx
sample_idx = cvCreateMat( 1, nsamples_all, CV_8UC1 );
{
CvMat mat;
cvGetCols( sample_idx, &mat, 0, ntrain_samples );
cvSet( &mat, cvRealScalar(1) ); cvGetCols( sample_idx, &mat, ntrain_samples, nsamples_all );
cvSetZero( &mat );
}
//1111111000 // 3. train classifier
svm.train( data,responses,var_type,sample_idx,
CvSVMParams( CvSVM::C_SVC, CvSVM::RBF ,0,0.3,0,0.1, 0, 0,
0, cvTermCriteria(CV_TERMCRIT_ITER,300,0.01) ));
printf( "\n");
} // compute prediction error on train and test data
for( i = 0; i < nsamples_all; i++ )
{
double r;
CvMat sample;
cvGetRow( data, &sample, i ); r = svm.predict( &sample );
r = fabs((double)r - responses->data.fl[i]) <= FLT_EPSILON ? 1 : 0; if( i < ntrain_samples )
train_hr += r;
else
test_hr += r;
} test_hr /= (double)(nsamples_all-ntrain_samples);
train_hr /= (double)ntrain_samples;
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. ); printf( "Number of support_vector_count: %d\n", svm.get_support_vector_count() ); //printf( "value of svm.get_support_vector(0): %f\n", svm.get_support_vector(0) ); // Save classifier to file if needed
//if( filename_to_save )
//svm.save( filename_to_save );
svm.save("../data/svmResult.xml"); cvReleaseMat( &mlp_response );
cvReleaseMat( &data );
cvReleaseMat( &responses ); return 0;
} bool MachineLearning::load(const char *training_filename)
/*************************************************
Function:
Description: 训练数据载入
Date: 2007-3-6
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
switch( traning_method )
{
case RandomTrees:
forest.clear();
build_rtrees_classifier(NULL,NULL,training_filename);
break;
default:
;
}
is_load_training_model = true; return true;
}
bool MachineLearning::train(const char *data_filename,const char *save_filename)
/*************************************************
Function:
Description: 样本数据训练
Date: 2007-3-6
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
switch( traning_method )
{
case RandomTrees:
forest.clear();
build_rtrees_classifier(data_filename,save_filename,NULL);
break;
default:
;
}
is_load_training_model = true;
return true;
}
bool MachineLearning::predict(char &shape_type,float featureData[])
/*************************************************
Function:
Description: 样本数据预测
Date: 2007-3-6
Author:
Input:
Output:
Return:
Others:
*************************************************/
{
if(is_load_training_model)
{
//float featureData[10];
//getCrossFeature(img,featureData); //to do build sample
CvMat *sample_data= cvCreateMat( 1, DataCount, CV_32F );
//cvSet2D(sample_data,0,0,cvRealScalar(0));
for(int i=0;i<DataCount;i++)
{
cvSet2D(sample_data,0,i,cvRealScalar(featureData[i]));
}
//float ss[23];
//memcpy(ss,sample_data->data.fl,sizeof(float)*23); switch( traning_method )
{
case RandomTrees:
predict_rtrees_classifier(sample_data,shape_type);
break;
default:
;
}
cvReleaseMat(&sample_data); return true;
}
else
return false;
} int MachineLearning::predict_rtrees_classifier(CvMat *sample_data,char &shape_type)
{
double r = forest.predict( sample_data );
shape_type = (char)r;
return 0;
}
trainingtools.cpp
// TrainingTools.cpp : 定义控制台应用程序的入口点。
// // 26个字母要按一定笔划顺序书写。书写的规律有以下几点:
//联机大写字母书写规则
//1. C J L O S U V W Z 一笔划完成
//2. B D G K M N P Q T X Y 两笔划完成
//3. A E F H I R 三笔划完成 //online upper letter rule
//1. C J L O S U V W Z finish in one stroke
//2. B D G K M N P Q T X Y finish in two stroke
//3. A E F H I R finish in three stroke #include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <string.h>
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <fstream>
#include "Finger.h"
#include "MachineLearning.h" #pragma comment(lib,"opencv_core2410d.lib")
#pragma comment(lib,"opencv_highgui2410d.lib")
#pragma comment(lib,"opencv_ml2410d.lib")
#pragma comment(lib,"opencv_imgproc2410.lib") IplImage *image = 0 ; //原始图像
IplImage *image2 = 0 ; //原始图像 using namespace std; const int SCALE_MAX = 500;
const DWORD IDLE_TIME_SPAN = 1000; //间隔一秒内没有输入,开始写入数据
const int SAMPLE_COUNT = 50; //每条曲线 五十个特征点
const int SAMPLE_COUNT_OPT = 5; //每条曲线只取五维
DWORD start_time =0;
DWORD idle_time =0;
bool InRecongnize = true; //0 训练 1 预测
char pre_letter =0;
MachineLearning ml; std::vector< FingerTrack > FingerTrackList;
std::vector <Finger>::iterator Itr_Finger;
std::vector< FingerTrack >::iterator Itr_FingerTrack;
std::vector< FingerTrack > FingerTrackListOpt;//优化轮廓 bool inTrack =false;
void WriteData(float featureData[]);
int DFT();
void toNormalSize();
int traing_data =0;
char letter='A'; CvFont mycvFont; //归一化处理
void toNormalSize()
{
int max_temp_x=0;
int max_temp_y=0;
int min_temp_x=10000;
int min_temp_y=10000;
for(int i=0;i<(int)FingerTrackListOpt.size();i++)
{
int ListObjSize = (int)FingerTrackListOpt[i].track.size();
for(int j=0;j<(int)ListObjSize;j++)
{
//FingerTrackListOpt[i].track[j].center.x -=FingerTrackListOpt[i].track[0].center.x;
//FingerTrackListOpt[i].track[j].center.y -=FingerTrackListOpt[i].track[0].center.y;
max_temp_x = max((FingerTrackListOpt[i].track[j].center.x),max_temp_x);
max_temp_y = max((FingerTrackListOpt[i].track[j].center.y),max_temp_y);
min_temp_x = min((FingerTrackListOpt[i].track[j].center.x),min_temp_x);
min_temp_y = min((FingerTrackListOpt[i].track[j].center.y),min_temp_y);
}
} for(int i=0;i<(int)FingerTrackListOpt.size();i++)
{
int ListObjSize = (int)FingerTrackListOpt[i].track.size();
for(int j=0;j<(int)ListObjSize;j++)
{
FingerTrackListOpt[i].track[j].center.x -=min_temp_x;
FingerTrackListOpt[i].track[j].center.y -=min_temp_y;
}
} int MaxW = max(max_temp_x-min_temp_x,max_temp_y-min_temp_y); //最大的
for(int i=0;i<(int)FingerTrackListOpt.size();i++)
{
int ListObjSize = (int)FingerTrackListOpt[i].track.size();
for(int j=0;j<(int)ListObjSize;j++)
{
FingerTrackListOpt[i].track[j].center.x =(int)((float)FingerTrackListOpt[i].track[j].center.x/MaxW*SCALE_MAX);
FingerTrackListOpt[i].track[j].center.y =(int)((float)FingerTrackListOpt[i].track[j].center.y/MaxW*SCALE_MAX);
}
} } void analysis()
{
FingerTrackListOpt.clear();
for(int i=0;i<(int)FingerTrackList.size();i++)
{
//创建FingerTrack 加入FingerTrackListOpt
FingerTrack ft;
FingerTrackListOpt.push_back(ft);
CvPoint start_pt = FingerTrackList[i].track[0].center;
Finger fg;
fg.center = start_pt;
FingerTrackListOpt[i].track.push_back(fg); //求取距离总和
long total_dis =0;
int ListObjSize = (int)FingerTrackList[i].track.size();
for(int j=0;j<ListObjSize-1;j++)
{
CvPoint pt = FingerTrackList[i].track[j].center;
CvPoint pt_next = FingerTrackList[i].track[j+1].center;
long distance = (pt_next.x - pt.x)*(pt_next.x - pt.x) + (pt_next.y - pt.y)*(pt_next.y - pt.y);
total_dis+=(long)sqrt((float)distance);
}
int search_len = total_dis/(SAMPLE_COUNT+2); //确定分割长度,取20等份
assert(search_len>0); //插值
for(int j=0;j<ListObjSize;j++)
{ CvPoint pt = FingerTrackList[i].track[j].center;
long distance = (start_pt.x - pt.x)*(start_pt.x - pt.x) + (start_pt.y - pt.y)*(start_pt.y - pt.y);
distance = (long)sqrt((float)distance);
if(distance>search_len)
{
//在轨迹上计算一个插值虚拟点
float radio = (float)search_len/distance;
start_pt.x = (int)(start_pt.x + (pt.x - start_pt.x)*radio);
start_pt.y = (int)(start_pt.y + (pt.y - start_pt.y)*radio);
Finger fg;
fg.center = start_pt;
FingerTrackListOpt[i].track.push_back(fg);
j--;
}
}
} //归一化处理
toNormalSize(); };
//写入特征数据到文件或者数组
void WriteData(float featureData[])
{
std::fstream logfile("data.txt",std::ios::app);
int Tracksize = (int)FingerTrackListOpt.size();
if(!InRecongnize)
{
logfile<<letter<<",";
logfile<<Tracksize;
} featureData[0] = (float)Tracksize;
int f_index = 0; for(int i=0;i<Tracksize;i++)
{
int ListObjSize = (int)FingerTrackListOpt[i].track.size();
assert(ListObjSize>=SAMPLE_COUNT); float pcadata[SAMPLE_COUNT_OPT];
int fData[SAMPLE_COUNT];
//X DFT
for(int j=0;j<SAMPLE_COUNT;j++)
{
fData[j] = FingerTrackListOpt[i].track[j].center.x;
}
ml.ExtractDFT(pcadata,fData,SAMPLE_COUNT,SAMPLE_COUNT_OPT);
for(int k=0;k<SAMPLE_COUNT_OPT;k++)
{
if(!InRecongnize) logfile<<","<<pcadata[k];
f_index++;
featureData[f_index] = pcadata[k]; }
//Y DFT
for(int j=0;j<SAMPLE_COUNT;j++)
{
fData[j] = FingerTrackListOpt[i].track[j].center.y;
}
ml.ExtractDFT(pcadata,fData,SAMPLE_COUNT,SAMPLE_COUNT_OPT);
for(int k=0;k<SAMPLE_COUNT_OPT;k++)
{
if(!InRecongnize) logfile<<","<<pcadata[k];
f_index++;
featureData[f_index] = pcadata[k];
} }
for(int i=Tracksize;i<3;i++) //用0填充
{
for(int j=0;j<SAMPLE_COUNT_OPT;j++)
{
if(!InRecongnize) logfile<<","<<0;
if(!InRecongnize) logfile<<","<<0;
f_index++;
featureData[f_index] = 0.0f;
f_index++;
featureData[f_index] = 0.0f;
}
}
if(!InRecongnize) logfile<<"\n";
logfile.close();
} static void on_mouse( int event, int x, int y, int flags, void *param )
{
if( event == CV_EVENT_LBUTTONDOWN )
{
if(!inTrack)
{
FingerTrack ft;
FingerTrackList.push_back(ft);
inTrack = true; } }
else if ( event == CV_EVENT_MOUSEMOVE )
{
if(inTrack)
{
Finger fg;
fg.center = cvPoint(x,y);
FingerTrackList.back().track.push_back(fg);
idle_time =0;
}
}
else if ( event == CV_EVENT_LBUTTONUP )
{
inTrack = false;
//analysis(); start_time = timeGetTime();
analysis();
//DFT(); } };
void OnChangeData(int pos)
{
letter = pos+'A';
} int main(int argc, char* argv[])
{ std::cout<<" == The upper letter online handwriting recongnize ==" << std::endl;
std::cout<<" 1. there two state (recongnizing and traning) for the app,In recongnizing mode,use your mouse write upper letter on 'Win' window,after 1 second,then will get result on Win2" << std::endl;
std::cout<<" 2. you can press 'm' key to change mode from recongnizing to traning or back." << std::endl;
std::cout<<" 3. In traning mode,change the value of letter, then you can write upper letter on 'Win' window, and app will write data into data.txt." << std::endl;
std::cout<<" 4. you can retrain the traning data by press 't' without restart program." << std::endl;
std::cout<<" 5. you can modify the traning data 'data.txt' by hand if you want. " << std::endl<< std::endl;
std::cout<<" enjoy it.:)" << std::endl<< std::endl;
std::cout<<" ===============================================================" << std::endl; CvSize image_sz = cvSize( 1000,1000);
image = cvCreateImage(image_sz , 8, 3 );
image2 = cvCreateImage(image_sz , 8, 3 ); cvNamedWindow("Win",0);
cvNamedWindow("Win2",0);
cvSetMouseCallback( "Win", on_mouse, 0 );
cvResizeWindow("Win",500,500);
cvResizeWindow("Win2",500,500);
cvCreateTrackbar("Letter", "Win2", &traing_data, 25, OnChangeData); mycvFont = cvFont(5,2);
ml.DataCount = 1 + SAMPLE_COUNT_OPT*2*3;
ml.train("data.txt",0); for(;;)
{
//set Timer
idle_time = timeGetTime()-start_time;
if(idle_time>IDLE_TIME_SPAN && FingerTrackList.size()>0 && !inTrack)
{ float featureData[31];
//记录训练数据
WriteData(featureData);
idle_time = 0;
FingerTrackList.clear();
FingerTrackListOpt.clear(); if(InRecongnize)
{
pre_letter = 0;
ml.predict(pre_letter,featureData); } } cvZero(image);
cvZero(image2); for(int i=0;i<(int)FingerTrackList.size();i++)
{
for(int j=0;j<(int)FingerTrackList[i].track.size();j++)
cvCircle(image,FingerTrackList[i].track[j].center,10,CV_RGB(0,255,0),1,8,0);
} for(int i=0;i<(int)FingerTrackListOpt.size();i++)
{
for(int j=0;j<(int)FingerTrackListOpt[i].track.size();j++)
{
CvPoint newpt = FingerTrackListOpt[i].track[j].center;
newpt.x =newpt.x/2+image2->width/2;
newpt.y =newpt.y/2+image2->height/2;
cvLine(image2,cvPoint(image2->width/2,0),cvPoint(image2->width/2 ,image2->height),CV_RGB(255,255,0),2,8,0);
cvLine(image2,cvPoint(0,image2->height/2),cvPoint(image2->width ,image2->height/2),CV_RGB(255,255,0),2,8,0);
cvCircle(image2,newpt,10,CV_RGB(255,0,0),1,8,0);
}
} CvPoint pt_info; if(InRecongnize)
{
pt_info = cvPoint(20,920);
mycvFont = cvFont(2,2);
cvPutText(image2,"recongnizing result = ",pt_info,&mycvFont,CV_RGB(20,250,250));
if(pre_letter!=0)
{
mycvFont = cvFont(5,2);
pt_info = cvPoint(400,920);
cvPutText(image2,&pre_letter,pt_info,&mycvFont,CV_RGB(255,0,0));
}
}
else
{
mycvFont = cvFont(5,2);
pt_info = cvPoint(290,920);
cvPutText(image2,&letter,pt_info,&mycvFont,CV_RGB(20,250,250));
mycvFont = cvFont(2,2);
pt_info = cvPoint(20,920);
cvPutText(image2,"is traning...",pt_info,&mycvFont,CV_RGB(20,250,250)); } cvShowImage("Win",image);
cvShowImage("Win2",image2);
int keyCode = cvWaitKey(10);
if (keyCode==27) break;
if (keyCode=='c')
{
FingerTrackList.clear();
FingerTrackListOpt.clear();
}
if (keyCode=='t')
{
ml.train("data.txt",0);
}
if (keyCode=='m')
{
InRecongnize = InRecongnize^1;
} } return 0;
} int DFT()
{
for(int k=0;k<(int)FingerTrackListOpt.size();k++)
{ int ListObjSize = (int)FingerTrackListOpt[k].track.size();
//if(ListObjSize==20) break;
printf("\n\nListObjSize %d ",ListObjSize); CvMat* s = cvCreateMat(1,ListObjSize,CV_32FC1);
CvMat* d = cvCreateMat(1,ListObjSize,CV_32FC1);
CvMat* s2 = cvCreateMat(1,ListObjSize,CV_32FC1); long avg_x =0;
long avg_y =0;
for(int j=0;j<(int)ListObjSize;j++)
{
CvPoint pt = FingerTrackListOpt[k].track[j].center;
avg_x +=pt.x;
avg_y +=pt.y;
}
avg_x = avg_x/ListObjSize;
avg_y = avg_y/ListObjSize; for(int j=0;j<(int)ListObjSize;j++)
{
CvPoint pt = FingerTrackListOpt[k].track[j].center;
float dis =(float)((pt.x-avg_x)* (pt.x-avg_x) + (pt.y-avg_y)* (pt.y-avg_y));
dis = sqrt(dis);
cvSetReal2D(s,0,j,dis);
}
//for(int j=0;j<(int)ListObjSize;j++)
//{
// printf("%6.2f ",cvGetReal2D(s,0,j));
//} printf(" \n"); //DFT 离散傅立叶变换
cvDFT(s,d,CV_DXT_FORWARD); //CV_DXT_FORWARD 代表了正变换:空域-〉频域 printf("\n The result of DFT: ");
for(int j=0;j<(int)ListObjSize;j++)
printf("%6.2f ",cvGetReal2D(d,0,j)); //printf(" \n");
////DFT 离散傅立叶逆变换
//cvDFT(d,s2,CV_DXT_INV_SCALE); //逆变换
//printf("\n The result of IDFT: ");
//for(int j=0;j<(int)ListObjSize;j++)
// printf("%6.2f ",cvGetReal2D(s2,0,j));
//printf(" "); cvReleaseMat(&s);
cvReleaseMat(&d);
cvReleaseMat(&s2);
}
return 0;
}
实现效果:
OpenCV OpenGL手写字符识别的更多相关文章
- 基于opencv的手写数字字符识别
摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...
- 学习OpenCV——SVM 手写数字检测
转自http://blog.csdn.net/firefight/article/details/6452188 是MNIST手写数字图片库:http://code.google.com/p/supp ...
- 仅用200个样本就能得到当前最佳结果:手写字符识别新模型TextCaps
由于深度学习近期取得的进展,手写字符识别任务对一些主流语言来说已然不是什么难题了.但是对于一些训练样本较少的非主流语言来说,这仍是一个挑战性问题.为此,本文提出新模型TextCaps,它每类仅用200 ...
- 基于opencv的手写数字识别(MFC,HOG,SVM)
参考了秋风细雨的文章:http://blog.csdn.net/candyforever/article/details/8564746 花了点时间编写出了程序,先看看效果吧. 识别效果大概都能正确. ...
- 利用Tensorflow实现手写字符识别
模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基 ...
- Caffe2 手写字符识别(MNIST - Create a CNN from Scratch)[8]
本教程创建一个小的神经网络用于手写字符的识别.我们使用MNIST数据集进行训练和测试.这个数据集的训练集包含60000张来自500个人的手写字符的图像,测试集包含10000张独立于训练集的测试图像.你 ...
- anaconda+theano+keras手写字符识别新版
标题介绍运行环境了win7 看网上好多keras识别minist 但是一般由于版本问题,无法直接用,,,这里还要特别感谢keras中文文档作者(三当家SCP).教程整的非常好.还有就是最好你在安装an ...
- Tensorflow学习笔记3:卷积神经网络实现手写字符识别
# -*- coding:utf-8 -*- import tensorflow as tf from tensorflow.examples.tutorials.mnist import input ...
- TensorFlow学习笔记2:逻辑回归实现手写字符识别
代码比较简单,没啥好说的,就做个记录而已.大致就是现建立graph,再通过session运行即可.需要注意的就是Variable要先初始化再使用. import tensorflow as tf fr ...
随机推荐
- [Pelican]Pelican入门(二)
之前是搭建了一个简单的博客,但是没有图片,没有具体的栏目分类 这次来研究下 一 导航栏 之前是直接把.md扔到的content文件夹下,结果导航栏,显示的是Category信息. 现在这么改成 D:. ...
- svn(subversion)代码版本管理在linux下的一些常见使用命令
以下的操作都是默认你的服务器安装有svn的大前提下进行的. 一.创建版本库 我的版本库存放路径为: /var/svn : 下面我们来创建一个名为 svntet 的版本库 注释: svnadmin ...
- 4. React 属性和状态介绍
React 中的属性和状态初看之下可以互相替代,但是在 React 的设计哲学中两者有着截然不同的使用方式和使用场景. 属性的含义和用法 props = propert ...
- MyBatis Generator For Eclipse 插件安装
由于在ORM框架MyBatis中,实现数据表于JavaBean映射时,配置的代码比较的复杂,所以为了加快开发的效率,MyBatis官方提供了一个Eclipse的插件, 我izuoyongjiushis ...
- scala学习笔记1(表达式)
<pre name="code" class="plain">//Scala中的 main 函数需要存在于 object 对象中,我们需要一个obj ...
- 03 CheckBox 复选框
五 CheckBox 复选框 >概念:可以从一个集合选项中选择一个或者多个选项 >属性:checked 选择状态 >使用: > ...
- Web Service进阶(四)WebService注解
@WebService 1.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service.缺省值为 Java 类的简单名称 + Service.(字符 ...
- ffplay播放器移植VC的工程:ffplay for MFC
本文介绍一个自己做的FFPLAY移植到VC下的开源工程:ffplayfor MFC.本工程将ffmpeg项目中的ffplay播放器(ffplay.c)移植到了VC的环境下.并且使用MFC做了一套简单的 ...
- Uva - 400 - Unix ls
先计算出最长文件的长度M,然后计算列数和行数,最后输出即可. AC代码: #include <iostream> #include <cstdio> #include < ...
- CUDA学习,环境配置和简单例子
根据摩尔定律,每18个月,硬件的速度翻一番.纵使CPU的主频会越来越高,但是其核数受到了极大的限制,目前来说,最多只有8个或者9个核.相比之下,GPU具有很大的优势,他有成千上万个核,能完成大规模的并 ...