opencv3.4-SVM使用

从0基于开始使用opencv关于SVM的使用,网上查阅相关资料后,终于可以相应的实现功能,相应的代码如下。

但是需要注意的几个问题,这也是我遇到的已经解决的,类型不对会出现相应的断言。

  1. 样本数据必须是CV_32FC1类型。opencv3版本决定的
  2. 样本标签必须是CV_32SC1,opencv3后从int数组转换为CV_32SC1类型,而opencv2是从float数据转换。

但是没有弄明白的是支持向量为什么是(0,0),不是应该是样本中的一些值么?

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"
//#include "ml.h"
using namespace cv;
#include
using namespace std;
 
int main( )

    //Console::WriteLine(L"Hello World");
int iWidth = 512, iheight = 512;
cv::Mat matImg = cv::Mat::zeros(iheight, iWidth, CV_8UC3);//三色通道


//1.获取样本
int labels[5] = { 1.0, -1.0, -1.0, -1.0,1.0 }; //样本数据  
Mat labelsMat(5, 1, CV_32SC1, labels);     //样本标签  
float trainingData[5][2] = { { 501, 300 },{ 255, 10 },{ 501, 255 },{ 10, 501 },{ 450,500 } }; //Mat结构特征数据  
Mat trainingDataMat(5, 2, CV_32FC1, trainingData);   //Mat结构标签  
//2.设置SVM参数

cv::Ptr svm = cv::ml::SVM::create();
svm->setType(cv::ml::SVM::C_SVC);//可以处理非线性分割的问题
svm->setKernel(cv::ml::SVM::LINEAR);//径向基函数
/*svm->setGamma(0.01);
svm->setC(10.0);*/
//算法终止条件
svm->setTermCriteria(cv::TermCriteria(CV_TERMCRIT_ITER, 100, 1e-6));

//3.训练支持向量
svm->train(trainingDataMat, ml::SampleTypes::ROW_SAMPLE,labelsMat);

//4.保存训练器
svm->save("mnist_svm.xml"); 

//5.导入训练器
//Ptr svm1 = StatModel::load("mnist_dataset/mnist_svm.xml");


//读取测试数据


cv::Vec3b green(0, 255, 0), blue(255, 0, 0);
for (int i = 0; i < matImg.rows; i++)
{
for (int j = 0; j < matImg.cols; j++)
{
cv::Mat sampleMat = (cv::Mat_(1, 2) << j,i);
float fRespone = svm->predict(sampleMat); 
if (fRespone == 1)
{
matImg.at(i,j) = green;
}
else if(fRespone   == -1)
{
matImg.at(i,j) = blue;
}


}
}


// Show the training data  
int thickness = -1;
int lineType = 8;
for (int i = 0; i < trainingDataMat.rows;i++)
{
if (labels[i] == 1)
{
circle(matImg, cv::Point(trainingData[i][0], trainingData[i][1]), 5, cv::Scalar(0, 0, 0), thickness, lineType);
}
else
{
circle(matImg, cv::Point(trainingData[i][0], trainingData[i][1]), 5, cv::Scalar(255, 255, 255), thickness, lineType);
}
}
//cvShowImage("circle", &((IplImage)matImg)); // show it to the user  
//cvWaitKey(0);


//显示支持向量点
thickness = 2;
lineType = 8;
cv::Mat vec = svm->getSupportVectors();
int nVarCount = svm->getVarCount();//支持向量的维数
for (int i = 0; i < vec.rows; ++i)
{
int x = (int)vec.at(i, 0);
int y = (int)vec.at(i, 1);
circle(matImg, Point(x,y), 6, Scalar(0, 0, 255), thickness, lineType);
}





cvShowImage("circle", &((IplImage)matImg)); // show it to the user  
cvWaitKey(0);

    return 0;
}
 

相关的也可以参照 http://blog.csdn.net/guoyunfei20/article/details/78105493

如果核函数用ml::SVM::LINEAR,下边Mat SupportVectorsMat = svm->getSupportVectors();将无法正常输出支持向量。这并非BUG,官方解释:

[cpp]  view plain  copy
  1. https://github.com/Itseez/opencv/blob/2.4/modules/ml/src/svm.cpp#L1531  
将所有支持向量压缩为了一个,这样做可以极大地优化线性核时的运行效率。

你可能感兴趣的:(opencv3.4-SVM使用)