計算機視覺—人臉識別(Hog特徵+SVM分類器)(8)

1、SVM支持向量機

一、SVM原理

在機器學習,支持向量機的監督學習模型與相關的學習算法能夠分析用於數據分類和迴歸分析。給定一組訓練樣例,每一個訓練樣例被標記爲屬於兩個類別中的一個或另外一個,SVM訓練算法創建一個模型,將新的例子分配給一個類別或另外一個類別,使其成爲非機率二元線性分類器(儘管方法如Platt縮放存在以在機率分類設置中使用SVM)。SVM模型是將這些例子表示爲空間中的點的映射,以便將各個類別的例子除以儘量寬的明顯差距。而後將新示例映射到同一空間中,並預測屬於基於它們落在哪一側的類別。html

好比,咱們有兩種顏色的球在桌子上,咱們要分開它們。python

咱們拿到一根棍子放在桌子上,是否完成得很漂亮?算法

有些賤人來了,桌子上放了更多的球,這種方法頗有效,但其中一個球在錯誤的一邊,如今可能有一個更好的地方放置棒。json

SVM試圖經過儘量在棒的兩側留出儘量大的間隙來將棒放置在最佳位置。bash

如今,當賤人回來時,棍子仍然是一個不錯的位置。機器學習

SVM工具箱還有另外一個更重要的技巧。賤人已經看到你用棍子有多好,因此他給了你一個新的挑戰。ide

世界上沒有任何棍棒可讓你分球,因此你會怎麼作?你固然翻桌子!把球扔進空中。而後,用你的專業忍者技能,你抓住一張紙並將其滑入球之間。函數

如今,賤人站着看球,他們的球會看起來被一些彎曲的線條分開。工具

再以後,無聊的大人們,把這些球叫作 「data」,把棍子 叫作 「classifier」, 最大間隙trick 叫作「optimization」, 拍桌子叫作「kernelling」, 那張紙叫作「hyperplane」。學習

二、opencv的SVM參數

OpenCV 3.3中給出了支持向量機(Support Vector Machines)的實現,即cv::ml::SVM類,此類的聲明在include/opencv2/ml.hpp文件中,實如今modules/ml/src/svm.cpp文件中,它既支持兩分類,也支持多分類,還支持迴歸等,OpenCV中SVM的實現源自libsvm庫。其中:

(1)、cv::ml::SVM類:繼承自cv::ml::StateModel,而cv::ml::StateModel又繼承自cv::Algorithm;

(2)、create函數:爲static,new一個SVMImpl用來建立一個SVM對象;

(3)、setType/getType函數:設置/獲取SVM公式類型,包括C_SVC、NU_SVC、ONE_CLASS、EPS_SVR、NU_SVR,用於指定分類、迴歸等,默認爲C_SVC;

(4)、setGamma/getGamma函數:設置/獲取核函數的γ參數,默認值爲1;

(5)、setCoef0/getCoef0函數:設置/獲取核函數的coef0參數,默認值爲0;

(6)、setDegree/getDegree函數:設置/獲取核函數的degreee參數,默認值爲0;

(7)、setC/getC函數:設置/獲取SVM優化問題的C參數,默認值爲0;

(8)、setNu/getNu函數:設置/獲取SVM優化問題的υ參數,默認值爲0;

(9)、setP/getP函數:設置/獲取SVM優化問題的ε參數,默認值爲0;

(10)、setClassWeights/getClassWeights函數:應用在SVM::C_SVC,設置/獲取weights,默認值是空cv::Mat;

(11)、setTermCriteria/getTermCriteria函數:設置/獲取SVM訓練時迭代終止條件,默認值是cv::TermCriteria(cv::TermCriteria::MAX_ITER + TermCriteria::EPS,1000, FLT_EPSILON);

(12)、setKernel/getKernelType函數:設置/獲取SVM核函數類型,包括CUSTOM、LINEAR、POLY、RBF、SIGMOID、CHI二、INTER,默認值爲RBF;

