在【OpenCV16:Hog特征】中已经详细描述了Hog特征,这次加上SVM做一个小小的识别。
实现步骤如下:1、准备数据集 2、对样本进行Hog特征的训练 3、预测
1、准备数据集
一个好的样本,远胜过一个复杂的神经网络。
我们将数据集分为两个文件夹neg(1931张图,大小64*128)和pos(820张,大小64*128)。
pos文件夹里存放的是正样本,所有图片都包含小狮子。
neg文件夹里存放的是负样本,所有图片都不能包含小狮子。
正样本尽可能多样化:如环境、角度、干扰等。
2、对样本进行Hog特征的训练 3、预测
定义的Hog特征在【OpenCV16:Hog特征】中有介绍,使用的推荐大小。
首先,要训练SVM 是监督学习,学习的是图中的Hog特征,所以要使用计算好的Hog特征对正负样本进行标签的设置。代码如下:
# 5、设置正负样本标签
for i in range(PosNum):
fileName = 'pos\\' + str(i+1) + '.jpg'
img = cv2.imread(fileName)
hist = hog.compute(img, (8,8)) # 计算hog特征
# 将正样本中的 Hog特征装到featureArray中
for j in range(featureNum): # Hog特征维度,在下面的全部代码中有定义
featureArray[i,j] = hist[j] # featureArray中的每一行代表一个3780维的 Hog特征
labelArray[i,0] = 1 # 正样本标签设置为 1
# 处理负样本
for i in range(NegNum):
fileName = 'neg\\' + str(i+1) + '.jpg'
img = cv2.imread(fileName)
hist = hog.compute(img, (8,8)) # 计算hog特征
for j in range(featureNum):
featureArray[i+PosNum, j] = hist[j]
labelArray[i+PosNum, 0] = -1 # 正样本标签设置为 -1
然后设置SVM的属性,并加以训练:
# 设置svm的属性
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(0.01)
# 6、训练
ret = svm.train(featureArray, cv2.ml.ROW_SAMPLE, labelArray)
在检测时,需要创建一个myHog,其核心是myDetect。所以要得到这个myDetect,myDetect是一个数组,数据由resultArray和经过SVM训练得到的rho组成。得到detect后调用detectMutiScale()方法预测,这个方法可以返回目标的宽高信息,从而实现绘制。全部代码如下:
# 整个过程分为7步:1、Hog参数设置 2、创建Hog 3、svm参数设置与创建 4、计算Hog 5、label 6、训练 7、预测
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 1、设置 Hog参数,定义3780维的Hog特征
PosNum = 820 # 正样本的数量
NegNum = 1931
winSize = (64,128) # win的大小
blockSize = (16,16) # block的大小
blockStep = (8,8)
cellSize = (8,8)
binNum = 9
# 2、创建Hog
hog = cv2.HOGDescriptor(winSize,blockSize,blockStep,cellSize,binNum)
# 3、创建svm
svm = cv2.ml.SVM_create()
# 4、计算Hog
featureNum = int(((128-16)/8+1) * ((64-16)/8+1) * 4 * 9) # 3780维的特征数,计算的是bin的数量,数字为推荐尺寸
featureArray = np.zeros(((PosNum + NegNum),featureNum),np.float32) # 装载特征的数组 全样本数行 * 特征维数(3780)列
labelArray = np.zeros(((PosNum + NegNum), 1), np.int32) # 装载标签的数组, 注意!!!!如果labelArray报错,那么你应该写成了np.float32
# svm 是监督学习,学习的是图中的Hog特征
# 5、设置正负样本标签
for i in range(PosNum):
fileName = 'pos\\' + str(i+1) + '.jpg'
img = cv2.imread(fileName)
hist = hog.compute(img, (8,8)) # 计算hog特征
# 将正样本中的 Hog特征装到featureArray中
for j in range(featureNum):
featureArray[i,j] = hist[j] # featureArray中的每一行代表一个3780维的 Hog特征
labelArray[i,0] = 1 # 正样本标签设置为 1
# 处理负样本
for i in range(NegNum):
fileName = 'neg\\' + str(i+1) + '.jpg'
img = cv2.imread(fileName)
hist = hog.compute(img, (8,8)) # 计算hog特征
for j in range(featureNum):
featureArray[i+PosNum, j] = hist[j]
labelArray[i+PosNum, 0] = -1 # 正样本标签设置为 -1
# 设置svm的属性
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(0.01)
# 6、训练
ret = svm.train(featureArray, cv2.ml.ROW_SAMPLE, labelArray)
print(ret)
# 7、预测
alpha = np.zeros((1), np.float32) # 一维数组
rho = svm.getDecisionFunction(0,alpha) # 在SVM的判决中需要用到 rho
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
print(resultArray)
# 创建 myDetect是为了创建 Hog,detect是其核心
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) # 把当前myDtector属性传入Hog
imgSrc = cv2.imread('OpenCV\\Test2.jpg', 1) # 读取检测图
# (8,8)win步长 (32,32)win尺寸 1.05缩放系数 2最小像素范围
objs = myHog.detectMultiScale(imgSrc, 0, (8,8), (32,32), 1.05, 2) # 三维信息
# 起始坐标,和宽度高度放在了objs的最后一维
x = int(objs[0][0][0])
y = int(objs[0][0][1])
w = int(objs[0][0][2])
h = int(objs[0][0][3])
# 绘制展示
cv2.rectangle(imgSrc,(x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow('dst',imgSrc)
cv2.waitKey(0)
cv2.destroyAllWindows()