OpenCv学习笔记--支持向量机SVM之C++的实现(1)

(一)支持向量机SVM的介绍

    1--本文尝试解决下面的问题
        如何使用OpenCv中的函数CvSVM::train()训练一个SVM分类器,以及用CvSVM::predit测试训练结果
    2--详细探究OpenCv中的CvSVM支持向量机类的各种函数和功能

(二)什么是支持向量机(SVM)

    1--支持向量机SVM---就是一个分类器,正式的定义是,一个能够将不同类样本在样本空间分割的---超平面.换
       句话说,给定一写标记(Label)好的训练样本(监督式学习),SVM算法输出一个最优化的分隔超平面
    2--如何来界定一个超平面是不是最优的呢?考虑如下面的问题:
       假设给定一些分属两类的2维点,这些点可以通过直线分割,但是可以分割这些点的分割线有多条,我们需
       要在这些分割线中找出一条---最优的分割线
    实例图片如下所示:

     3--在上面的图中,你可以很直接的观察到有多种可能的直线将样本分开,那是不是某条直线比其他直线
          更加合适呢?我们可以凭借直觉来定义一条评价直线好坏的标准:
          距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度很高,泛化性很差。因此我们的目标
     找到一条直线,离所有的样本点的距离最远
     4--因此,SVM算法的实质就是找出一个能够将某个最大化的超平面,这个值就是超平面距离所有训练样
         本的--最小距离.这个最小距离用SVM术语来说,叫做----间隔(margin)
     5--概括一下,就是---最优分割超平面---最大化训练数据的问题
    示例的图片如下所示:

OpenCv学习笔记--支持向量机SVM之C++的实现(1)_第1张图片

(三)如何计算最优超平面呢?

    具体的理论知识,请查看《机器学习》相关的数据

(四)基于OpenCv的SVM算法的C++的实现,代码如下所示:

/********************************************************************************************* 程序功能: OpenCv2.4.8之机器学习模块---(1)支持向量机SVM-----线性可分情况下的SVM 编写环境: OpenCv2.4.8+VS2010 地点时间: 陕西师范大学 2016.4.21 作者信息: 九月 **********************************************************************************************/
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>

using namespace cv;

int main()
{
    //【1】声明要创建的图像的高和宽
    int width  = 512;
    int height = 512;
    //【2】使用Matlab风格的函数zeros()创建一个8位无符号整形的三通道RGB彩色图像
    Mat image = Mat::zeros(height, width, CV_8UC3);

    //【3】设置SVM支持向量机要训练的数据
    float labels[4] = {1.0, -1.0, -1.0, -1.0};
    Mat labelsMat(3, 1, CV_32FC1, labels);

    float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
    Mat trainingDataMat(3, 2, CV_32FC1, trainingData);

    //【4】设置SVM的参数
    CvSVMParams params;
    params.svm_type    = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

    //【5】训练SVM
    CvSVM SVM;
    SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

    Vec3b green(0,255,0), blue (255,0,0);
   //【6】显示由SVM给出的决策区域
    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 == -1) 
                 image.at<Vec3b>(j, i)  = blue;
        }


    //【7】显示训练数据
    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);


    //【8】显示支持向量
    thickness = 2;
    lineType  = 8;
    int c     = SVM.get_support_vector_count();

    for (int i = 0; i < c; ++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);
    }

    //【9】保存这张照片
    imwrite("result.png", image);       
    //【10】将SVM分类的结果显示出来
    imshow("SVM分类的结果", image);
    waitKey(0);

}
    程序运行的结果如下所示:

OpenCv学习笔记--支持向量机SVM之C++的实现(1)_第2张图片

你可能感兴趣的:(OpenCv学习笔记--支持向量机SVM之C++的实现(1))