我的OpenCV学习笔记(六):使用支持向量机(SVM)
来源:互联网 发布:apache php mysql搭建 编辑:程序博客网 时间:2024/05/11 18:54
SVM是2000年左右提出的一种新的分类方法,着重解决了小样本分类问题。具体原理可以参看模式识别的书籍。OpenCV中的SVM的实现也是基于大名鼎鼎的SVM 库:http://www.csie.ntu.edu.tw/~cjlin。OpenCV教程中有两个例子,一个是线性可分的,一个是线性不可分的,我对他们做了详尽的注释:
先看线性可分时:
#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/ml/ml.hpp>using namespace cv;int main(){ // Data for visual representation int width = 512, height = 512; Mat image = Mat::zeros(height, width, CV_8UC3); // Set up training data float labels[5] = {1.0, -1.0, -1.0, -1.0,1.0}; Mat labelsMat(5, 1, CV_32FC1, labels);float trainingData[5][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501},{501,128} }; Mat trainingDataMat(5, 2, CV_32FC1, trainingData); //设置支持向量机的参数 CvSVMParams params; params.svm_type = CvSVM::C_SVC;//SVM类型:使用C支持向量机 params.kernel_type = CvSVM::LINEAR;//核函数类型:线性 params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);//终止准则函数:当迭代次数达到最大值时终止 //训练SVM//建立一个SVM类的实例 CvSVM SVM;//训练模型,参数为:输入数据、响应、XX、XX、参数(前面设置过) SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); Vec3b green(0,255,0), 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) << i,j);//predict是用来预测的,参数为:样本、返回值类型(如果值为ture而且是一个2类问题则返回判决函数值,否则返回类标签)、 float response = SVM.predict(sampleMat); if (response == 1) image.at<Vec3b>(j, i) = green; else if (response == -1) image.at<Vec3b>(j, i) = blue; } //画出训练数据 int thickness = -1; int lineType = 8; circle( image, Point(501, 10), 5, Scalar( 0, 0, 0), thickness, lineType);//画圆 circle( image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType); circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType); circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness, lineType);circle(image, Point( 501, 128), 5, Scalar(0, 0, 0), thickness, lineType); //显示支持向量 thickness = 2; lineType = 8;//获取支持向量的个数 int c = SVM.get_support_vector_count(); for (int i = 0; i < c; ++i) { //获取第i个支持向量const float* v = SVM.get_support_vector(i);//支持向量用到的样本点,用灰色进行标注 circle( image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness, lineType); } imwrite("result.png", image); // save the image imshow("SVM Simple Example", image); // show it to the user waitKey(0);}
线性不可分时由于样本较多,训练的时间比较长:
#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/ml/ml.hpp>#include "time.h"using namespace cv;using namespace std;//程序说明://一共两个样本集每个样本集有100个样本,其中90个是线性可分的,10个线型不可分//这200个样本数据储存在trainData内:trainData是一个200行2列的矩阵,其中第一列储存样本的X值,第二列储存的是样本的Y值//每一列的前90个元素是第一类的线性可分部分,后90个元素是第二类的线性可分部分,中间的20个元素是线性不可分部分//第一类样本的X值分布在整幅图像的[0,0.4]范围内,第二类样本的X值分布在整幅图像的[0.6,1]范围内,中间的[0.4,0.6]是线性不可分的部分;这三部分的Y值都在整幅图像的高度内自由分布//每个样本集的数量#define NTRAINING_SAMPLES 100//其中的线性部分#define FRAC_LINEAR_SEP 0.9fint main(){//定义显示结果的图像//图像的宽度、高度const int WIDTH = 512,HEIGHT = 512;Mat image = Mat::zeros(HEIGHT,WIDTH,CV_8UC3);//************第一步:设定训练数据***********//************1.设定数据结构****************//承载训练数据的结构Mat trainData(2*NTRAINING_SAMPLES,2,CV_32FC1);//承载这些数据分类的结构Mat labels(2*NTRAINING_SAMPLES,1,CV_32FC1);//设定随机数种子RNG rng(100);//设定线性可分部分的数据量int nLinearSamples = (int) (NTRAINING_SAMPLES*FRAC_LINEAR_SEP);//**************2.设定第一类中的数据*********//从整个数据集中取出前[0,89]行//注:*Range的范围是[a,b)Mat trainClass = trainData.rowRange(0,nLinearSamples);//取出第一列Mat c = trainClass.colRange(0,1);//随机生成X的值:[0,0.4*WIDTH]rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(0.4*WIDTH));//取出第二列c = trainClass.colRange(1,2);//随机生成Y的值rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));//**************2.设定第二类的数据*************//从整个数据中取出[110,199]行trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples,2*NTRAINING_SAMPLES);//取出第一列c = trainClass.colRange(0,1);//随机生成X的值[0.6*WIDTH,WIDTH]rng.fill(c,RNG::UNIFORM,Scalar(0.6*WIDTH),Scalar(WIDTH));//取出第二列c = trainClass.colRange(1,2);//随机生成Y的值rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));//***************3.设定线性不可分的数据***********//取出[90,109]行trainClass = trainData.rowRange(nLinearSamples,2*NTRAINING_SAMPLES-nLinearSamples);//取出第一列c = trainClass.colRange(0,1);//随机生成X的值[0.4*WIDTH,0.6*WIDTH]rng.fill(c,RNG::UNIFORM,Scalar(0.4*WIDTH),Scalar(0.6*WIDTH));//取出第二列c = trainClass.colRange(1,2);//随机生成Y的值rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));//***************4.为所有数据设置标签**********//前100个数据设为第一类labels.rowRange(0,NTRAINING_SAMPLES).setTo(1);//后100个数据设为第二类labels.rowRange(NTRAINING_SAMPLES,2*NTRAINING_SAMPLES).setTo(2);//**************第二步:设置SVM参数***********CvSVMParams params;//SVM类型: C-Support Vector Classificationparams.svm_type= SVM::C_SVC;params.C= 0.1;//和函数类型:Linear kernelparams.kernel_type = SVM::LINEAR;//终止准则:当迭代次数到达最大值后终止params.term_crit= TermCriteria(CV_TERMCRIT_ITER,(int) 1e7,1e-6);//**************第三步:训练SVM***********cout<<"开始训练过程"<<endl;//开始计时clock_t start,finish;double duration;start = clock();//*************1.建立一个SVM实例**********CvSVM svm;//*************2.调用训练函数*************svm.train(trainData,labels,Mat(),Mat(),params);//结束计时finish = clock();duration = (double)(finish-start) / CLOCKS_PER_SEC;cout<<"训练过程结束,共耗时:"<<duration<<"秒"<<endl;//************第四步:显示判决域************//第一类用绿色;第二类用蓝色Vec3b green(0,100,0),blue(100,0,0);for(int i = 0; i < image.rows; ++i){for(int j = 0; j < image.cols; ++j){Mat sampleMat = (Mat_<float>(1,2)<<i,j);float response = svm.predict(sampleMat);if (response == 1){image.at<Vec3b>(j,i) = green;}else if (response == 2){image.at<Vec3b>(j,i) = blue;}}}//************第五步:显示训练数据************//红色//负数会导致画出的图型是实心的int thick = -1;int lineType = 8;float px,py;//************1.第一类*************for(int i = 0; i < NTRAINING_SAMPLES; ++i){px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(image,Point((int)px,(int)py),3,Scalar(0,255,0));}//***********2.第二类****************for(int i = NTRAINING_SAMPLES; i < 2*NTRAINING_SAMPLES; ++i){px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(image,Point((int)px,(int)py),3,Scalar(255,0,0));}//***********第六步:显示支持向量*************thick = 2;lineType = 8;//获取支持向量的个数int x = svm.get_support_vector_count();for(int i = 0; i < x; ++i){const float* v = svm.get_support_vector(i);circle(image,Point((int)v[0],(int)v[1]),6,Scalar(128,128,128),thick,lineType);}imshow("分类结果",image);waitKey(0);return 0;}
其实我对SVM的理解也只是照猫画虎,当训练数据是高维情况时,也完全不知所措,以后要是需要在这方面有深入研究的话,在仔细考虑吧!
- 我的OpenCV学习笔记(六):使用支持向量机(SVM)
- 我的OpenCV学习笔记(六):使用支持向量机(SVM)
- SVM(支持向量机)学习笔记
- 支持向量机(SVM)学习笔记
- Andrew Ng机器学习入门学习笔记(六)之支持向量机(SVM)
- 机器学习(六)支持向量机svm初级篇
- 机器学习(六)支持向量机svm初级篇
- 学习笔记——支持向量机svm(1)最简单的支持向量机
- OpenCV学习之路-支持向量机SVM(一)
- OpenCV学习笔记(三):解释支持向量机(SVM)Emamples
- 深度学习*学习笔记----支持向量机SVM(3)
- opencv笔记(12):支持向量机-SVM
- 机器学习笔记08:支持向量机(一)(SVM)
- 机器学习笔记(五) 支持向量机SVM
- 【opencv机器学习】支持向量机SVM的程序
- OpenCv学习笔记--支持向量机SVM之C++的实现(1)
- 机器学习---支持向量机(SVM)
- 机器学习:支持向量机(SVM)
- 将java project打包成jar包,web project 打包成war包的几种演示
- Android调试技术汇总
- 纪念邮票问题
- 揭开正则表达式的神秘面纱(看一遍就完全搞定的正则表达式教程)
- 第十周任务一
- 我的OpenCV学习笔记(六):使用支持向量机(SVM)
- POJ:2752Seek the Name, Seek the Fame
- 求数组中和最大的子数组(数组中和最大的子串)
- 判断是否为IP地址
- 2.jquery操作select,checkbox,radio
- 关于vs2010的那点事
- 有规则的txt文件拆分
- wireshark的抓包文件格式-pcap文件格式学习
- java的四种文件写入方法比较