OpenCV筆記(3)實現支援向量機(SVM)
參考教程:點選開啟連結
參考教程使用的是OpenCV 2.0 版本,這裡將其修改為3.0版本。
1.SVM(支援向量機)
SVM是一種訓練機器學習的演算法,可以用於解決分類和迴歸問題。
正式定義:是一個能將不同類樣本在樣本空間分割的超平面,給定一些標記好的訓練樣本,SVM演算法輸出一個最優化的分隔超平面。
判定是否為最優平面的依據:
如上圖所示,給定一些分屬兩類的特徵點,這些點可以通過直線分割,我們要找到一個最優的直線。滿足的直線很多,該怎麼定義最優?有個評價標準是直線到所有點的距離最遠。距離樣本點太近的話,直線對噪聲敏感度高,泛化性比較差。
SVM演算法就是找到能將某個值最大化的超平面,這個值是超平面離所有樣本點的最小距離。這個距離叫間隔。
相比較其他機器學習演算法,它的優點有樣本小 、結構風險小、非線性等。
SVM離不開核函式。簡單來說,核函式就是將低維空間的線性不可分類問題,轉化為高維空間的線性可分問題,在高維空間找到最優邊界。
2.OpenCV實現
首先,建立訓練樣本:
//建立訓練樣本
int labels[10] = {1, 1, -1, 1, -1, -1, -1, 1, -1, -1};
float trainingData[10][2] = {{501,150},{255,10},{501,255},{10,501},{25,80},{150,300},{77,200},{300,300},{45,250},{200,200}};
Mat labelsMat(10, 1, CV_32SC1, labels);
Mat trainingDataMat(10, 2, CV_32FC1, trainingData);
labels是訓練資料的分類標記,有兩類:1和-1。
trainingData是訓練資料。
設定SVM的引數:
Ptr<SVM> svm = SVM::create();//建立分類器
svm->setType(SVM::C_SVC);//SVM型別
svm->setKernel(SVM::LINEAR);//核函式的型別
svm->setTermCriteria(TermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON));//演算法終止條件
這裡opencv 2.x版本和3.x版本設定方式不一樣,下面是2.x版本:
CvSVMParams params;//建立分類器
params.svm_type = CvSVM::C_SVC;//SVM型別
params.kernel_type = CvSVM::LINEAR;//核函式的型別
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);//演算法終止條件
其它的引數我們需要時,可以繼續設定。
開始訓練:
//設定訓練資料並訓練分類器
Ptr<TrainData> tData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(tData);
下面是2.x版本的訓練:
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
SVM區域分割:
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) << j, i);
float response = svm->predict(sampleMat);
//float response = SVM.predict(sampleMat); 這裡有不同
if (response == 1)
{
image.at<Vec3b>(i, j) = green;
}
else if (response == -1)
{
image.at<Vec3b>(i, j) = blue;
}
}
}
給空間上色,著色取決於SVM的分類,綠色是標記為1的點,藍色是標記為-1的點。
顯示結果:
//顯示訓練資料
int thickness = -1;
int lineType = 8;
Scalar c1 = Scalar::all(0); //標記為1的顯示成黑點
Scalar c2 = Scalar::all(255); //標記成-1的顯示成白點
for (int i = 0; i < labelsMat.rows; i++)
{
const float* v = trainingDataMat.ptr<float>(i);
Point pt = Point((int)v[0], (int)v[1]);
if (labels[i] == 1)
{
circle(image, pt, 5, c1, thickness, lineType);
}
else
{
circle(image, pt, 5, c2, thickness, lineType);
}
}
imshow("SVM", image);
waitKey(0);
最終結果:
程式建立一張影像,在其中顯示訓練樣本,1為黑點,-1為白點。
訓練得到SVM,並將影像的每一個畫素分類。分類的結果將影像分為藍綠兩部分,中間線是最優分割平面。
完整程式碼:
#include <stdio.h>
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace ml;
int main()
{
int width = 512;
int height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
//建立訓練樣本
int labels[10] = { 1, -1, 1, 1, -1, 1, -1, 1, -1, -1 };
float trainingData[10][2] = {{501,150},{255,10},{501,255},{10,501},{25,80},{150,300},{77,200},{300,300},{45,250},{200,200}};
Mat labelsMat(10, 1, CV_32SC1, labels);
Mat trainingDataMat(10, 2, CV_32FC1, trainingData);
Ptr<SVM> svm = SVM::create();//建立分類器
svm->setType(SVM::C_SVC);//SVM型別
svm->setKernel(SVM::LINEAR);//核函式的型別
svm->setTermCriteria(TermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON));//演算法終止條件
//設定訓練資料並訓練分類器
Ptr<TrainData> tData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(tData);
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) << j, i);
float response = svm->predict(sampleMat);
//float response = SVM.predict(sampleMat); 這裡有不同
if (response == 1)
{
image.at<Vec3b>(i, j) = green;
}
else if (response == -1)
{
image.at<Vec3b>(i, j) = blue;
}
}
}
//顯示訓練資料
int thickness = -1;
int lineType = 8;
Scalar c1 = Scalar::all(0); //標記為1的顯示成黑點
Scalar c2 = Scalar::all(255); //標記成-1的顯示成白點
for (int i = 0; i < labelsMat.rows; i++)
{
const float* v = trainingDataMat.ptr<float>(i);
Point pt = Point((int)v[0], (int)v[1]);
if (labels[i] == 1)
{
circle(image, pt, 5, c1, thickness, lineType);
}
else
{
circle(image, pt, 5, c2, thickness, lineType);
}
}
imshow("SVM", image);
waitKey(0);
}
相關文章
- 我的OpenCV學習筆記(六):使用支援向量機(SVM)OpenCV筆記
- 學習Opencv2.4.9(四)---SVM支援向量機OpenCV
- 支援向量機(SVM)和python實現(二)Python
- 機器學習演算法筆記之5:支援向量機SVM機器學習演算法筆記
- 機器學習:支援向量機(SVM)機器學習
- 機器學習——支援向量機(SVM)機器學習
- 【Python機器學習實戰】感知機和支援向量機學習筆記(三)之SVM的實現Python機器學習筆記
- [譯] 支援向量機(SVM)教程
- 機器學習——支援向量機SVM(一)機器學習
- 支援向量機(SVM)從原理到python程式碼實現Python
- 支援向量機(Support Vector Machine,SVM)—— 線性SVMMac
- SVM 支援向量機演算法-實戰篇演算法
- 吳恩達《Machine Learning》精煉筆記 7:支援向量機 SVM吳恩達Mac筆記
- 人工智慧-機器學習-支援向量機SVM人工智慧機器學習
- 一文讀懂支援向量機SVM(附實現程式碼、公式)公式
- 【機器學習】支援向量機(個人筆記)機器學習筆記
- 分類演算法-支援向量機 SVM演算法
- 機器學習基礎專題:支援向量機SVM機器學習
- 機器學習基礎篇:支援向量機(SVM)理論與實踐機器學習
- 機器學習(四):通俗理解支援向量機SVM及程式碼實踐機器學習
- 支援向量機SVM:從數學原理到實際應用
- SVM 支援向量機演算法-原理篇演算法
- 演算法金 | 再見,支援向量機 SVM!演算法
- 支援向量機(SVM)的約束和無約束優化、理論和實現優化
- SVM多分類器的實現(Opencv3,C++)OpenCVC++
- 吳恩達機器學習筆記 —— 13 支援向量機吳恩達機器學習筆記
- 支援向量機 (二): 軟間隔 svm 與 核函式函式
- 學習SVM(四) 理解SVM中的支援向量(Support Vector)
- Python機器學習筆記:SVM(3)——證明SVMPython機器學習筆記
- 支援向量機|SMO演算法實現演算法
- Python數模筆記-Sklearn(5)支援向量機Python筆記
- 《機器學習_07_01_svm_硬間隔支援向量機與SMO》機器學習
- 【opencv3】 svm實現手寫體與人臉識別OpenCV
- 支援向量機python實現(簡易版)Python
- 學習SVM(一) SVM模型訓練與分類的OpenCV實現模型OpenCV
- ClickHouse原始碼筆記3:函式呼叫的向量化實現原始碼筆記函式
- 《機器學習_07_03_svm_核函式與非線性支援向量機》機器學習函式
- 學習SVM(二) 如何理解支援向量機的最大分類間隔