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感觉依旧云里雾里,这远远不够,有些问题得自己进一步学习之后再回来补充。