文章目錄
- SVM
- Hog特征
- Hog特征+SVM實作獅子識別
SVM
支持向量機:尋求一個最優的超平面,實作樣本的分類

下面我們用SVM實作一個根據身高體重對男女生分類的問題
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 準備資料
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]])
# 0為女生 1為男生
label = np.array([[0],[0],[0],[0],[0],[1],[1],[1],[1],[1]])
data = np.vstack((rand1,rand2)) # 合并兩組資料
data = np.array(data, dtype = 'float32')
svm = cv2.ml.SVM_create() # 創建svm學習模型
svm.setType(cv2.ml.SVM_C_SVC) # 型別為svm分類
svm.setKernel(cv2.ml.SVM_LINEAR) # 設定svm的內核為線性分類器
svm.setC(0.01)
#訓練
svm.train(data,cv2.ml.ROW_SAMPLE,label)
# 預測
pt_data = np.array([[167,55],[162,57]])
pt_data = np.array(pt_data, dtype = 'float32')
#pt_label = [[0],[1]]
predict = svm.predict(pt_data)
predict[1]
array([[0.],
[1.]], dtype=float32)
Hog特征
看下面這個例子:

這里有一個影像img(整個白色區域), win視窗(藍色區域)為影像中Hog特征計算的最大模板,官方模板大小為64*128,block(紅色區域部分)為win視窗中的小模板,大小一般為16*16,block中又有很多的小模板cell(綠色區域),大小一般為8*8,
cell bin: 通過計算像素的梯度得到梯度的大小和方向, 方向為0-360度, 如果以40度進行劃分,將會得到9塊,將這9塊設定為9個單元,每一個單元就是一個bin,
hot特征維度: win視窗中block模板的個數 * cell模板個數 * bin的個數
hog特征: 像素都有一個梯度,win視窗中所有的像素梯度構成了hog特征
如何計算梯度:
我們使用倆個模板:水平梯度模板[1 0 -1], 豎直梯度模板[[1],[0],[-1]],即相鄰像素之差,
求得幅值為:f = sqrt(x^2 + y^2),角度angle = arctan(a / b)
bin的劃分:如果以40度進行劃分,將會得到9個bin,則bin1的區域為(0-20度)和180-200度,即關于180度對稱的夾角
如果某個梯度的角度正好在bin角度范圍的正中心, 如d = 10,則將其規劃到bin1區域,否則將該梯度分解到相鄰的倆個bin單元中:d1 = d * d(夾角), d2 = d * (1 - d(夾角))
計算整體的hog特征
1.首先計算每個cell下所有bin的值,每一個bin的計算方式為所有劃分到該bin下的幅值之和sum(d)
2.得到影像特征的維度,以上面的為例,該影像的特征維度為win視窗中block模板的個數 * cell模板個數 * bin的個數 = 105* 4 * 9 = 3780
3.通過使用svm支持向量機對特征進行分類,得到一個3780維的分類結果,用hog * svm得到一個值 f,讓 f 與我們的判決門限進行比較,如果大于判決門限則認為是目標,
Hog特征+SVM實作獅子識別
這里使用正樣本(PosNum) 820張圖片,負樣本(NegNum)1931張圖片進行訓練模型,最終完成訓練,最后采用帶有小獅子的圖片進行測驗
這里使用的正負樣本的資料集如下百度云鏈接中:
鏈接:https://pan.baidu.com/s/1jNpN8ecMKhOHLiy1KlEj4w
提取碼:61hr
訓練步驟如下:
1.設定引數
2.創建Hog:我們使用cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,Bin)函式來創建
3.創建svm,我們使用cv2.ml.SVM_create()函式來創建,并設定屬性
4.計算Hog,準備標簽label
5.訓練
6.預測
7.繪圖
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 1.設定引數
PosNum = 820
NegNum = 1931
winSize = (64,128)
blockSize = (16,16) # 105
blockStride = (8,8)
cellSize = (8,8)
Bin = 9 # 3780
#2.創建hog
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,Bin)
#3.創建svm
svm = cv2.ml.SVM_create()
#svm屬性設定
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(0.01) # 優化
#4.計算hog
featureNum = int(((128 - 16) / 8 + 1) * ((64 - 16) / 8 + 1) * 4 * 9) # 3780
featureArray = np.zeros((PosNum + NegNum, featureNum),np.float32)
labelArray = np.zeros((PosNum + NegNum, 1),np.int32)
# 處理正樣本
for i in range(PosNum):
filename = 'pos\\' + str(i + 1) + '.jpg'
img = cv2.imread(filename)
# 計算影像的hog特征, shape (3780,1)
hist = hog.compute(img, (8,8)) # 第二個引數: winStride Window stride
# 將該hog特征值存到featureArray里面
featureArray[i] = hist.reshape(-1)
labelArray[i] = 1
# 處理負樣本
for i in range(PosNum, PosNum + NegNum):
filename = 'neg\\' + str(i + 1 - PosNum) + '.jpg'
img = cv2.imread(filename)
# 計算影像的hog特征, shape (3780,1)
hist = hog.compute(img, (8,8)) # 第二個引數: winStride Window stride
# 將該hog特征值存到featureArray里面
featureArray[i] = hist.reshape(-1)
labelArray[i] = -1
# 5.訓練
svm.train(featureArray,cv2.ml.ROW_SAMPLE, labelArray)
# 6.檢測
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
# 7.繪圖
myDetect = np.zeros((3781), np.float32)
for i in range(3780):
myDetect[i] = resultArray[0,i]
myDetect[3780] = rho[0]
# 構建hog
myHog = cv2.HOGDescriptor()
myHog.setSVMDetector(myDetect)
# 加載待檢測圖片
imageSrc = cv2.imread('test.jpg', 1)
cv2.imshow('img', imageSrc)
# 引數:(8,8)win滑動步長,(32,32)win大小,縮放系數 目標大小
objects = myHog.detectMultiScale(imageSrc, 0, (8,8), (32,32), 1.05, 2)
x = int(objects[0][0][0])
y = int(objects[0][0][1])
w = int(objects[0][0][2])
h = int(objects[0][0][3])
cv2.rectangle(imageSrc, (x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow('img', imageSrc)
print(objects)
cv2.waitKey(0)
(0.2555259476741386, array([[1.]]), array([[0]], dtype=int32))
[0.]
(array([[ 0, 0, 64, 128]], dtype=int32), array([[0.25552595]]))

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/194016.html
標籤:python
