以上是我上一篇文章中的代码实现,里面分别用了opencv中的SVM和LibSVM,opencv的SVM用起来更方便,但貌似内部其实也是基于Libsvm,同样的参数训练出来的结果是一致的,里面有Libsvm的调用过程,如果用libsvm需要在工程里面添加libsvm的源码文件分别是svm.h和svm.cpp,林智仁的库里自带的那两个核心文件即可。

libsvm的用法让人更感觉是在用C的写法,opencv封装过的易用性更好,稍后我会把工程文件放到github上供大家下载,若有什么错误,还请批评指教~,这里用的是Minist的数据集,图像时我经过处理后的单张图像,大小为20*20,里面有详细的函数使用说明

[https://github.com/YihangLou/SVM-Minist-HandWriting-Recognition] Github上的工程链接

// DigitsRec_HOG_SVM.cpp : 定义控制台应用程序的入口点。
#include "opencv2/opencv.hpp"
#include "fstream"
#include "svm.h"
using namespace std;
using namespace cv; #define srcfeature vector<string> trainImageList;//训练图像列表,此处路径
vector<int> trainLabelList; //标签
vector<string> testImageList;//训练图像列表,此处路径
string trainImageFile= "D:\\WorkSpace\\homework\\PatternRecognization\\第一次作业\\minist\\train_image\\imagelist.txt";
string testImageFile = "D:\\WorkSpace\\homework\\PatternRecognization\\第一次作业\\minist\\test_image\\imagelist.txt";
string testBasePath = "D:\\WorkSpace\\homework\\PatternRecognization\\第一次作业\\minist\\test_image\\";
string trainBasePath = "D:\\WorkSpace\\homework\\PatternRecognization\\第一次作业\\minist\\train_image\\";
string SVMModel ="svm_model.xml";
CvMat * dataMat;
CvMat * labelMat; //***************************************************************
// 名称: readTrainFileList
// 功能: 读取训练的图像列表和图像的位置
// 权限: public
// 返回值: void
// 参数: string trainImageFile 文件列表
// 参数: string basePath 基地址
// 参数: vector<string> & trainImageList 图像路径list
// 参数: vector<int> & trainLabelList 图像标签list
//***************************************************************
void readTrainFileList(string trainImageFile, string basePath, vector<string> &trainImageList, vector<int> &trainLabelList)
{
ifstream readData( trainImageFile );
string buffer;
while( readData )
{
if( getline( readData, buffer))
{
int label = int((buffer[0])-'0');//在我这里路径中第一个文件夹就是类别
trainLabelList.push_back( label);
trainImageList.push_back( buffer );//图像路径
}
}
readData.close();
cout<<"Read Train Data Complete"<<endl;
} //***************************************************************
// 名称: readTestFileList
// 功能: 读测试文件
// 权限: public
// 返回值: void
// 参数: string testImageFile
// 参数: string basePath
// 参数: vector<string> & testImageList 测试图像列表
//***************************************************************
void readTestFileList(string testImageFile, string basePath, vector<string> &testImageList)
{
ifstream readData( testImageFile ); //加载测试图片集合
string buffer;
while( readData )
{
if( getline( readData, buffer))
{
testImageList.push_back( buffer );//图像路径
}
}
readData.close();
cout<<"Read Test Data Complete"<<endl;
} //***************************************************************
// 名称: processHogFeature
// 功能: 计算Hog特征
// 权限: public
// 返回值: void
// 参数: vector<string> trainImageList
// 参数: vector<int> trainLabelList
// 参数: CvMat * & dataMat
// 参数: CvMat * & labelMat
//***************************************************************
void processHogFeature(vector<string> trainImageList,vector<int> trainLabelList, CvMat * &dataMat,CvMat * &labelMat)
{ int trainSampleNum = trainImageList.size();
dataMat = cvCreateMat( trainSampleNum, 324, CV_32FC1 ); //324为Hog feature Size
cvSetZero( dataMat );
labelMat = cvCreateMat( trainSampleNum, 1, CV_32FC1 );
cvSetZero( labelMat );
IplImage* src;
IplImage* trainImg=cvCreateImage(cvSize(20,20),8,3);//20 20 for( int i = 0; i != trainImageList.size(); i++ )
{
src=cvLoadImage( (trainBasePath + trainImageList[i]).c_str(),1);
if( src == NULL )
{
cout<<" can not load the image: "<<(trainBasePath + trainImageList[i]).c_str()<<endl;
continue;
}
//cout<<"Calculate Hog Feature "<<(trainBasePath + trainImageList[i]).c_str()<<endl; cvResize(src,trainImg);
HOGDescriptor *hog=new HOGDescriptor(cvSize(20,20),cvSize(10,10),cvSize(5,5),cvSize(5,5),9);
vector<float>descriptors;
hog->compute(trainImg, descriptors,Size(1,1), Size(0,0)); int j =0;
for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
{
cvmSet(dataMat,i,j,*iter);//存储HOG特征
j++;
}
cvmSet( labelMat, i, 0, trainLabelList[i] );
//cout<<"Image and label "<<trainImageList[i].c_str()<<" "<<trainLabelList[i]<<endl;
}
cout<<"Calculate Hog Feature Complete"<<endl;
cout<<dataMat<<endl;
} void processNonFeature(vector<string> trainImageList,vector<int> trainLabelList, CvMat * &dataMat,CvMat * &labelMat)
{ int trainSampleNum = trainImageList.size();
dataMat = cvCreateMat( trainSampleNum, 400, CV_32FC1 ); //324为Hog feature 大小,需提前设置
cvSetZero( dataMat );
labelMat = cvCreateMat( trainSampleNum, 1, CV_32FC1 );
cvSetZero( labelMat );
IplImage* src;
IplImage* resizeImg=cvCreateImage(cvSize(20,20),8,3);//20 20是训练样本的大小 for( int i = 0; i != trainImageList.size(); i++ )
{
src=cvLoadImage( (trainBasePath + trainImageList[i]).c_str(),1);
if( src == NULL )
{
cout<<" can not load the image: "<<(trainBasePath + trainImageList[i]).c_str()<<endl;
continue;
}
//cout<<"Calculate Hog Feature "<<(trainBasePath + trainImageList[i]).c_str()<<endl; cvResize(src,resizeImg);
IplImage * grayImage = cvCreateImage(cvGetSize(resizeImg), IPL_DEPTH_8U, 1);
cvCvtColor(resizeImg,grayImage,CV_BGR2GRAY);
//二值化图像
IplImage * binaryImage = cvCreateImage(cvGetSize(grayImage),IPL_DEPTH_8U,1);
cvThreshold(grayImage,binaryImage,25,255,CV_THRESH_BINARY);
//cvNamedWindow("src");
//cvShowImage("src", src); //cvNamedWindow("show");
//cvShowImage("show", binaryImage);
//cvWaitKey(0);//这里是看一下二值化的效果怎么样
HOGDescriptor *hog=new HOGDescriptor(cvSize(20,20),cvSize(10,10),cvSize(5,5),cvSize(5,5),9);
vector<float>descriptors; int j =0; //j为矩阵的水平坐标,要把特征从vector中拷贝过来
uchar * tmp = new uchar;
for(int n=0;n<binaryImage->height;n++)
{ for(int m=0;m<binaryImage->width;m++)
{
*tmp=((uchar *)(binaryImage->imageData + n*binaryImage->widthStep))[m];
cvmSet(dataMat,i,j,*tmp);//存储HOG特征
j++;
}
} cvmSet( labelMat, i, 0, trainLabelList[i] );
//cout<<"Image and label "<<trainImageList[i].c_str()<<" "<<trainLabelList[i]<<endl;
}
cout<<"Calculate Hog Feature Complete"<<endl; } //***************************************************************
// 名称: trainSVM
// 功能: 此处用的是opencv的SVM训练
// 权限: public
// 返回值: void
// 参数: CvMat * & dataMat
// 参数: CvMat * & labelMat
//***************************************************************
void trainSVM(CvMat * & dataMat,CvMat * & labelMat )
{
cout<<"train svm start"<<endl;
cout<<dataMat<<endl;
CvSVM svm;
CvSVMParams param;//这里是SVM训练相关参数
CvTermCriteria criteria;
criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );
param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria ); svm.train( dataMat, labelMat, NULL, NULL, param );//训练数据
svm.save( SVMModel.c_str());
cout<<"SVM Training Complete"<<endl;
} //***************************************************************
// 名称: trainLibSVM
// 功能: 此处用的是LibSVM库的SVM训练
// 权限: public
// 返回值: void
// 参数: CvMat * & dataMat
// 参数: CvMat * & labelMat
//***************************************************************
void trainLibSVM(CvMat *& dataMat, CvMat * & labelMat)
{
cout<<"LibSVM start"<<endl;
//配置SVM参数
svm_parameter param;
//param.svm_type = C_SVC;
param.svm_type = EPSILON_SVR;
param.kernel_type = RBF;
param.degree = 10.0;
param.gamma = 0.09;
param.coef0 = 1.0;
param.nu = 0.5;
param.cache_size = 1000;
param.C = 10.0;
param.eps = 1e-3;
param.p = 1.0; //svm_prob读取
svm_problem svm_prob; int sampleNum = dataMat->rows;
int vectorLength = dataMat->cols; svm_prob.l = sampleNum;
svm_prob.y = new double [sampleNum]; for (int i = 0; i < sampleNum; i++)
{
svm_prob.y[i] = cvmGet(labelMat,i,0);
} cout<<"LibSVM middle"<<endl;
svm_prob.x = new svm_node * [sampleNum]; for (int i = 0; i < sampleNum; i++)
{
svm_node * x_space = new svm_node [vectorLength + 1];
for (int j = 0; j < vectorLength; j++)
{
x_space[j].index = j;
x_space[j].value = cvmGet(dataMat,i,j); }
x_space[vectorLength].index = -1;//注意,结束符号,一开始忘记加了 svm_prob.x[i] = x_space;
} cout<<"LibSVM end"<<endl;
svm_model * svm_model = svm_train(&svm_prob, &param);
#ifdef srcfeature
svm_save_model("libsvm_minist_src_feature_model_.model",svm_model);
#else
svm_save_model("libsvm_minist_model.model",svm_model);
#endif
for (int i=0 ; i < sampleNum; i++)
{
delete [] svm_prob.x[i];
} delete [] svm_prob.y;
svm_free_model_content(svm_model);
} //***************************************************************
// 名称: testSVM
// 功能: 测试opencv训练的SVM准确率
// 权限: public
// 返回值: void
// 参数: vector<string> testImageList
// 参数: string SVMModel
//***************************************************************
void testSVM(vector<string> testImageList, string SVMModel)
{
CvSVM svm;
svm.load(SVMModel.c_str());//加载模型文件 IplImage* testImage;
IplImage* tempImage;
char buffer[512]; ofstream ResultOutput( "predict_result.txt" );//把预测结果存储在这个文本中
for( int j = 0; j != testImageList.size(); j++ )//依次遍历所有的待检测图片
{
testImage = cvLoadImage( (testBasePath+testImageList[j]).c_str(), 1);
if( testImage == NULL )
{
cout<<" can not load the image: "<<(testBasePath+testImageList[j]).c_str()<<endl;
continue;
}
tempImage =cvCreateImage(cvSize(20,20),8,3);
cvZero(tempImage);
cvResize(testImage,tempImage);
HOGDescriptor *hog=new HOGDescriptor(cvSize(20,20),cvSize(10,10),cvSize(5,5),cvSize(5,5),9);
vector<float>descriptors; hog->compute(tempImage, descriptors,Size(1,1), Size(0,0));
CvMat* TempMat=cvCreateMat(1,descriptors.size(),CV_32FC1);
int n=0;
for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
{
cvmSet(TempMat,0,n,*iter);
n++;
} int resultLabel = svm.predict(TempMat);//检测结果
sprintf( buffer, "%s %d\r\n",testImageList[j].c_str(),resultLabel );
ResultOutput<<buffer;
}
cvReleaseImage(&testImage);
cvReleaseImage(&tempImage);
ResultOutput.close();
cout<<"SVM Predict Complete"<<endl;
} //***************************************************************
// 名称: testLibSVM
// 功能: 测试LisbSVM训练的模型的分类性能
// 权限: public
// 返回值: void
// 参数: string LibSVMModelFile
// 参数: vector<string> testImageList
// 参数: string SVMModel
//***************************************************************
void testLibSVM(string LibSVMModelFile, vector<string> testImageList, string SVMModel)
{ svm_model * svm = svm_load_model(LibSVMModelFile.c_str()); IplImage* testImage;
IplImage* tempImage;
char buffer[512]; ofstream ResultOutput( "libsvm_predict_result.txt" );
for( int j = 0; j != testImageList.size(); j++ )//依次遍历所有的待检测图片
{
testImage = cvLoadImage( (testBasePath+testImageList[j]).c_str(), 1);
if( testImage == NULL )
{
cout<<" can not load the image: "<<(testBasePath+testImageList[j]).c_str()<<endl;
continue;
}
tempImage =cvCreateImage(cvSize(20,20),8,3);
cvZero(tempImage);
cvResize(testImage,tempImage);
HOGDescriptor *hog=new HOGDescriptor(cvSize(20,20),cvSize(10,10),cvSize(5,5),cvSize(5,5),9);
vector<float>descriptors; hog->compute(tempImage, descriptors,Size(1,1), Size(0,0)); svm_node * inputVector = new svm_node [ descriptors.size()+1];
int n = 0;
for(vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
{
inputVector[n].index = n;
inputVector[n].value = *iter;
n++;
}
inputVector[n].index = -1; int resultLabel = svm_predict(svm,inputVector);//分类结果
sprintf( buffer, "%s %d\r\n",testImageList[j].c_str(),resultLabel );
ResultOutput<<buffer;
delete [] inputVector;
}
svm_free_model_content(svm);
cvReleaseImage(&testImage);
cvReleaseImage(&tempImage);
ResultOutput.close();
cout<<"SVM Predict Complete"<<endl;
} //***************************************************************
// 名称: releaseAll
// 功能: 释放相应的资源
// 权限: public
// 返回值: void
//***************************************************************
void releaseAll()
{ cvReleaseMat( &dataMat );
cvReleaseMat( &labelMat);
cout<<"Release All Complete"<<endl;
} //***************************************************************
// 名称: main
// 功能: 这里用了两种SVM,一种是opencv中的,一种是libsvm中的,训练测试需要选择相对应的svm
// 权限: public
// 返回值: int
//***************************************************************
int main()
{ readTrainFileList(trainImageFile,trainBasePath,trainImageList,trainLabelList);
processHogFeature(trainImageList,trainLabelList, dataMat,labelMat);
//trainSVM(dataMat,labelMat );
//processNonFeature(trainImageList,trainLabelList, dataMat,labelMat);
trainLibSVM(dataMat,labelMat);
//readTestFileList( testImageFile, testBasePath, testImageList);
testLibSVM("libsvm_minist_model.model",testImageList,SVMModel);
//testSVM( testImageList, SVMModel);
releaseAll();
return 0;
}

libsvm Minist Hog 手写体识别(源码文件)的更多相关文章

  1. libsvm Minist Hog 手写体识别

    统计手写数字集的HOG特征 转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ 这篇文章是模式识别的小作业,利用sv ...

  2. [C/C++] 各种C/C++编译器对UTF-8源码文件的兼容性测试(VC、GCC、BCB)

    在不同平台上开发C/C++程序时,为了避免源码文件乱码,得采用UTF-8编码来存储源码文件.但是很多编译器对UTF-8源码文件兼容性不佳,于是我做了一些测试,分析了最佳保存方案. 一.测试程序 为了测 ...

  3. 《UNIX网络编程(第3版)》unp.h等源码文件的编译安装

    操作系统:Mac OS X 10.11.5 1.下载书中的源代码:点击下载 2.切换到解压后的目录 unpv13e,先查看下 README,依次执行: ./configure cd lib make ...

  4. Erlang千万级用户游戏框架(Openpoker)源码文件分析清单

    openpoker源码 erlang写的网游服务器源码,OpenPoker是一个大型多人扑克网游,内建支持了容错能力,负载平衡和无限制的规模大小.本文是openpoker源码文件功能的一个清单式说明: ...

  5. C++ 多源码文件简单组织

    C++ 多源码文件简单组织 基本上和C的是一样的,只不过C++的方法要在类中声明.看一个简单实例.ainimal.h  类里面对外公开的信息. 点击(此处)折叠或打开 #ifndef _ANIMAL_ ...

  6. Python源码文件中带有中文时,输出乱码

    Python源码文件中带有中文时,文件头应加注释: #!/usr/bin/env python # -*- coding: utf-8 -*- 第一行注释是为了告诉Linux/OS X系统,这是一个P ...

  7. 对threading模块源码文件的解读(不全)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #对threading模块源码文件的解读(不全) import threading #类 #Thread() ...

  8. TFS二次开发-基线文件管理器(5)-源码文件的读取

      在上一节中,我们在保存标签之前,已经将勾选的文件路径保存到了Listbox中,这里只需要将保存的数据输出去为txt文档就可以做版本控制了.   版本文件比较复杂的是如何读取,也就是如何通过文件路径 ...

  9. go语言的源码文件的分类及含义

    Go源码文件:名称以.go为后缀,内容以Go语言代码组织的文件 多个Go源码文件是需要用代码包组织起来的 源码文件分为三类:命令源码文件.库源码文件(go语言程序) 测试源码文件(辅助源码文件) 命令 ...

随机推荐

  1. 钉钉如何进行PC端开发

    前段时间,用钉钉进行了服务器端的开发,对照着官方文档,感觉还是比较顺利的.后续想有时间研究一下PC端客户端的开发,看着官方文档,说的确实是比较简练,但也确实没看太明白,废了半天劲也没成功.后来经过无数 ...

  2. (转)JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)

     JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)         函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过 ...

  3. swift学习笔记之-泛型

    //泛型(Generics) import UIKit /*泛型(Generics):泛型代码可以让你编写适用自定义需求以及任意类型的灵活可重用的函数和类型.它的可以让你避免重复的代码,用一种清晰和抽 ...

  4. 如何:对 SharePoint 列表项隐藏 ECB 中的菜单项

    可以通过使用功能框架向编辑控制块 (ECB) 菜单添加新的自定义操作.但是,您不能使用此方法进行相反的操作,即隐藏现有的 ECB 菜单项,因为它们是通过使用 ECMAScript(JavaScript ...

  5. EWS API 2.0读取日历信息-读取内容注意事项

    采用模拟账号的方式读取日历信息,注意下日历的内容读取(Body)读取.代码如下:(采用 EWS API 2.0版本) 1.读取内容前必须设置如下属性:否则会提示:You must load or as ...

  6. Android 获取图片exif信息

    使用android api读取图片的exif信息 布局代码: <LinearLayout xmlns:android="http://schemas.android.com/apk/r ...

  7. Android JNI简介

    JNI简介 JNI (Java Native Interface),Java的本地接口 JNI是Java众多开发技术中的一门,意在利用本地代码,为Java程序提供 更高效,更灵活的拓展.应用场景包括: ...

  8. Android App监听软键盘按键的三种方式与改变软键盘右下角确定键样式

    actionNone : 回车键,按下后光标到下一行actionGo : Go,actionSearch : 放大镜actionSend : SendactionNext : NextactionDo ...

  9. C#参考书的链接推荐

    Visual C#.NET入门与提高http://download.chinaitlab.com/soft/6330.htm 使用Visual C# 开发asp.NET入门http://downloa ...

  10. PlantUML的实例参考

    project: blog target: plant-uml-instances.md date: 2015-12-24 status: publish tags: - PlantUML - UML ...