【opencv】支持向量机CvSVM分类

有关于SVM的理论可以参考opencv_tutorials.pdf
译文可以参考博客:
http://blog.csdn.net/dwb1015/article/details/12841305

本文通过svm进行多类分类
源码如下:

//编程环境:VS2012 + Opencv2.4.9
#include <fstream>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;
#define COUNT 21 //读入的点个数

int main()
{
    //从文件载入数据
    float data[COUNT][2];   
    ifstream fin1("data.txt");  
    for(int i=0;i<COUNT;i++)
    {
        fin1>>data[i][0];   
        fin1>>data[i][1];
    }
    fin1.close();   
    //显示读入的数据
    for(int i=0;i<COUNT;i++)    
    {
        cout<<data[i][0]<<" ";
        cout<<data[i][1]<<" "<<endl;
    }

    float label[COUNT][1];  
    ifstream fin2("label.txt"); 
    for(int i=0;i<COUNT;i++)
    {
        fin2>>label[i][0];  
    }
    fin2.close();   
    //显示读入的数据
    for(int i=0;i<COUNT;i++)    
    {
        cout<<label[i][0]<<" "<<endl;
    }

    Mat trainData(COUNT, 2, CV_32FC1, data);
    Mat trainLabel(COUNT, 1, CV_32FC1, label);

    cout<<"trainData"<<trainData<<endl;
    cout<<"trainLabel"<<trainLabel<<endl;

    CvSVM svm;
    CvSVMParams param;

    param.svm_type  = CvSVM::C_SVC;     //n(n>2)的分类器,其中参数C是异常惩罚因子,可以进行不完全分类
    //param.svm_type  = CvSVM::NU_SVC;    //n(n>2)类似不完全分类的分类器,参数nu(nu属于[0,1]),取代了C_SVC类型的异常惩罚因子C;
    //param.svm_type  = CvSVM::ONE_CLASS;  //单分类器,用一个分界线对特征空间进行分割。
    param.kernel_type = CvSVM::LINEAR;  //线性核函数,此核函数在分类是速度最快,分类将在原始空间中完成;
    //param.kernel_type = CvSVM::POLY;    //多项式核
    //param.kernel_type = CvSVM::RBF;     //径向基核,对于大部分情况都是选择此类型
    //param.kernel_type = CvSVM::SIGMOID;  //sigmoid核函数
    param.term_crit  = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); //SVM迭代终止条件,CV_TERMCRIT_ITER为终止条件类型,100为最大迭代次数,1e-6为结果的准确率

    //训练SVM
    svm.train(trainData, trainLabel, Mat(), Mat(), param);

    Mat image = Mat::zeros(500, 500, CV_8UC3);  
    Vec3b green(0,255,0), blue(255,0,0), red(0,0,255),gray(125,125,125);

    for (int i = 0; i < image.cols; i++)
    {
        for (int j = 0; j < image.rows; j++)
        {
            Mat sampleMat = (Mat_<float>(1,2) << i,j); 
            float response = svm.predict(sampleMat);

            if(response == 3)
                image.at<Vec3b>(j,i) = green;
            if(response == 2)
                image.at<Vec3b>(j,i) = gray;
            if(response == 1)
                image.at<Vec3b>(j,i) = blue;
            if(response == 0)
                image.at<Vec3b>(j,i) = red;
        }
    }

    for (int i = 0; i < COUNT; i++)
    {
        Point p(data[i][0],data[i][1]);
        if (label[i][0]==0)
            circle( image, p, 3, Scalar(255, 255, 0), -1, 8);
        if (label[i][0]==1)
            circle( image, p, 3, Scalar(255, 0, 255), -1, 8);
        if (label[i][0]==2)
            circle( image, p, 3, Scalar(0, 255, 255), -1, 8);
        if (label[i][0]==3)
            circle( image, p, 3, Scalar(0, 0, 0), -1, 8);
    }

    imshow("result",image);
    imwrite("output.jpg",image);
    waitKey(0);

    return 0;
}

label.txt:

0
1
0
2
0
0
0
1
0
3
3
1
0
1
1
2
2
2
0
0
2

data.txt:

100 250
250 450
150 160
300 420
210 120
90 20
70 60
330 210
80 200
400 120
420 200
300 300
50 130
270 300
320 310
490 450
480 480
420 400
250 250
230 270
400 300

结果:
这里写图片描述

CvSVM::predict
预测样本的相应数据。

C++: float CvSVM::predict(const Mat& sample, bool returnDFVal=false ) const
C++: float CvSVM::predict(const CvMat* sample, bool returnDFVal=false ) const
C++: float CvSVM::predict(const CvMat* samples, CvMat* results) const
参数
sample – 需要预测的输入样本。
samples – 需要预测的输入样本们。
returnDFVal – 指定返回值类型。如果值是true,则是一个2类分类问题,该方法返回的决策函数值是边缘的符号距离。
results – 相应的样本输出预测的响应。
这个函数用来预测一个新样本的响应数据(response)。在分类问题中,这个函数返回类别编号;在回归问题中,返回函数值。输入的样本必须与传给trainData的训练样本同样大小。如果训练中使用了varIdx参数,一定记住在predict函数中使用跟训练特征一致的特征。

所以returnDFVal 为true时,二分类得到的结果可以间接的作为相似度,绝对值越大,与训练样本越不相似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值