SVM手写字符识别小程序

来源:互联网 发布:c语言的预处理命令 编辑:程序博客网 时间:2024/04/29 23:48

该程序是基于opencv3.1写的,自己的训练样本图片,图片大小都是32X32,主要思路是利用灰度图在行和列方向上的投影得到的64(32+32)个标签进行数据分类

主函数如下:

#include"LetterDet.h"int main(){image_read();image_SVMClassify();cv::waitKey();return 0;}

对应的头文件:

/************************************************************为什么变成 D:\testImages\ 就会出错  *转义序列 \" 表示双引号,而不是字符串的结尾*http://blog.csdn.net/holybin/article/details/17751063**********************************************************/#ifndef LETTERDET_H#define LETTERDET_H#include<opencv2\opencv.hpp>#include<iostream>#include<string.h>#include<stdlib.h>#include<sstream>#include<fstream>using namespace std;#define source_path    "D:\testImages"            #define feature_path   "features.txt"  //cv::Mat FeatureMat = cv::Mat::zeros( 860 , 64 , CV_32FC1 );//cv::Mat LabelMat = cv::Mat::zeros( 1 , 860 , CV_32SC1 );void image_read();void image_feature_write( cv::Mat& image , int label );void getTrainingDataAndLabel();void image_SVMClassify();#endif


具体的函数实现:

#include"LetterDet.h"cv::Mat sampleFeatureMat = cv::Mat::zeros( 850 , 64 , CV_32FC1 );       // SVM训练数据是行向量cv::Mat sampleLabelMat = cv::Mat::zeros( 850 , 1 , CV_32SC1 );          // SVM标签是列向量void image_read(){for( int i = 0; i < 10; i++ ){for( int j = 0; j < 85; j++ ){stringstream str;                          // 读取一系列图片str << "D:\\testImages\\" << i << "_" << j << ".jpg";cv::Mat srcImage = cv::imread( str.str() , 0 );if( !srcImage.data ){cout << "读取失败,请检查该图片是否存在!!!" << endl;exit( 0 );}else{//cout << str.str() << "\t读取成功!" << endl;}image_feature_write( srcImage , i );}}}void image_feature_write( cv::Mat& image , int label ){FILE* file;if( fopen_s( &file , feature_path , "a+" ) )  // 以可附加的方式打开只写文件,若文件不存在则建立{cout << "Can't open file!" << endl;exit( 0 );}else{//getFeature();for( int i = 0; i < image.rows; i++ )   //投影到X轴的所有像素和{int sum = 0;uchar* ptr = image.ptr( i );for( int j = 0; j < image.cols; j++ ){sum += ptr[j];}fprintf( file , " %d" , sum );}for( int j = 0; j < image.cols; j++ )   //投影到Y轴的所有像素和{int sum = 0;for( int i = 0; i < image.rows; i++ ){sum += image.at<uchar>( i , j );}fprintf( file , " %d" , sum );}}fprintf( file , " %d" , label );fprintf( file , "\n" );fclose( file );             // 一定要记得关闭文件}void getTrainingDataAndLabel(){FILE* file;//if( fopen_s( &file , feature_path , "a+" ) )file=fopen( feature_path , "r" );/*if( fopen_s( &file , feature_path , "r" ) ){cout << "打开features.txt文件成功!" << endl;}else{cout << "打开features.txt文件失败!" << endl;}*///ifstream fr;          // 记得包含库文件<fstream>//fr.open( feature_path , ios::in );sampleLabelMat.setTo( 0 );     // 850,1sampleFeatureMat.setTo( 0 );   // 850,64cout << "开始读取features.txt文件中的数据" << endl;for( int i = 0; i < 850; i++ ){for( int j = 0; j < 65; j++ ){if( j == 64 ){fscanf( file , "%d" , &sampleLabelMat.at<int>( i , 0 ) );continue;}else{fscanf( file , "%f" , &sampleFeatureMat.at<float>( i , j ) );}}}fclose( file );}void image_SVMClassify(){getTrainingDataAndLabel();cout << "开始训练Auto分类器..." << endl;cv::Ptr<cv::ml::SVM> m_SVM = cv::ml::SVM::create();m_SVM->setType( cv::ml::SVM::C_SVC );     // SVM类型为C_SVM,可以进行2类以上的分类m_SVM->setKernel( cv::ml::SVM::LINEAR );  // 核函数径向基函数,线性的不可分没法用m_SVM->setC( 0.01 );          // 应该是松弛因子的惩罚系数C ?m_SVM->setTermCriteria( cv::TermCriteria( CV_TERMCRIT_ITER + CV_TERMCRIT_EPS , 1000 , FLT_EPSILON ) );//设定终止条件为迭代1000次或者误差小于FLT_EPSILONcv::Ptr<cv::ml::TrainData> trainDataSet = cv::ml::TrainData::create( sampleFeatureMat , cv::ml::ROW_SAMPLE , sampleLabelMat );m_SVM->trainAuto( trainDataSet , 10 ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::C ) ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::GAMMA ) ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::P ) ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::NU ) ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::COEF ) ,cv::ml::SVM::getDefaultGrid( cv::ml::SVM::DEGREE ) ,true );//m_SVM->train( sampleFeatureMat , cv::ml::SampleTypes::ROW_SAMPLE , sampleLabelMat );cv::Mat image = cv::imread( "8_90.jpg" , 0 );//cv::imshow( "Image" , image );cv::Mat test( 1 , 64 , CV_32FC1 );for( int i = 0; i < image.rows; i++ )   //投影到X轴的所有像素和{int sum = 0;uchar* ptr = image.ptr( i );for( int j = 0; j < image.cols; j++ ){sum += ptr[j];}test.at<float>( 0 , i ) = sum;}for( int j = 0; j < image.cols; j++ )   //投影到Y轴的所有像素和{int sum = 0;for( int i = 0; i < image.rows; i++ ){sum += image.at<uchar>( i , j );}test.at<float>( 0 , image.rows + j ) = sum;}int response = ( int ) m_SVM->predict( test );printf( "response:%d\n" , response );}

最后的结果输出类似如下:



0 0
原创粉丝点击