(13)、setCustomKernel函數:初始化CUSTOM核函數;

(14)、trainAuto函數:用最優參數訓練SVM;

(15)、getSupportVectors/getUncompressedSupportVectors函數:獲取全部的支持向量;

(16)、getDecisionFunction函數:決策函數;

(17)、getDefaultGrid/getDefaultGridPtr函數:生成SVM參數網格;

(18)、save/load函數:保存/載入已訓練好的model,支持xml,yaml,json格式;

(19)、train/predict函數:用於訓練/預測,均使用基類StatModel中的。

原文連接:http://bytesizebio.net/2014/02/05/support-vector-machines-explained-well/
公式連接:https://en.wikipedia.org/wiki/Support_vector_machine
SVM參數連接:https://docs.opencv.org/master/d1/d2d/classcv_1_1ml_1_1SVM.html

實例

svm_type()—— 指定SVM的類型:

參數:

  • C_SVC:C表示懲罰因子,C越大表示對錯誤分類的懲罰越大。
  • NU_SVC:和C_SVC相同。
  • ONE_CLASS:不須要類標號,用於支持向量的密度估計和聚類.
  • EPSILON_SVR:-不敏感損失函數,對樣本點來講,存在着一個不爲目標函數提供任何損失值的區域,即-帶。
  • NU_SVR:因爲EPSILON_SVR須要事先肯定參數,然而在某些狀況下選擇合適的參數卻不是一件容易的事情。而NU_SVR可以自動計算參數。

kernel_type()—— SVM的內核類型:

參數:

  • LINEAR:線性核函數(linear kernel)
  • POLY:多項式核函數(ploynomial kernel)
  • RBF:徑向機核函數(radical basis function)
  • SIGMOID: 神經元的非線性做用函數核函數(Sigmoid tanh)
  • PRECOMPUTED:用戶自定義核函數

train()

參數:

  • InputArray samples, 訓練樣本
  • int layout, 排版,參數:ROW_SAMPLE,每一個訓練樣本是一行樣本,COL_SAMPLE,每一個訓練樣本佔據一列樣本
  • InputArray responses, 與訓練樣本相關聯的響應向量

getDecisionFunction()

參數:

  • int i,決策函數的索引。若是解決的問題是迴歸,1類或2類分類,那麼只會有一個決策函數,而且索引應該老是0.不然,在N類分類的狀況下,將會有N(N- 1 )/ 2 決策功能。
  • OutputArray alpha, α 權重的可選輸出向量,對應於不一樣的支持向量。在線性SVM的狀況下,全部的alpha都是1。
  • OutputArray svidx, 支持向量矩陣內的支持向量索引的可選輸出向量。在線性SVM的狀況下,每一個決策函數由單個「壓縮」支持向量組成。
import cv2
import numpy as np
import matplotlib.pyplot as plt
#1 準備data
rand1 = np.array([[155,48],[159,50],[164,53],[168,56],[172,60]])
# 女生身高和體重數據
rand2 = np.array([[152,53],[156,55],[160,56],[172,64],[176,65]])
# 男生身高和體重數據

# 2 創建分組標籤,0表明女生,1表明男生
label = np.array([[0],[0],[0],[0],[0],[1],[1],[1],[1],[1]])

# 3 合併數據
data = np.vstack((rand1,rand2))
data = np.array(data,dtype='float32')

# 4 訓練
# ml 機器學習模塊 SVM_create() 建立
svm = cv2.ml.SVM_create() 

# 屬性設置
svm.setType(cv2.ml.SVM_C_SVC) # svm type
svm.setKernel(cv2.ml.SVM_LINEAR) # line
svm.setC(0.01)

# 訓練
result = svm.train(data,cv2.ml.ROW_SAMPLE,label)

# 預測
pt_data = np.vstack([[167,55],[162,57]]) #0 女生 1男生
pt_data = np.array(pt_data,dtype='float32')
print(pt_data)
(par1,par2) = svm.predict(pt_data)
print(par2)
複製代碼

