SVM手写字符识别小程序

该程序是基于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,1
	sampleFeatureMat.setTo( 0 );   // 850,64
	
	cout << "开始读取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_EPSILON

	cv::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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值