SVM(Support Vector Machine),是一种有监督的学习模型,通常用来进行模式识别、分类、以及回归分析。
概括来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。
通俗来说,我们先让用训练样本告诉两个人(例如两分类问题)哪一类东西分别是他们的。然后我们给他们一些测试样本,他们就各自去拿属于他们的,那些类别标示很明显的,当然毫无争议。但是,那些类别标示不是很明显的,他们根据我们给他们设定的规则(参数)据理力争,想拔河一样你争我夺,最后找到归属。我们的目标是找到一个最好的规则,让样本毫无争议的归属它的主人。但是,这是理想情况,现实是那条理想的规则(最优超平面)不容易找到,甚至经常出现错分的情况。
SVM的数学意义,很是深奥,推到相对复杂,在这里不做深究,这篇文章主要关注与应用。因为,笔者认为,大部分人学SVM主要是为了应用,至于原理以及改进,让那些专家大牛考虑吧。
对于理论方面,感有兴趣的朋友请参考此博文:http://blog.youkuaiyun.com/v_july_v/article/details/7624837
对于应用,最好最快的学习方法就是看例题了,接下来我们通过一个多分类的例子来详细学习OpenCV中SVM的使用。
在学习例子之后,笔者会给出OpenCV中SVM的使用介绍。
#include <cv.h>
#include <highgui.h>
#include <ml.h>
#include <time.h>
#include <ctype.h>
#include <iostream>
using namespace std;
int main()
{
int size=400; //图像尺寸
const int s=100; //样本点的个数
int i,j,sv_num;
IplImage *img=0;
//SVM声明
CvSVM svm=CvSVM();
CvSVMParams param;
CvTermCriteria criteria; //停止迭代的标准
CvRNG rng=cvRNG(time(NULL));
CvPoint pts[s]; //定义100个点
float data[s*2]; //点的坐标
int res[s]; //点的类别
CvMat data_mat,res_mat;
CvScalar rcolor;
const float* support;
//图像区域的初始化,清0
img = cvCreateImage(cvSize(size,size),IPL_DEPTH_8U,3);
cvZero(img);
//学习数据的生成
for(i=0;i<s;i++)
{
pts[i].x=cvRandInt(&rng)%size;//用随机整数赋值
pts[i].y=cvRandInt(&rng)%size;
//定义三类学习数据
if (pts[i].y> 50 * cos(pts[i].x* CV_PI/ 100) + 200)
{
cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(255, 0, 0));
cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(255, 0, 0));
res[i] = 1;
}
else
{
if (pts[i].x> 200)
{
cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 255, 0));
cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 255, 0));
res[i] = 2;
}
else
{
cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 0, 255));
cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 0, 255));
res[i] = 3;
}
}
}
//学习数据的显示
cvNamedWindow("SVM_samples", CV_WINDOW_AUTOSIZE);
cvShowImage("SVM_samples", img);
cvWaitKey(5000);
//学习参数的生成
for (i= 0; i< s; i++)
{
data[i* 2] = float (pts[i].x) / size;
data[i* 2 + 1] = float (pts[i].y) / size;
}
cvInitMatHeader(&data_mat, s, 2, CV_32FC1, data);
cvInitMatHeader(&res_mat, s, 1, CV_32SC1, res);
//SVM参数设置的两种形式:经测试,第2种没有第一种效果好,因为第一种我们制定了详细的参数
//而,第2种我们用的是默认的参数
//1.
criteria= cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);//类型,最大迭代数,双精度数
param= CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 20.0, 0.5, 0.1, NULL, criteria);
/*2.
param.svm_type = CvSVM::C_SVC;
param.kernel_type = CvSVM::RBF;
param.term_crit=cvTermCriteria(CV_TERMCRIT_EPS,1000,FLT_EPSILON);
*/
//利用训练数据和确定的学习参数,训练SVM
svm.train(&data_mat, &res_mat, NULL, NULL, param);
//学习结果的绘图,将size内的所有像素(特征向量)进行分类,直观的显示出分类结果
for (i= 0; i< size; i++)
{
for (j= 0; j< size; j++)
{
CvMat m;
float ret = 0.0;
float a[] = { float (j) / size, float (i) / size };
cvInitMatHeader(&m, 1, 2, CV_32FC1, a);
ret= svm.predict(&m);
switch ((int) ret)
{
case 1:
rcolor= CV_RGB(100, 0, 0);
break;
case 2:
rcolor= CV_RGB(0, 100, 0);
break;
case 3:
rcolor= CV_RGB(0, 0, 100);
break;
}
cvSet2D(img, i, j, rcolor);
}
}
//训练数据的重新绘制,注意之前的训练数据的绘制用了5S显示,现在需要重新绘制
for (i= 0; i< s; i++)
{
CvScalar rcolor;
switch (res[i])
{
case 1:
rcolor= CV_RGB(255, 0, 0);
break;
case 2:
rcolor= CV_RGB(0, 255, 0);
break;
case 3:
rcolor= CV_RGB(0, 0, 255);
break;
}
cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), rcolor);
cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), rcolor);
}
//绘制支持向量,用白色的圆圈对支持向量作标记
sv_num= svm.get_support_vector_count();
for (i= 0; i< sv_num; i++)
{
support = svm.get_support_vector(i);
cvCircle(img, cvPoint((int) (support[0] * size), (int) (support[1] * size)), 5, CV_RGB(200, 200, 200));
}
/*
创建一个特征向量,测试分类结果
CvMat *zx = cvCreateMat(2,1,CV_32FC1);
cvmSet(zx,0,0,0.56);
cvmSet(zx,1,0,0.28);
float lei = svm.predict(zx);
cout<<lei<<endl;
*/
//显示最终的图像
cvNamedWindow("SVM_result1", CV_WINDOW_AUTOSIZE);
cvShowImage("SVM_result1", img);
cvWaitKey(0);
cvDestroyWindow("SVM");
cvReleaseImage(&img);
return 0;
}
运行结果:
1.学习数据显示图像:
2.分类结果图(参数设置用方法1):
3.分类结果图(参数设置用方法2):
OpenCV_SVM使用介绍:
设置SVM参数
struct CvSVMParams
SVM 训练参数结构。
该结构必须被初始化后,传给CvSVM。
CvSVMParams::CvSVMParams
构造函数
C++:

本文介绍了SVM的基本概念和在OpenCV中的应用。通过一个多分类例子,详细讲解了如何使用OpenCV的SVM类,包括CvSVMParams、CvSVM的构造与训练方法,如train、train_auto等,以及预测和获取支持向量的相关函数。旨在帮助读者理解并掌握SVM的实际运用。
最低0.47元/天 解锁文章
1060

被折叠的 条评论
为什么被折叠?



