支持向量机的原理这里也就不阐述了,我也不太会。我大概的理解就是和KNN一样是个分类器,可以想象以下,两类样本点可以用很多条线分开,但是那一条是最优呢?支持向量机中利用支持向量(可能是样本中的几个点,具体怎么取这个向量不需要我们考虑),然后计算支持向量到分割线的距离,距离最大的那条分界线那就是最优分类了。所以SVM中用的是间隔最大化思想。
支持向量机只有一成为一个很强的算法,是因为它能够适应各种情况,也因如此参数设置比KNN要多很多。OpenCV中给出接口:
SVM中有不同的内核,不同的内核计算公式中有不同的参数,所以要根据所选内核来调整参数;
一般用linear线性内核,poly多项式内核,rbf 基于径向的函数
enum KernelTypes {
/** Returned by SVM::getKernelType in case when custom kernel has been set */
CUSTOM=-1,
/** Linear kernel. No mapping is done, linear discrimination (or regression) is
done in the original feature space. It is the fastest option. \f$K(x_i, x_j) = x_i^T x_j\f$. */
LINEAR=0,
/** Polynomial kernel:
\f$K(x_i, x_j) = (\gamma x_i^T x_j + coef0)^{degree}, \gamma > 0\f$. */
POLY=1,
/** Radial basis function (RBF), a good choice in most cases.
\f$K(x_i, x_j) = e^{-\gamma ||x_i - x_j||^2}, \gamma > 0\f$. */
RBF=2,
/** Sigmoid kernel: \f$K(x_i, x_j) = \tanh(\gamma x_i^T x_j + coef0)\f$. */
SIGMOID=3,
/** Exponential Chi2 kernel, similar to the RBF kernel:
\f$K(x_i, x_j) = e^{-\gamma \chi^2(x_i,x_j)}, \chi^2(x_i,x_j) = (x_i-x_j)^2/(x_i+x_j), \gamma > 0\f$. */
CHI2=4,
/** Histogram intersection kernel. A fast kernel. \f$K(x_i, x_j) = min(x_i,x_j)\f$. */
INTER=5
};
对应参数:
degree:内核函数(POLY)的参数degree。
gamma:内核函数(POLY/ RBF/ SIGMOID)的参数。
coef0:内核函数(POLY/ SIGMOID)的参数coef0。
C_SVC是默认类型:C类支撑向量分类机。 n类分组 (n≥2),容许用异常值处罚因子C进行不完全分类。
enum Types {
C_SVC=100,
NU_SVC=101,
ONE_CLASS=102,
EPS_SVR=103,
NU_SVR=104
};
对应参数:
Cvalue:SVM类型(C_SVC/ EPS_SVR/ NU_SVR)的参数C。
nu:SVM类型(NU_SVC/ ONE_CLASS/ NU_SVR)的参数 。
p:SVM类型(EPS_SVR)的参数。
class_weights:C_SVC中的可选权重,赋给指定的类,乘以C今后变成 。所以这些权重影响不合类此外错误分类处罚项。权重越大,某一类此外误分类数据的处罚项就越大。
term_crit:SVM的迭代练习过程的中断前提,解决项目组受束缚二次最优题目。您可以指定的公差和/或最大迭代次数。
// SVM.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include
#include
using namespace cv;
using namespace cv::ml;
int train_sample_nums = 200;
int main()
{
/******************数据集制作***************************/
Mat trainData(train_sample_nums, 2, CV_32FC1);
Mat trainClassess(train_sample_nums, 1, CV_32SC1); //注意标签的格式,有符号
//创建可视化图像
Mat img(500, 500, CV_8UC3, Scalar::all(0));
//样本点
Mat sample(1, 2, CV_32FC1);
Mat trainData1, trainData2, trainClasses1, trainClasses2;
RNG rng = RNG(-1);
//生成均值为(200,200),方差为(40,40)的随机数据
trainData1 = trainData.rowRange(0, train_sample_nums / 2);
rng.fill(trainData1, CV_RAND_NORMAL, Scalar(100, 100), Scalar(40, 40));
trainData2 = trainData.rowRange(train_sample_nums / 2, train_sample_nums);
rng.fill(trainData2, CV_RAND_NORMAL, Scalar(300, 300), Scalar(40, 40));
//trainClasses1和trainClassess的前100行绑定
trainClasses1 = trainClassess.rowRange(0, train_sample_nums / 2);
trainClasses1 = Scalar::all(1);
trainClasses2 = trainClassess.rowRange(train_sample_nums / 2, train_sample_nums);
trainClasses2 = Scalar::all(-1);
/*****************训练********************/
cv::Ptr svm = cv::ml::SVM::create();
svm->setType(cv::ml::SVM::C_SVC);
svm->setC(1.0);
svm->setKernel(cv::ml::SVM::POLY);
svm->setGamma(1.0);
svm->setDegree(2.0);
svm->setCoef0(0.0);
svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 500, 1e-6));// cv::ml::SVM::setTermCriteria(CV_TERMCRIT_ITER, 500, 1e-6);
cv::Ptr TrainData = TrainData::create(trainData, SampleTypes::ROW_SAMPLE, trainClassess);
//svm->train(trainData, cv::ml::ROW_SAMPLE, trainClassess);
svm->train(TrainData);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
Mat sampleMat = (Mat_(1, 2) << i, j);
float response = svm->predict(sampleMat);
if (response == 1)
{
img.at(i, j) = Vec3b(0, 160, 0);
}
else if (response == -1)
{
img.at(i, j) = Vec3b(0, 0, 160);
}
}
}
for (int i = 0; i < train_sample_nums / 2; i++)
{
Point pt;
pt.x = round(trainData1.at(i, 0));
pt.y = round(trainData1.at(i, 1));
circle(img, pt, 1, Scalar(0, 255, 255));
pt.x = round(trainData2.at(i, 0));
pt.y = round(trainData2.at(i, 1));
circle(img, pt, 1, Scalar(255, 255, 0));
}
int thickness = 1;
int lineType = 8;
Mat image(img);
Mat sv = svm->getSupportVectors();
for (int i = 0; i < sv.rows; i++)
{
const float* v = sv.ptr(i);
circle(image, cv::Point((int)v[0], (int)v[1]), 6, Scalar(255, 0, 0), thickness, lineType);
}
imshow("img", img);
imshow("image", image);
waitKey(0);
}
SVM图像分割:待填坑