学习SVM (一). 官方例程的学习与入门

SVM是什么?

https://www.zhihu.com/question/21094489     支持向量机讲解(通俗)有视频


入门资料:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms    SVM的官方翻译例程(只不过是2版本的,可以对照着看下面的讲解)


源代码(自己加了些注释)

/*
   SVM小试
*/
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
#include <iostream>

using namespace std;
using namespace cv;
using namespace cv::ml;

int main()
{
	 
	Mat image = Mat::zeros(512, 512, CV_8UC3);  //用于分类结果的可视化
   
	//设置分类的数据 
	int labels[4] = { 1,-1,-1,-1 };
	float sample[4][2] = { { 501, 10 },{ 255, 10 },{ 501, 255 },{ 10, 501 } };
	Mat labelsMat(4, 1, CV_32SC1,labels);     //将数组转换为矩阵
	Mat sampleMat(4, 2, CV_32FC1,sample);     

	//设置svm参数
	Ptr<SVM> svm = SVM::create();       //创建一个分类器   svm是一个指针
	svm->setType(SVM::C_SVC);
	svm->setKernel(SVM::LINEAR);
	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
	svm->train(sampleMat, ROW_SAMPLE, labelsMat);     //训练数据  建立svm模型
	
	//展示划分后的区域
	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  dataMat = (Mat_<float>(1, 2) << j, i);       //  <<运算符发生重载 先行后列

			float  response = svm->predict(dataMat);

			if (response == 1)
			{
				image.at<Vec3b>(i, j) = green;    //参数为先行后列
			}
			else if (response == -1)
			{
				image.at<Vec3b>(i, j) = blue;
			}
		}
	}

	//显示样本点(之前被训练的数据)
	int thickness = -1;
	int lineType = 8;
	circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType); //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);

	//显示支持的向量
	thickness = 2;
	lineType = 8;
	Mat sv = svm->getUncompressedSupportVectors();

	for (int i = 0; i < sv.rows; i++)
	{
		const float  *v = sv.ptr<float>(i);                   //返回元素第i行的指针
		circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);    // 用灰色表示支持的向量
	}

	imwrite("image.jpg", image);        // save the image

	imshow("效果图", image);
	
	waitKey();

	return 0;

}

效果图:



分析

很多官方的文档都已经讲解了,不再啰嗦。写些官方文档没有的和自己当初的困惑(有错误希望大家提出)

(1)将样本和标签转换为矩阵时,矩阵的类型是有限制的。具体可看此博客的源代码注意事项

https://blog.csdn.net/wfh2015/article/details/51163890      

(2) train的第二个参数的含义

svm->train(sampleMat, ROW_SAMPLE, labelsMat);     //训练数据  建立svm模型
/** @brief Sample types */
enum SampleTypes
{
    ROW_SAMPLE = 0, //!< each training sample is a row of samples
    COL_SAMPLE = 1  //!< each training sample occupies a column of samples
};

(3)ptr智能指针的使用

const float *v = sv.ptr<float>(i); //返回元素第i行的指针

https://blog.csdn.net/github_35160620/article/details/51708659      Mat数据类型指针ptr的使用

(4) 支持的向量是什么意思?


注:对于SVM感觉依旧云里雾里,这远远不够,有些问题得自己进一步学习之后再回来补充。

猜你喜欢

转载自blog.csdn.net/xv1356027897/article/details/80197693
今日推荐