OpenCV 與 SVM

xiaozl_284發表於2017-03-13

OpenCV 與 SVM


一、SVM概述

支援向量機SVM(Support Vector Machine)是一個有監督的學習模型,通常用來分類及迴歸分析。同樣地,在OpenCV中已經有相關的庫函式CvSVM實現了。一如既往地,我們不詳細介紹SVM的演算法原理,只是簡單地介紹OpenCV是如何呼叫SVM的。本文參考:http://blog.csdn.net/qq_15947787/article/details/51375349

如果想要詳細瞭解SVM的演算法原理及證明過程,推薦以下參考網址:http://www.dataguru.cn/thread-371987-1-1.htmlhttp://blog.csdn.net/alvine008/article/details/9097105

二、 設定引數及初始化
    //設定引數  
    CvSVMParams params;  
    params.svm_type  = CvSVM::C_SVC;     //n(n>2)的分類器,其中引數C是異常懲罰因子,可以進行不完全分類  
    //params.svm_type  = CvSVM::NU_SVC;    //n(n>2)類似不完全分類的分類器,引數nu(nu屬於[0,1]),取代了C_SVC型別的異常懲罰因子C;  
    //params.svm_type  = CvSVM::ONE_CLASS;  //單分類器,用一個分界線對特徵空間進行分割。  

    params.kernel_type = CvSVM::LINEAR;  //線性核函式,此核函式在分類是速度最快,分類將在原始空間中完成;  
    //params.kernel_type = CvSVM::POLY;    //多項式核  
    //params.kernel_type = CvSVM::RBF;     //徑向基核,對於大部分情況都是選擇此型別  
    //params.kernel_type = CvSVM::SIGMOID;  //sigmoid核函式  

    params.term_crit  = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); //SVM迭代終止條件,CV_TERMCRIT_ITER為終止條件型別,100為最大迭代次數,1e-6為結果的準確率  

    //訓練SVM  
    CvSVM SVM;  
    SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); 
三、 預測資料標籤
    //資料視覺化表示  
    int width = 512, height = 512;  
    Mat image = Mat::zeros(height, width, CV_8UC3);
    Vec3b green(0,255,0), blue(255,0,0);  

    //顯示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;  
        }  
四、 完整的示例程式碼及結果顯示:

// OpenCV SVM 支援向量機.cpp : 定義控制檯應用程式的入口點。
//參考網址: http://blog.csdn.net/qq_15947787/article/details/51375349

#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;
#define COUNT 21   //樣本點個數

int main()
{
    //讀入訓練資料特徵
    float data[COUNT][2] = { 0 };
    ifstream in1("data.txt");
    for (int i = 0; i < COUNT; i++)
    {
        in1 >> data[i][0];
        in1 >> data[i][1];
    }
    in1.close();
    //讀入訓練資料標籤
    float label[COUNT] = { 0 };
    ifstream in2("label.txt");
    for (int i = 0; i < COUNT; i++)
    {
        in2 >> label[i];
    }
    in2.close();

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

    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);
    Vec3b green(0, 255, 0), blue(255, 0, 0), red(0, 0, 255), gray(125, 125, 125);
    Mat image = Mat::zeros(500, 500, CV_8UC3);
    for (int i = 0; i < image.cols; i++)
    {
        for (int j = 0; j < image.rows; j++)
        {
            Mat sampleMat = (Mat_<float>(1, 2) << i,j);   //   這裡用的訓練資料的第一維應該是列,第二維是行 (i,j)
            float response = svm.predict(sampleMat);

            if (response == 3)
                image.at<Vec3b>(j,i) = green;    //所以image這裡是(j,i)
            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)
            circle(image, p, 3, Scalar(255, 255, 0), -1, 8);
        if (label[i] == 1)
            circle(image, p, 3, Scalar(255, 0, 255), -1, 8);
        if (label[i] == 2)
            circle(image, p, 3, Scalar(0, 255, 255), -1, 8);
        if (label[i] == 3)
            circle(image, p, 3, Scalar(0, 0, 0), -1, 8);
    }

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


    return 0;
}

data

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

label

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

圖片結果:


相關文章