結果:

[[167.  55.]
 [162.  57.]]
[[0.]
 [1.]]
複製代碼

2、Hog特徵

方向梯度直方圖(Histogram of Oriented Gradient, HOG)特徵是一種在計算機視覺和圖像處理中用來進行物體檢測的特徵描述子。它經過計算和統計圖像局部區域的梯度方向直方圖來構成特徵。Hog特徵結合SVM分類器已經被普遍應用於圖像識別中,尤爲在行人檢測中得到了極大的成功。須要提醒的是,HOG+SVM進行行人檢測的方法是法國研究人員Dalal在2005的CVPR上提出的,而現在雖然有不少行人檢測算法不斷提出,但基本都是以HOG+SVM的思路爲主。

HOG特徵提取算法的實現過程:

HOG特徵提取方法就是將一個image(你要檢測的目標或者掃描窗口):

1)灰度化(將圖像看作一個x,y,z(灰度)的三維圖像);

2)採用Gamma校訂法對輸入圖像進行顏色空間的標準化(歸一化);目的是調節圖像的對比度,下降圖像局部的陰影和光照變化所形成的影響,同時能夠抑制噪音的干擾;

3)計算圖像每一個像素的梯度(包括大小和方向);主要是爲了捕獲輪廓信息,同時進一步弱化光照的干擾。

4)將圖像劃分紅小cells(例如6*6像素/cell);

5)統計每一個cell的梯度直方圖(不一樣梯度的個數),便可造成每一個cell的descriptor;

6)將每幾個cell組成一個block(例如3*3個cell/block),一個block內全部cell的特徵descriptor串聯起來便獲得該block的HOG特徵descriptor。

7)將圖像image內的全部block的HOG特徵descriptor串聯起來就能夠獲得該image(你要檢測的目標)的HOG特徵descriptor了。這個就是最終的可供分類使用的特徵向量了。

原文連接:https://blog.csdn.net/liulina603/article/details/8291093

3、實例

HOGDescriptor()

參數:

  • Size win_size=Size(64, 128),檢測窗口大小。
  • Size block_size=Size(16, 16),塊大小,目前只支持Size(16, 16)
  • Size block_stride=Size(8, 8),塊的滑動步長,大小隻支持是單元格cell_size大小的倍數。
  • Size cell_size=Size(8, 8),單元格的大小,目前只支持Size(8, 8)。
  • int nbins=9, 直方圖bin的數量(投票箱的個數),目前每一個單元格Cell只支持9個。
  • double win_sigma=DEFAULT_WIN_SIGMA,高斯濾波窗口的參數。
  • double threshold_L2hys=0.2,塊內直方圖歸一化類型L2-Hys的歸一化收縮率
  • bool gamma_correction=true,是否gamma校訂
  • nlevels=DEFAULT_NLEVELS,檢測窗口的最大數量

正樣本:

負樣本:

import cv2
import numpy as np
import matplotlib.pyplot as plt
# 第一步:肯定標準
PosNum = 820
# 正樣本個數
NegNum = 1931
# 負樣本我的
winSize = (64,128)
# 一個窗口(win)的大小是64x128
blockSize = (16,16) 
# 每一個塊的大小是16x16
blockStride = (8,8) 
# 每一個塊的步長是8x8
# 一個窗口有((64-16)/8+1)*((128-16)/8+1) = 7*15 = 105個塊(block)
cellSize = (8,8)
# 每一個胞元的大小是8x8
# 一個塊(block)有 (16/8)*(16/8) = 4胞元(cell)
nBin = 9 
# 一個胞元有 9 個bin,表示每個胞元對應的向量就是9維
# 窗口對應的一維特徵向量維數n = 105 * 4 * 9 = 3780
# hog+svm檢測行人,最終的檢測方法是最基本的線性判別函數,wx + b = 0,剛纔所求的3780維向量其實就是w,而加了一維的b就造成了opencv默認的3781維檢測算子

