700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > OpenCV之机器学习:利用svm(支持向量机)分类

OpenCV之机器学习:利用svm(支持向量机)分类

时间:2022-04-17 00:19:39

相关推荐

OpenCV之机器学习:利用svm(支持向量机)分类

文章目录

代码一、SVM创建1.setType()2.setKernel()3.设置核参数4.setTermCriteria() 二、SVM训练1.Ptr< TrainData>类型2.训练函数trainAuto() 三、SVM预测四、存储和载入SVM文件1.存储2.载入3.获得向量(1)支持向量(2)未压缩支持向量 参考:

代码

过程:

创建SVM,之后设置参数训练分类器:创建训练数据矩阵和响应数据矩阵预测:用图形化显示决策区域和显示训练数据

#include <iostream>#include <opencv2/opencv.hpp>using namespace cv;using namespace cv::ml;int main(){// 创建分类器并设置参数Ptr<SVM> model =SVM::create();model->setType(SVM::C_SVC); model->setKernel(SVM::LINEAR); //核函数//设置训练数据矩阵float trainingData[10][2] = {{501, 150 }, {255, 10 }, {501, 255 }, {10, 501 }, {25, 80 },{150, 300 }, {77, 200 } , {300,300 },{45, 250 } , {200, 200 } };Mat trainingDataMat(10, 2, CV_32FC1, trainingData);//设置响应数据矩阵int labels[10] = {1, -1, 1, 1,-1,1,-1,1,-1,-1 };Mat labelsMat(10, 1, CV_32SC1, labels);//创建TrainData实例Ptr<TrainData> tData=TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);//每个训练数据是训练数据矩阵的行,所以是ROW_SAMPLE// 训练分类器model->trainAuto(tData);//创建窗口可视化Mat image = Mat::zeros(512, 512, CV_8UC3);/*显示决策区域*/Vec3b red(0, 0, 255), blue(255, 0, 0);for (int i = 0; i < image.rows; i++){for (int j = 0; j < image.cols; j++){//生成测试数据Mat sampleMat = (Mat_<float>(1, 2) << j, i); //进行预测,返回1或-1,和响应数据的值对应float response = model->predict(sampleMat); if (response == 1)image.at<Vec3b>(i, j) = red;else if (response == -1)image.at<Vec3b>(i, j) = blue;}}/*显示训练数据*/Scalar c1 = Scalar::all(0); //标记为1的显示成黑点Scalar c2 = Scalar::all(255); //标记成-1的显示成白点//绘图时,先宽后高,对应先列后行for (int i = 0; i < trainingDataMat.rows; i++){const float* v = trainingDataMat.ptr<float>(i); //取出每行的头指针Point pt = Point((int)v[0], (int)v[1]);if (labels[i] == 1)circle(image, pt, 5, c1, -1, 8); elsecircle(image, pt, 5, c2, -1, 8);}imshow("SVM Simple Example", image); waitKey(0);return 0;}

显示训练数据要放在显示决策区域之后,不是因为SVM的过程问题,而是显示图像的问题。因为显示决策区域是对整个图像操作,所以如果显示训练数据在之前就会被覆盖。

一、SVM创建

//创建一个分类器Ptr<SVM> svm = SVM::create();//设置svm类型svm->setType(SVM::C_SVC);//设置核函数svm->setKernel(SVM::POLY);svm->setDegree(0.5);svm->setGamma(1);//核函数中的coef0设置(针对多项式/sigmoid核函数)((默认0)svm->setCoef0(1);svm->setC(C);svm->setNu(0.5);svm->setP(0);svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 1000, 0.01));

1.setType()

设置svm类型:

SVM::C_SVC

C类支撑向量分类机。

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

SVM::NU_SVC

ν \nu ν类支撑向量分类机。

m类似然不完全分类的分类器。 ν \nu ν参数为庖代C(其值在区间[0,1]中, ν \nu ν越大,决定计划鸿沟越腻滑)。

SVM::ONE_CLASS

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

SVM::EPS_SVR

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

SVM::NU_SVR

ν \nu ν类支撑向量回归机。 ν \nu ν庖代了 p。

2.setKernel()

设置内核:

SVM::LINEAR :

线性内核,没有任何向映射至高维空间,线性区分(或回归)在原始特点空间中被完成,这是最快的选择。

SVM::POLY :

多项式内核:

SVM::RBF :

基于径向的函数,对于大多半景象都是一个较好的选择

SVM::SIGMOID :

Sigmoid函数内核:

3.设置核参数

setDegree()

内核函数(POLY)的参数degree。

setGamma()

内核函数(POLY/ RBF/ SIGMOID)的参数 γ \gamma γ

setCoef0()

内核函数(POLY/ SIGMOID)的参数coef0

setC()

SVM类型(C_SVC/ EPS_SVR/ NU_SVR)的参数C

