我的OpenCV學習筆記(六):使用支援向量機(SVM)
SVM是2000年左右提出的一種新的分類方法,著重解決了小樣本分類問題。具體原理可以參看模式識別的書籍。OpenCV中的SVM的實現也是基於大名鼎鼎的SVM 庫:http://www.csie.ntu.edu.tw/~cjlin。OpenCV教程中有兩個例子,一個是線性可分的,一個是線性不可分的,我對他們做了詳盡的註釋:
先看(無噪聲)線性可分時:
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/ml/ml.hpp>
- using namespace cv;
- int main()
- {
- // Data for visual representation
- int width = 512, height = 512;
- Mat image = Mat::zeros(height, width, CV_8UC3);
- // Set up training data
- float labels[5] = {1.0, -1.0, -1.0, -1.0,1.0};
- Mat labelsMat(5, 1, CV_32FC1, labels);
- float trainingData[5][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501},{501,128} };
- Mat trainingDataMat(5, 2, CV_32FC1, trainingData);
- //設定支援向量機的引數
- CvSVMParams params;
- params.svm_type = CvSVM::C_SVC;//SVM型別:使用C支援向量機
- params.kernel_type = CvSVM::LINEAR;//核函式型別:線性
- params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);//終止準則函式:當迭代次數達到最大值時終止
- //訓練SVM
- //建立一個SVM類的例項
- CvSVM SVM;
- //訓練模型,引數為:輸入資料、響應、XX、XX、引數(前面設定過)
- SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
- 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 sampleMat = (Mat_<float>(1,2) << i,j);
- //predict是用來預測的,引數為:樣本、返回值型別(如果值為ture而且是一個2類問題則返回判決函式值,否則返回類標籤)、
- float response = SVM.predict(sampleMat);
- if (response == 1)
- image.at<Vec3b>(j, i) = green;
- else if (response == -1)
- image.at<Vec3b>(j, i) = blue;
- }
- //畫出訓練資料
- 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);
- circle(image, Point( 501, 128), 5, Scalar(0, 0, 0), thickness, lineType);
- //顯示支援向量
- thickness = 2;
- lineType = 8;
- //獲取支援向量的個數
- int c = SVM.get_support_vector_count();
- for (int i = 0; i < c; ++i)
- {
- //獲取第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);
- }
- imwrite("result.png", image); // save the image
- imshow("SVM Simple Example", image); // show it to the user
- waitKey(0);
- }
(含有噪聲)線性可分時由於樣本較多,訓練的時間比較長:
- #include <iostream>
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/ml/ml.hpp>
- #include "time.h"
- using namespace cv;
- using namespace std;
- //程式說明:
- //一共兩個樣本集每個樣本集有100個樣本,其中90個是線性可分的,10個線型不可分
- //這200個樣本資料儲存在trainData內:trainData是一個200行2列的矩陣,其中第一列儲存樣本的X值,第二列儲存的是樣本的Y值
- //每一列的前90個元素是第一類的線性可分部分,後90個元素是第二類的線性可分部分,中間的20個元素是線性不可分部分
- //第一類樣本的X值分佈在整幅影像的[0,0.4]範圍內,第二類樣本的X值分佈在整幅影像的[0.6,1]範圍內,中間的[0.4,0.6]是線性不可分的部分;這三部分的Y值都在整幅影像的高度內自由分佈
- //每個樣本集的數量
- #define NTRAINING_SAMPLES 100
- //其中的線性部分
- #define FRAC_LINEAR_SEP 0.9f
- int main()
- {
- //定義顯示結果的影像
- //影像的寬度、高度
- const int WIDTH = 512,HEIGHT = 512;
- Mat image = Mat::zeros(HEIGHT,WIDTH,CV_8UC3);
- //************第一步:設定訓練資料***********
- //************1.設定資料結構****************
- //承載訓練資料的結構
- Mat trainData(2*NTRAINING_SAMPLES,2,CV_32FC1);
- //承載這些資料分類的結構
- Mat labels(2*NTRAINING_SAMPLES,1,CV_32FC1);
- //設定隨機數種子
- RNG rng(100);
- //設定線性可分部分的資料量
- int nLinearSamples = (int) (NTRAINING_SAMPLES*FRAC_LINEAR_SEP);
- //**************2.設定第一類中的資料*********
- //從整個資料集中取出前[0,89]行
- //注:*Range的範圍是[a,b)
- Mat trainClass = trainData.rowRange(0,nLinearSamples);
- //取出第一列
- Mat c = trainClass.colRange(0,1);
- //隨機生成X的值:[0,0.4*WIDTH]
- rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(0.4*WIDTH));
- //取出第二列
- c = trainClass.colRange(1,2);
- //隨機生成Y的值
- rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));
- //**************2.設定第二類的資料*************
- //從整個資料中取出[110,199]行
- trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples,2*NTRAINING_SAMPLES);
- //取出第一列
- c = trainClass.colRange(0,1);
- //隨機生成X的值[0.6*WIDTH,WIDTH]
- rng.fill(c,RNG::UNIFORM,Scalar(0.6*WIDTH),Scalar(WIDTH));
- //取出第二列
- c = trainClass.colRange(1,2);
- //隨機生成Y的值
- rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));
- //***************3.設定線性不可分的資料***********
- //取出[90,109]行
- trainClass = trainData.rowRange(nLinearSamples,2*NTRAINING_SAMPLES-nLinearSamples);
- //取出第一列
- c = trainClass.colRange(0,1);
- //隨機生成X的值[0.4*WIDTH,0.6*WIDTH]
- rng.fill(c,RNG::UNIFORM,Scalar(0.4*WIDTH),Scalar(0.6*WIDTH));
- //取出第二列
- c = trainClass.colRange(1,2);
- //隨機生成Y的值
- rng.fill(c,RNG::UNIFORM,Scalar(1),Scalar(HEIGHT));
- //***************4.為所有資料設定標籤**********
- //前100個資料設為第一類
- labels.rowRange(0,NTRAINING_SAMPLES).setTo(1);
- //後100個資料設為第二類
- labels.rowRange(NTRAINING_SAMPLES,2*NTRAINING_SAMPLES).setTo(2);
- //**************第二步:設定SVM引數***********
- CvSVMParams params;
- //SVM型別: C-Support Vector Classification
- params.svm_type = SVM::C_SVC;
- params.C = 0.1;
- //和函式型別:Linear kernel
- params.kernel_type = SVM::LINEAR;
- //終止準則:當迭代次數到達最大值後終止
- params.term_crit = TermCriteria(CV_TERMCRIT_ITER,(int) 1e7,1e-6);
- //**************第三步:訓練SVM***********
- cout<<"開始訓練過程"<<endl;
- //開始計時
- clock_t start,finish;
- double duration;
- start = clock();
- //*************1.建立一個SVM例項**********
- CvSVM svm;
- //*************2.呼叫訓練函式*************
- svm.train(trainData,labels,Mat(),Mat(),params);
- //結束計時
- finish = clock();
- duration = (double)(finish-start) / CLOCKS_PER_SEC;
- cout<<"訓練過程結束,共耗時:"<<duration<<"秒"<<endl;
- //************第四步:顯示判決域************
- //第一類用綠色;第二類用藍色
- Vec3b green(0,100,0),blue(100,0,0);
- 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 == 2)
- {
- image.at<Vec3b>(j,i) = blue;
- }
- }
- }
- //************第五步:顯示訓練資料************
- //紅色
- //負數會導致畫出的圖型是實心的
- int thick = -1;
- int lineType = 8;
- float px,py;
- //************1.第一類*************
- for(int i = 0; i < NTRAINING_SAMPLES; ++i)
- {
- px = trainData.at<float>(i,0);
- py = trainData.at<float>(i,1);
- circle(image,Point((int)px,(int)py),3,Scalar(0,255,0));
- }
- //***********2.第二類****************
- for(int i = NTRAINING_SAMPLES; i < 2*NTRAINING_SAMPLES; ++i)
- {
- px = trainData.at<float>(i,0);
- py = trainData.at<float>(i,1);
- circle(image,Point((int)px,(int)py),3,Scalar(255,0,0));
- }
- //***********第六步:顯示支援向量*************
- thick = 2;
- lineType = 8;
- //獲取支援向量的個數
- int x = svm.get_support_vector_count();
- for(int i = 0; i < x; ++i)
- {
- const float* v = svm.get_support_vector(i);
- circle(image,Point((int)v[0],(int)v[1]),6,Scalar(128,128,128),thick,lineType);
- }
- imshow("分類結果",image);
- waitKey(0);
- return 0;
- }
網址:http://blog.csdn.net/thefutureisour/article/details/7491565
相關文章
- OpenCV筆記(3)實現支援向量機(SVM)OpenCV筆記
- 學習Opencv2.4.9(四)---SVM支援向量機OpenCV
- 學習SVM(四) 理解SVM中的支援向量(Support Vector)
- 【Python機器學習實戰】感知機和支援向量機學習筆記(三)之SVM的實現Python機器學習筆記
- 機器學習演算法筆記之5:支援向量機SVM機器學習演算法筆記
- 機器學習:支援向量機(SVM)機器學習
- 機器學習——支援向量機(SVM)機器學習
- [譯] 支援向量機(SVM)教程
- 機器學習——支援向量機SVM(一)機器學習
- 學習OpenCV——SVMOpenCV
- 學習SVM(二) 如何理解支援向量機的最大分類間隔
- 支援向量機(Support Vector Machine,SVM)—— 線性SVMMac
- 吳恩達《Machine Learning》精煉筆記 7:支援向量機 SVM吳恩達Mac筆記
- 人工智慧-機器學習-支援向量機SVM人工智慧機器學習
- 《吳恩達機器學習》學習筆記007_支援向量機吳恩達機器學習筆記
- 【機器學習】支援向量機(個人筆記)機器學習筆記
- 分類演算法-支援向量機 SVM演算法
- 機器學習基礎專題:支援向量機SVM機器學習
- 支援向量機SVM:從數學原理到實際應用
- opencv SVM的使用OpenCV
- CUDA 學習筆記之向量宣告使用筆記
- 支援向量機(SVM)和python實現(二)Python
- SVM 支援向量機演算法-原理篇演算法
- SVM 支援向量機演算法-實戰篇演算法
- 演算法金 | 再見,支援向量機 SVM!演算法
- opencv SVM 使用OpenCV
- opencv學習筆記(一)OpenCV筆記
- 監督學習之支援向量機
- 吳恩達機器學習筆記 —— 13 支援向量機吳恩達機器學習筆記
- 學習SVM(一) SVM模型訓練與分類的OpenCV實現模型OpenCV
- 支援向量機 (二): 軟間隔 svm 與 核函式函式
- Javascript 學習 筆記六JavaScript筆記
- Python數模筆記-Sklearn(5)支援向量機Python筆記
- 《機器學習_07_01_svm_硬間隔支援向量機與SMO》機器學習
- 機器學習基礎篇:支援向量機(SVM)理論與實踐機器學習
- 機器學習(四):通俗理解支援向量機SVM及程式碼實踐機器學習
- 支援向量機(SVM)從原理到python程式碼實現Python
- HexMap學習筆記(六)——河流筆記