# 第二步:創造一個HOG描述子和檢測器
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nBin)
# 第三步:啓動SVM分離器
svm = cv2.ml.SVM_create()

# 第四步:計算Hog
featureNum = int(((128-16)/8+1)*((64-16)/8+1)*4*9)
# 窗口對應的一維特徵向量維數n
featureArray = np.zeros(((PosNum+NegNum),featureNum),np.float32)
# 建立Hog特徵矩陣
labelArray = np.zeros(((PosNum+NegNum),1),np.int32)
# 建立標籤矩陣

# 給圖片樣本打標籤,正樣本是1,負樣本是-1
for i in range(0,PosNum):
    fileName = 'pos/'+str(i+1)+'.jpg'
    # 導入正樣本圖片
    img = cv2.imread(fileName)
    hist = hog.compute(img,(8,8))
    # 每一個hog特性的維數是3780
    for j in range(0,featureNum):
        featureArray[i,j] = hist[j]
    # featureArray裝載hog特徵, [1,:]表明hog特徵1, [2,:]表明hog特徵2
    labelArray[i,0] = 1
    # 正樣本的label是 1
    
for i in range(0,NegNum):
    fileName = 'neg/'+str(i+1)+'.jpg'
    img = cv2.imread(fileName)
    hist = hog.compute(img,(8,8))
    for j in range(0,featureNum):
        featureArray[i+PosNum,j] = hist[j]
    labelArray[i+PosNum,0] = -1
    # 負樣本的label是 -1
    
# SVM屬性設置 
svm.setType(cv2.ml.SVM_C_SVC)
# SVM模型類型:C_SVC表示SVM分類器,C_SVR表示SVM迴歸
svm.setKernel(cv2.ml.SVM_LINEAR)
# 核函數類型: LINEAR:線性核函數(linear kernel),POLY:多項式核函數(ploynomial kernel),RBF:徑向機核函數(radical basis function),SIGMOID: 神經元的非線性做用函數核函數(Sigmoid tanh),PRECOMPUTED:用戶自定義核函數 
svm.setC(0.01)
# SVM類型(C_SVC/ EPS_SVR/ NU_SVR)的參數C,C表示懲罰因子,C越大表示對錯誤分類的懲罰越大

# 第六步:訓練函數
ret = svm.train(featureArray,cv2.ml.ROW_SAMPLE,labelArray)

# 第七步:檢測 (一、建立myhog,參數myDeteect)
alpha = np.zeros((1),np.float32)
# 權重的可選輸出向量
rho = svm.getDecisionFunction(0,alpha)
# 檢索決策函數。
print(rho)
print(alpha)

alphaArray = np.zeros((1,1),np.float32)
supportVArray = np.zeros((1,featureNum),np.float32)
resultArray = np.zeros((1,featureNum),np.float32)
alphaArray[0,0] = alpha
resultArray = -1*alphaArray*supportVArray

myDetect = np.zeros((3781),np.float32)
for i in range(0,3780):
    myDetect[i] = resultArray[0,i]
myDetect[3780] = rho[0]
# myDetect是3781維,其中3780維來自resultArray,最後一維來自rho

myHog = cv2.HOGDescriptor()
myHog.setSVMDetector(myDetect)

# 第八步:導入待檢測圖片的加載 
imageSrc = cv2.imread('Test2.jpg',1)
# 加載待檢測圖片
objs = myHog.detectMultiScale(imageSrc,0,(8,8),(32,32),1.05,2)
# 檢測圖片
x = int(objs[0][0][0])
y = int(objs[0][0][1])
w = int(objs[0][0][2])
h = int(objs[0][0][3])
# 原始座標(x,y),寬w,高h

# 第九步:繪製展現
cv2.rectangle(imageSrc,(x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow('dst',imageSrc)
cv2.waitKey(0)
複製代碼

待檢測圖片:

結果:

(0.19296025963377925, array([[1.]]), array([[0]], dtype=int32))
[0.]
複製代碼

相關文章
相關標籤/搜索