setNu()

SVM类型(NU_SVC/ ONE_CLASS/ NU_SVR)的参数 ν \nu ν

setP()

SVM类型(EPS_SVR)的参数 ϵ \epsilon ϵ。

4.setTermCriteria()

SVM的迭代练习过程的中断前提,解决项目组受束缚二次最优题目。您可以指定的公差和/或最大迭代次数。

二、SVM训练

步骤:

先创建TrainData实例再将TrainData传入train()函数

1.Ptr< TrainData>类型

static Ptr<TrainData> cv::ml::TrainData::create(InputArray samples,int layout,InputArray responses,InputArray varIdx = noArray(),InputArray sampleIdx = noArray(),InputArray sampleWeights = noArray(),InputArray varType = noArray() )

参数:

samples

训练数据。

必须是CV_32Flayout

就是SampleTypes:

ROW_SAMPLE

每个训练样本是训练数据矩阵的行

COL_SAMPLE

每个训练样本是训练数据矩阵的列

responses

响应数据。

如果响应是标量,则应将它们存储为单行或单列。(在前一种情况下,响应在默认情况下被视为有序;在后一种情况下无条件)

矩阵应该具有类型CV_32F或CV_32S

如:

//设置训练数据float trainingData[10][2] = {{501, 150 }, {255, 10 }, {501, 255 }, {10, 501 }, {25, 80 },{150, 300 }, {77, 200 } , {300,300 },{45, 250 } , {200, 200 } };Mat trainingDataMat(10, 2, CV_32FC1, trainingData);//设置响应数据int labels[10] = {1, -1, 1, 1,-1,1,-1,1,-1,-1 };Mat labelsMat(10, 1, CV_32SC1, labels);//创建TrainData实例Ptr<TrainData> tData=TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);//每个训练数据是训练数据矩阵的行,所以是ROW_SAMPLE

2.训练函数trainAuto()

参数是Ptr<TrainData>

virtual bool cv::ml::SVM::trainAuto(const Ptr< TrainData > & data,int kFold = 10,ParamGrid Cgrid = getDefaultGrid(C),ParamGrid gammaGrid = getDefaultGrid(GAMMA),ParamGrid pGrid = getDefaultGrid(P),ParamGrid nuGrid = getDefaultGrid(NU),ParamGrid coeffGrid = getDefaultGrid(COEF),ParamGrid degreeGrid = getDefaultGrid(DEGREE),bool balanced = false )

data:

Ptr<TrainData>实例

kFold

交叉验证参数。训练集分为kFold子集。一个子集用于测试模型,其他子集用于训练集。因此,SVM算法执行kFold次。

balanced

如果为真且问题是2类分类,则该方法创建更平衡的交叉验证子集,即子集中类之间的比例接近于整个训练数据集中的该比例。

如:

model->trainAuto(tData);

参数是Ptr<TrainData>的拆分形式

bool cv::ml::SVM::trainAuto(InputArray samples,int layout,InputArray responses,int kFold = 10,Ptr< ParamGrid > Cgrid = SVM::getDefaultGridPtr(SVM::C),Ptr< ParamGrid > gammaGrid = SVM::getDefaultGridPtr(SVM::GAMMA),Ptr< ParamGrid > pGrid = SVM::getDefaultGridPtr(SVM::P),Ptr< ParamGrid > nuGrid = SVM::getDefaultGridPtr(SVM::NU),Ptr< ParamGrid > coeffGrid = SVM::getDefaultGridPtr(SVM::COEF),Ptr< ParamGrid > degreeGrid = SVM::getDefaultGridPtr(SVM::DEGREE),bool balanced = false )

如:

model->train(trainingDataMat,ROW_SAMPLE,labelsMat);

三、SVM预测

使用StatModel下的predict()

virtual float cv::ml::StatModel::predict(InputArray samples,OutputArray results = noArray(),int flags = 0 )const

参数:

samples

猜测的输入样本。

float浮点型矩阵,必须与训练样本同样大小。

results:

可选的结果输出矩阵。

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

这个函数用来猜测一个新样本的响应数据(response)。

在分类题目中,这个函数返回类别编号;在回归题目中,返回函数值。

flags:

可选标志,取决于模型。

返回值:

float类型,返回1或-1(这就是你的响应数据的值)。

四、存储和载入SVM文件

1.存储

原型:

virtual void cv::Algorithm::save(const String & filename)const

文件格式的后缀是.svm

比如:

string path="/home/doctor/code/svmfile.svm";model->save(path);

