libsvm库是一个开源的svm多语言支持库,官网地址https://www.csie.ntu.edu.tw/~cjlin/libsvm/,github地址https://github.com/cjlin1/libsvm
1.在c++中使用Libsvm库,第一步是将github中的svm.h,svm.cpp拷贝到CMakeLists调用的第三方库位置,然后就可以在自己的代码中使用,关于CMakeLists的编写和svm原理可以自行了解。
2.训练
只是关键一部分,主要记录下相关语法调用
//SVM 基于libsvm
std::string model_path= "../MODEL/svm.xml";
void trainSVM()
{
//定义训练集和测试集的样本数
const int sampleSum=18*3;
//读取训练数据,先以模板为训练集
boost::format fmt_train_SVM("../train/temp%d.png");
std::vector<cv::Mat> train_data;
for (size_t i = 1; i < sampleSum+1; i++) //读取
{
cv::Mat data=cv::imread( (fmt_train_SVM % i).str() ,0);
cv::Mat dataShape=data.reshape(1,1);
train_data.emplace_back(dataShape);
}
//设置标签 训练样本所属类别
int labels[sampleSum] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
// 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
};
svm_problem problem;
problem.l=sampleSum; //训练样本数
problem.x = new svm_node*[sampleSum]; //特征矩阵
problem.y = new double[sampleSum]; //标签矩阵
for (int i=0; i<sampleSum; ++i)
{
problem.x[i] = new svm_node[420*240+1]; //
for(int j=0; j<420*240; ++j)
{
problem.x[i][j].index = j + 1;
problem.x[i][j].value = train_data[i].at<uchar>(0,j);
}
problem.x[i][420*240].index = -1;
problem.y[i] = labels[i];
}
//参数
svm_parameter param;
param.svm_type=C_SVC;
param.kernel_type=LINEAR;
param.degree=3;
param.gamma=0.01;
param.coef0=0;
param.cache_size=20;
param.eps=1e-6;
param.C=1;
param.nr_weight=0;
param.weight_label=nullptr;
param.weight=nullptr;
param.nu=0.5;
param.p=0.1;
param.shrinking=0;
param.probability=0; //改成1后预测结果差得很大
//train
auto model = svm_train(&problem, ¶m);
//save
if (svm_save_model(model_path.c_str(), model))
{
std::cerr << "Save SVM to [" << model_path << "] FAILED" << std::endl;
}
else
{
std::cout << "Save SVM to [" << model_path << "] SUCCEED." << std::endl;
}
}
3.测试
//返回svm,基于libsvm
int testSVM(cv::Mat singleLabelMat)
{
//1.get model
svm_model *model=svm_load_model(model_path.c_str());
//mat to svm_node
cv::Mat sam=singleLabelMat.clone();
cv::Mat samShape= sam.reshape(1,1);
svm_node *sample=new svm_node[420*240+1];
for (size_t i = 0; i < 420*240; i++)
{
sample[i].index=i+1;
sample[i].value=samShape.at<uchar>(0,i);
}
sample[420*240+1].index=-1;
double probresut[18];
double resultLabel=svm_predict_probability(model,sample,probresut);
//double resultLabel=svm_predict(model,sample);
std::cout<<"labels: "<<resultLabel<<" "<<std::endl;
return int(resultLabel);
}