欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV:使用python-cv2+Hog特征+SVM实现狮子识别

程序员文章站 2022-07-14 23:43:41
...

SVM

支持向量机:寻求一个最优的超平面,实现样本的分类
OpenCV:使用python-cv2+Hog特征+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特征

看下面这个例子:
OpenCV:使用python-cv2+Hog特征+SVM实现狮子识别

这里有一个图像img(整个白色区域), win窗口(蓝色区域)为图像中Hog特征计算的最大模板,官方模板大小为64*128block(红色区域部分)为win窗口中的小模板,大小一般为16*16block中又有很多的小模板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]]))

OpenCV:使用python-cv2+Hog特征+SVM实现狮子识别