
</pre><pre name="code" class="cpp">#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace std;
int main()
{
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);//创建一副用以显示信息的图片
//(1)创建训练数据
// 此练习中训练数据由一组已标记的二维点组成,
// 他们分别属于两个不同的类;其中一类有一个点组成1,另一类由三个点组成-1
// Data for visual representation
float labels[4] = { 1.0, -1.0, -1.0, -1.0};//设置标签,本程序是给标签做分类和线性规划
Mat labelsMat(4, 1, CV_32FC1, labels);//创建一个矩阵
//函数CvSVM::train的调用将在需要的训练数据被保存成float型的Mat对象之后。
// 因此,我们要通过上面定义的数组创建这些对象:
// Set up training data
float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);// Mat(int rows, int cols, int type, const Scalar& s);
//(2)创建SVM的参数
// 本篇指导中,我们用最简单的例子介绍了SVM理论,
// 其中训练样本可以被线性地区分为两类。但是,SVM能被用于各种问题
// (例如,数据的非线性分类问题,SVM使用一个核函数来提升样本维度等等)。
// 基于这一结论,我们在训练SVM之前必须定义一些参数。这些参数被保存在CvSVMParams类的对象中。
// Set up SVM's parameters
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
//(3)训练SVM
// 我们称这个方法为CvSVM::train来创建SVM模型。
// Train the SVM
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
//(4)使用SVM区域分类
// CvSVM::predict是通过以训练的SVM模型来分类输入样本的方法。
// 本例中为了着色由SVM预测的空间我们就使用这个方法。
// 也就是说,我们遍历一副图片,把它的像素当成笛卡尔平面的点。
// 每一个点都根据SVM的分类预测染上了颜色;如果是标记为1的类别就涂成绿色的,
// 如果是标记为 - 1的类,就涂成蓝色的。
Vec3b green(0, 255, 0), blue(255, 0, 0);
// Show the decision regions given by the SVM
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
// create a 2x4 double-precision identity matrix Mat M = (Mat_(2,4) << 1, 0, 0, 0, 1, 0, 0, 0);
Mat sampleMat = (Mat_<float>(1, 2) << j, i);//创建一个矩阵
float response = SVM.predict(sampleMat);//预测这个矩阵的标签
if (response == 1)
image.at<Vec3b>(i, j) = green;//图像在某点的赋值
else if (response == -1)
image.at<Vec3b>(i, j) = blue;
}
// Show the training data,这是自己的
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);
//(5)支持向量
// 这里我们使用很多方法来获得支持向量的信息。方法CvSVM::get_support_vector_count
// 输出该问题中支持向量的总数,CvSVM::get_support_vector可通过索引获取每一个支持向量。
// 这里,我们使用这种方法找到是支持向量的训练样本并把他们标记出来。
// Show support vectors
thickness = 2;
lineType = 8;
int c = SVM.get_support_vector_count();
cout << "支持向量的个数为--- " << c << endl;//输出的结果是 1
for (int i = 0; i < c; ++i)
{
//v得出的是一个坐标,
const float* v = SVM.get_support_vector(i);
//scalar--标量--是将图像设置成单一灰度和颜色, Scalar(128, 128, 128)是灰色
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);
}