如何使用opencv中的svm分类器

版权声明:本文为博主原创文章,转载注明出处。 https://blog.csdn.net/pengjc2001/article/details/60871621

最近掉进了机器学习的坑了。算法的开发应该是科学家的事,但算法的应用就是工程师的事了。Halcon提供了的工具太自动化了。当你还没意识过来,结果就出来了。想用opencv来实现一个简单的字符识别程序。分类器就选svm吧。(目前就接触了knn svm,但是感觉knn太暴力)。svm提供一种二分法的手段。对于解决是非问题再好不过了。在《Mastering OpenCV with Practical Computer Vision Projects》中车牌识别的方案中,就用它来找车牌。是车牌 or 不是车牌。

目前我要关注的是

1、 如何给它喂数据、如何设计参数、如何用的问题。

2、它是一种二分法的手段,那如何扩展到多分类呢。

关于问题1:

a、需要两组数据,对象的特征描述数据、及其相对应的类别标识

Mat trainingDataMat(4, 2, CV_32FC1, trainingData);     //由已知数组 转换 到Mat 矩阵

Mat labelsMat(4, 1, CV_32SC1, labels);

Mat data = Mat::zeros(testCount, 2, CV_32FC1);   //预先产生一个 testCount X 2 的矩阵

Mat res = Mat::zeros(testCount, 1, CV_32SC1);

trainData: 练习数据,必须是CV_32FC1 (32位浮点类型,单通道)。数据必须是CV_ROW_SAMPLE的,即特点向量以行来存储。

labelsData: 类别标识数据, 1D向量存储在CV_32SC1 (32位 int )或者CV_32FC1 格式

b、算法设置

设置核函数类型     由函数 setKernel() 完成设置 (如 setKernel(SVM::RBF))

KernelTypes   核函数类型                
CUSTOM  
Returned by SVM::getKernelType in case when custom kernel has been set 
 
LINEAR   线性内核,没有任何向映射至高维空间,线性区分(或回归)在原始特点空间中被完成,这是最快的选择。
Linear kernel. No mapping is done, linear discrimination (or regression) is done in the original feature space. It is the fastest option. K(x i ,x j )=x T i x j  . 
 
POLY  多项式内核
Polynomial kernel: K(x i ,x j )=(γx T i x j +coef0) degree ,γ>0 . 
 
RBF  基于径向的函数,对于大多半景象都是一个较好的选择
Radial basis function (RBF), a good choice in most cases. K(x i ,x j )=e −γ||x i −x j || 2  ,γ>0 . 
 
SIGMOID   Sigmoid函数内核
Sigmoid kernel: K(x i ,x j )=tanh(γx T i x j +coef0) . 
 
CHI2  
Exponential Chi2 kernel, similar to the RBF kernel: K(x i ,x j )=e −γχ 2 (x i ,x j ) ,χ 2 (x i ,x j )=(x i −x j ) 2 /(x i +x j ),γ>0 . 
 
INTER  
Histogram intersection kernel. A fast kernel. K(x i ,x j )=min(x i ,x j ) . 


指定svm类型  svm->setType(SVM::C_SVC);

svm_type:指定SVM的类型(5种):

C_SVC   C类支撑向量分类机。 n类分组 (n≥2),容许用异常值处罚因子C进行不完全分类。

C-Support Vector Classification. n-class classification (n ≥  2), allows imperfect separation of classes with penalty multiplier C for outliers.  

NU_SVC   ν -类支撑向量分类机。n类似然不完全分类的分类器。参数为庖代C(其值在区间【0,1】中,nu越大,决定计划鸿沟越腻滑)

ν -Support Vector Classification. n-class classification with possible imperfect separation. Parameter ν  (in the range 0..1, the larger the value, the smoother the decision

boundary) is used instead of C.  

ONE_CLASS   单分类器,所有的练习数据提取自同一个类里,然后SVM建树了一个分界线以分别该类在特点空间中所占区域和其它类在特点空间中所占区域。

Distribution Estimation (One-class SVM). All the training data are from the same class, SVM builds a boundary that separates the class from the rest of the feature space. 

 EPS_SVR   ϵ -类支撑向量回归机。练习集中的特点向量和拟合出来的超平面的间隔须要小于p。异常值处罚因子C被采取。

ϵ -Support Vector Regression. The distance between feature vectors from the training set and the fitting hyper-plane must be less than p. For outliers the penalty multiplier

C is used.  

NU_SVR ν - 类支撑向量回归机。 替换了 p。

ν -Support Vector Regression. ν  is used instead of p. 

其他参数设置

setDegree (double val)   degree:内核函数(POLY)的参数degree。

setGamma (double val)   gamma:内核函数(POLY/ RBF/ SIGMOID)的参数。

setCoef0 (double val) coef0:内核函数(POLY/ SIGMOID)的参数coef0。

setC (double val)  SVM类型(C_SVC/ EPS_SVR/ NU_SVR)的参数C。

setNu (double val)  nu:SVM类型(NU_SVC/ ONE_CLASS/ NU_SVR)的参数 。

setP (double val)  p:SVM类型(EPS_SVR)的参数。

setClassWeights (const cv::Mat &val)

class_weights:C_SVC中的可选权重,赋给指定的类,乘以C今后变成 。所以这些权重影响不合类此外错误分类处罚项。权重越大,某一类此外误分类数据的处罚项就越大。

setTermCriteria (const cv::TermCriteria &val)      term_crit:SVM的迭代练习过程的中断前提,解决项目组受束缚二次最优题目。您可以指定的公差和/或最大迭代次数。

c、预测

float CvSVM::predict(const Mat& sample, bool returnDFVal=false ) const  

float CvSVM::predict(const CvMat* sample, bool returnDFVal=false ) const  

float CvSVM::predict(const CvMat* samples, CvMat* results) const  

sample: 须要猜测的输入样本。

samples: 须要猜测的输入样本们。

returnDFVal: 指定返回值类型。若是值是true,则是一个2类分类题目,该办法返回的决定计划函数值是边沿的符号间隔。

results: 响应的样本输出猜测的响应。

这个函数用来猜测一个新样本的响应数据(response)。在分类题目中,这个函数返回类别编号;在回归题目中,返回函数值。

输入的样本必须与传给trainData的练习样本同样大小。

若是练习中应用了varIdx参数,必然记住在predict函数中应用跟练习特点一致的特点。

d、获取支撑向量(getUncompressedSupportVectors,getSupportVector )

在opencv3.0中用 LINEAR核时 getSupportVector 得不到支撑向量 opencv3.2中引入了getUncompressedSupportVectors。


关于问题2,opencv已经将svm的多分类集成了。

一对一法(one-versus-one,简称OVO SVMs或者pairwise)。其做法是在任意两类样本之间设计一个SVM,因此k个类别的样本就需要设计k(k-1)/2个SVM。当对一个未知样本进行分类时,最后得票最多的类别即为该未知样本的类别。Libsvm中的多类分类就是根据这个方法实现的。



猜你喜欢

转载自blog.csdn.net/pengjc2001/article/details/60871621