#include <iostream>#include <opencv2/opencv.hpp>#include <string>using namespace std;using namespace cv;using namespace cv::ml;int main(){// 创建分类器并设置参数Ptr<SVM> model =SVM::create();model->setType(SVM::C_SVC); model->setKernel(SVM::LINEAR); //核函数//设置训练数据矩阵float trainingData[10][2] = {{501, 150 }, {255, 10 }, {501, 255 }, {10, 501 }, {25, 80 },{150, 300 }, {77, 200 } , {300,300 },{45, 250 } , {200, 200 } };Mat trainingDataMat(10, 2, CV_32FC1, trainingData);//设置响应数据矩阵int labels[10] = {1, -1, 1, 1,-1,1,-1,1,-1,-1 };Mat labelsMat(10, 1, CV_32SC1, labels);//创建TrainData实例Ptr<TrainData> tData=TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);//每个训练数据是训练数据矩阵的行,所以是ROW_SAMPLE// 训练分类器model->trainAuto(tData);//创建窗口可视化Mat image = Mat::zeros(512, 512, CV_8UC3);/*显示决策区域*/Vec3b red(0, 0, 255), blue(255, 0, 0);for (int i = 0; i < image.rows; i++){for (int j = 0; j < image.cols; j++){//生成测试数据Mat sampleMat = (Mat_<float>(1, 2) << j, i); //进行预测,返回1或-1,和响应数据的值对应float response = model->predict(sampleMat); if (response == 1)image.at<Vec3b>(i, j) = red;else if (response == -1)image.at<Vec3b>(i, j) = blue;}}/*显示训练数据*/Scalar c1 = Scalar::all(0); //标记为1的显示成黑点Scalar c2 = Scalar::all(255); //标记成-1的显示成白点//绘图时,先宽后高,对应先列后行for (int i = 0; i < trainingDataMat.rows; i++){const float* v = trainingDataMat.ptr<float>(i); //取出每行的头指针Point pt = Point((int)v[0], (int)v[1]);if (labels[i] == 1)circle(image, pt, 5, c1, -1, 8); elsecircle(image, pt, 5, c2, -1, 8);}string path="/home/doctor/code/svmfile.svm";model->save(path);imshow("SVM Simple Example", image); waitKey(0);return 0;}

2.载入

原型:

static Ptr<SVM> cv::ml::SVM::load(const String & filepath)

比如:

string path="/home/doctor/code/svmfile.svm";Ptr<SVM> model=SVM::load(path);

3.获得向量

(1)支持向量

原型:

virtual Mat cv::ml::SVM::getSupportVectors() const

该方法将所有支持向量作为浮点矩阵返回,其中支持向量存储为矩阵行。

Mat trainingDataMat=model->getSupportVectors();

(2)未压缩支持向量

Mat cv :: ml :: SVM :: getUncompressedSupportVectors()const

检索线性SVM的所有未压缩支持向量。

该方法返回线性SVM的所有未压缩支持向量,其中用于预测的压缩支持向量来自。

它们以浮点矩阵返回,其中支持向量存储为矩阵行。

#include <iostream>#include <opencv2/opencv.hpp>#include <string>using namespace std;using namespace cv;using namespace cv::ml;int main(){string path="/home/doctor/code/svmfile.svm";Ptr<SVM> model=SVM::load(path);Mat trainingDataMat=model->getUncompressedSupportVectors();cout<<trainingDataMat.rows<<' ' <<trainingDataMat.cols<<endl;//设置响应数据矩阵int labels[10] = {1, -1, 1, 1,-1,1,-1,1,-1,-1 };//创建窗口可视化Mat image = Mat::zeros(512, 512, CV_8UC3);/*显示决策区域*/Vec3b red(0, 0, 255), blue(255, 0, 0);for (int i = 0; i < image.rows; i++){for (int j = 0; j < image.cols; j++){//生成测试数据Mat sampleMat = (Mat_<float>(1, 2) << j, i); //进行预测,返回1或-1,和响应数据的值对应float response = model->predict(sampleMat); if (response == 1)image.at<Vec3b>(i, j) = red;else if (response == -1)image.at<Vec3b>(i, j) = blue;}}/*显示训练数据*/Scalar c1 = Scalar::all(0); //标记为1的显示成黑点Scalar c2 = Scalar::all(255); //标记成-1的显示成白点//绘图时,先宽后高,对应先列后行for (int i = 0; i < trainingDataMat.rows; i++){const float* v = trainingDataMat.ptr<float>(i); //取出每行的头指针Point pt = Point((int)v[0], (int)v[1]);if (labels[i] == 1)circle(image, pt, 5, c1, -1, 8); elsecircle(image, pt, 5, c2, -1, 8);}imshow("SVM Simple Example", image); waitKey(0);return 0;}

参考:

OPENCV中SVM参数解析–学习1

在opencv3中实现机器学习之:利用svm(支持向量机)分类

官方文档:

cv::ml::SVM Class Reference

/3.4.6/d5/d33/structcv_1_1HOGDescriptor.html

官方例子:

/3.4.6/d0/df8/samples_2cpp_2train_HOG_8cpp-example.html#a4

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。