基于python的HOG+SVM目标检测算法实现

更新时间:2023-05-13 15:14:25 阅读: 评论:0

基于python的HOG+SVM⽬标检测算法实现
⽬录
⼀、场景需求解读
  ⽬标检测是⼀个很常见的计算机视觉任务,它在现实场景中具有很多的应⽤。随着深度学习技术的快速发展,当前主流的⽬标检测算法主要分为单阶段和双阶段,代表性的算法包括SSD和Faster-rcnn等;除此之外也可以分为基于Anchors和Anchors free的算法,尽管这些算法都能取得较⾼的精度,但是它们都需要依赖GPU和⼤量的训练样本,另外,这些算法的运⾏速度都⽐较慢,⼀般都是在GPU上⾯能获得近似实时的速度。对于现实⽣活中的⼀些场景⽽⾔,它们可能对算法的速度和成本有着较⾼的要求,但是检测任务⼜相对来讲⽐较简单,对于这种情况⽽⾔,传统的基于HOG+SVM的检测算法仍然具有较⼤的⽤武之地。下⾯展⽰了⼀个案例。
⼆、HOG算法简介
  HOG是⼀种在计算机视觉和图像处理中⽤来进⾏物体检测的描述⼦。通过计算和统计局部区域的梯度⽅向直⽅图来构成特征。Hog特征结合SVM分类器已经被⼴泛应⽤于图像识别中,尤其在⾏⼈检测中获
得了极⼤的成功。
主要思想:在⼀幅图像中,局部⽬标的表象和形状能够利⽤梯度或边缘的⽅向密度分布来进⾏描述。其本质是梯度的统计信息,⽽梯度主要存在于边缘所在的地⽅。
算法优点:与其他的特征描述⽅法相⽐,HOG具有较多优点。由于HOG是在图像的局部⽅格单元上进⾏操作的,所以它对图像的⼏何和光学形变都能保持很好的不变性,这两种形变只会出现在更⼤的空间领域上。其次,在粗的空域抽样、精细的⽅向抽样以及较强的局部光学归⼀化等条件下,只要⾏⼈⼤体上能够保持直⽴的姿势,可以容许⾏⼈有⼀些细微的肢体动作,这些细微的动作可以被忽略⽽不影响检测效果。因此HOG特征特别适合于做图像中的⼈体检测。
实现流程:
步骤1-读取待检测的图⽚;
步骤2-将输⼊图像灰度化(将输⼊的彩⾊图像的r,g,b值通过特定公式转换为灰度值);
步骤3-采⽤Gamma校正法对输⼊图像进⾏颜⾊空间的标准化(归⼀化);
步骤4-计算图像中每个像素的梯度值(包括⼤⼩和⽅向),捕获轮廓信息;
步骤5-统计每个cell内的梯度直⽅图(不同梯度的个数),形成每个cell的特征描述⼦;
步骤6-将每⼏个cell组成⼀个block(以3*3为例),⼀个block内所有cell的特征串联起来得到该block的HOG特征描述⼦;
步骤7-将图像image内所有block块的HOG特征描述⼦串联起来得到该image(检测⽬标)的HOG特征描述⼦,这就是最终分类的特征向量。
三、SVM算法简介
  ⽀持向量机(support vector machines, SVM)是⼀种⼆分类模型,它的基本模型是定义在特征空间上的间隔最⼤的线性分类器,间隔最⼤使它有别于感知机;SVM还包括核技巧,这使它成为实质上的⾮线性分类器。SVM的的学习策略就是间隔最⼤化,可形式化为⼀个求解凸⼆次规划的问题,也等价于正则化的合页损失函数的最⼩化问题。SVM的的学习算法就是求解凸⼆次规划的最优化算法。具体的算法实现原理请参考。
四、基于HOG的⽬标检测算法训练流程
步骤1-从训练数据集中获取P个正样本块,并计算这P个正样本块的HOG特征描述⼦;
步骤2-从训练数据集中获取N个负样本块,并计算这N个负样本块的HOG特征描述⼦,其中N>>P;
步骤3-在这些正样本和负样本块上⾯训练⼀个SVM分类器模型;
步骤4-应⽤hard-negative-mining。对于负⾯训练集中的每个图像和每个可能的图像⽐例,在图像上⾯应⽤滑动窗⼝。在每个窗⼝中计算相应的HOG特征描述符并应⽤分类器。如果您的分类器(错误地)将给定窗⼝分类为⼀个对象(它将绝对存在误报),记录与误报补丁相关的特征向量以及分类的概率。这种⽅法被称为hard-negative-mining。具体效果如下图所⽰:
步骤5-⾸先获取使⽤hard-negative-mining技术获取到的错误的正样本块,然后按照概率值对它们进⾏排序;接着使⽤这些样本块重新训练分类器模型;
步骤6-将训练好的模型应⽤到测试图⽚中;
步骤7-对预测的结果使⽤NMS去除冗余的BB。
五、⽬标检测代码实现
训练代码如下所⽰,具体的训练数据集从下载,最终将会获得⼀个训练好的分类模型。
import cv2
import numpy as np
import random
def load_images(dirname, amout = 9999):
img_list = []
file = open(dirname)
img_name = adline()
while img_name != '':  # ⽂件尾
img_name = dirname.rsplit(r'/', 1)[0] + r'/' + img_name.split('/', 1)[1].strip('\n')
img_list.append(cv2.imread(img_name))
img_name = adline()
amout -= 1
if amout <= 0: # 控制读取图⽚的数量
break
return img_list
# 从每⼀张没有⼈的原始图⽚中随机裁出10张64*128的图⽚作为负样本
def sample_neg(full_neg_lst, neg_list, size):
random.ed(1)
width, height = size[1], size[0]
for i in range(len(full_neg_lst)):
for j in range(10):
y = int(random.random() * (len(full_neg_lst[i]) - height))
y = int(random.random() * (len(full_neg_lst[i]) - height))
x = int(random.random() * (len(full_neg_lst[i][0]) - width))
neg_list.append(full_neg_lst[i][y:y + height, x:x + width])
return neg_list
# wsize: 处理图⽚⼤⼩,通常64*128; 输⼊图⽚尺⼨>= wsize
def computeHOGs(img_lst, gradient_lst, wsize=(128, 64)):
hog = cv2.HOGDescriptor()
# hog.winSize = wsize
for i in range(len(img_lst)):
if img_lst[i].shape[1] >= wsize[1] and img_lst[i].shape[0] >= wsize[0]:
roi = img_lst[i][(img_lst[i].shape[0] - wsize[0]) // 2: (img_lst[i].shape[0] - wsize[0]) // 2 + wsize[0], \
(img_lst[i].shape[1] - wsize[1]) // 2: (img_lst[i].shape[1] - wsize[1]) // 2 + wsize[1]]
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
gradient_lst.pute(gray))
# return gradient_lst
def get_svm_detector(svm):
sv = SupportVectors()
rho, _, _ = DecisionFunction(0)
sv = np.transpo(sv)
return np.append(sv, [[-rho]], 0)
# 主程序
# 第⼀步:计算HOG特征
neg_list = []
pos_list = []
gradient_lst = []
labels = []
hard_neg_list = []
svm = cv2.ml.SVM_create()
pos_list = load_images(r'G:/python_project/INRIAPerson/96X160H96/Train/pos.lst')
full_neg_lst = load_images(r'G:/python_project/INRIAPerson/train_64x128_H96/neg.lst')
sample_neg(full_neg_lst, neg_list, [128, 64])
print(len(neg_list))
computeHOGs(pos_list, gradient_lst)
[labels.append(+1) for _ in range(len(pos_list))]
computeHOGs(neg_list, gradient_lst)
[labels.append(-1) for _ in range(len(neg_list))]
# 第⼆步:训练SVM
svm.tCoef0(0)
svm.tCoef0(0.0)
svm.tDegree(3)
criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 1000, 1e-3)
svm.tTermCriteria(criteria)
svm.tGamma(0)
svm.tKernel(cv2.ml.SVM_LINEAR)
svm.tNu(0.5)
svm.tP(0.1)  # for EPSILON_SVR, epsilon in loss function?
svm.tC(0.01)  # From paper, soft classifier
svm.tType(cv2.ml.SVM_EPS_SVR)  # C_SVC # EPSILON_SVR # may be also NU_SVR # do regression ain(np.array(gradient_lst), cv2.ml.ROW_SAMPLE, np.array(labels))
# 第三步:加⼊识别错误的样本,进⾏第⼆轮训练
# 参考 /article/SVM-HOG-HardExample/
hog = cv2.HOGDescriptor()
hard_neg_list.clear()
hog.tSVMDetector(get_svm_detector(svm))
for i in range(len(full_neg_lst)):
rects, wei = hog.detectMultiScale(full_neg_lst[i], winStride=(4, 4),padding=(8, 8), scale=1.05)
for (x,y,w,h) in rects:
巨蟹金牛hardExample = full_neg_lst[i][y:y+h, x:x+w]
hardExample = full_neg_lst[i][y:y+h, x:x+w]
hard_neg_list.size(hardExample,(64,128)))
computeHOGs(hard_neg_list, gradient_lst)
[labels.append(-1) for _ in range(len(hard_neg_list))]
# 第四步:保存训练结果
hog.tSVMDetector(get_svm_detector(svm))
hog.save('myHogDector.bin')
测试代码如下所⽰。
import cv2
import numpy as np
hog = cv2.HOGDescriptor()大喝一声
hog.load('myHogDector.bin')
cap = cv2.VideoCapture(0)
while True:
ok, img = ad()
rects, wei = hog.detectMultiScale(img, winStride=(4, 4),padding=(8, 8), scale=1.05)
乌龟价格for (x, y, w, h) in rects:
cv2.imshow('a', img)
if cv2.waitKey(1)&0xff == 27:    # esc键
break
cv2.destroyAllWindows()
六、⾮极⼤值抑制(NMS)简介及代码实现
  对于⽬标检测算法⽽⾔,通常检测出的结果中会存在⼀些重复或者冗余的情况,即输出了多个可能是⼈脸的BB,那么我们通常都需要使⽤NMS技术来获得⼀个最准确的BB,下图展⽰了⼀个实例。
NMS的原理-NMS的本质是搜索局部极⼤值,抑制⾮极⼤值元素。
NMS的作⽤-当算法对⼀个⽬标产⽣了多个候选框的时候,选择 score 最⾼的框,并抑制其他对于改⽬标的候选框。
NMS的应⽤场景-⼀幅图中有多个⽬标(如果只有⼀个⽬标,那么直接取 score 最⾼的候选框即可)。
NMS的输⼊-算法对⼀幅图产⽣的所有的候选框,以及每个框对应的 score (可以⽤⼀个 5 维数组 dets 表⽰,前 4 维表⽰四个⾓的坐标,第 5 维表⽰分数),阈值 thresh。
NMS的输出-正确的候选框组(dets 的⼀个⼦集)。
# coding=utf-8
# 导⼊python包
import numpy as np
import cv2
def non_max_suppression_slow(boxes, overlapThresh):
# 如果输⼊为空,直接返回空列表
if len(boxes) == 0:
return []
# 初始化列表索引
pick = []
# 获取边界框的坐标值
x1 = boxes[:,0]
y1 = boxes[:,1]
x2 = boxes[:,2]
y2 = boxes[:,3]
# 计算边界框的区域⼤⼩并按照右下⾓的y坐标进⾏排序
己亥杂诗的意思
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = np.argsort(y2)
idxs = np.argsort(y2)
while len(idxs) > 0:
# 获取索引列表中的最后⼀个索引,将索引值添加到所选索引的列表中,然后使⽤最后⼀个索引初始化禁⽌显⽰列表。  last = len(idxs) - 1
i = idxs[last]
pick.append(i)
suppress = [last]
# 遍历索引列表中的所有索引
for pos in xrange(0, last):
# 获取当前的索引
j = idxs[pos]
# 查找边界框起点的最⼤(x,y)坐标和边界框终点的最⼩(x,y)坐标
xx1 = max(x1[i], x1[j])
yy1 = max(y1[i], y1[j])
xx2 = min(x2[i], x2[j])
yy2 = min(y2[i], y2[j])
画画的英文
# 计算边界框的宽和⾼
w = max(0, xx2 - xx1 + 1)
h = max(0, yy2 - yy1 + 1)
# 计算区域列表中计算的边界框和边界框之间的重叠率
overlap = float(w * h) / area[j]
# 如果它们具有较⼤的重叠率,则抑制掉它
if overlap > overlapThresh:
瑞士手表品牌大全
suppress.append(pos)
# 从禁⽌显⽰列表中的索引列表中删除所有索引
idxs = np.delete(idxs, suppress)
# 返回选择的边界框
return boxes[pick]
# 构建⼀个列表,其中包含将与其各⾃的边界框⼀起检查的图像
images = [
("audrey.jpg", np.array([
(12, 84, 140, 212),鞋带怎么洗
(24, 84, 152, 212),
(36, 84, 164, 212),
(12, 96, 140, 224),
(24, 96, 152, 224),
(24, 108, 152, 236)])),
("bksomels.jpg", np.array([
(114, 60, 178, 124),
(120, 60, 184, 124),
(114, 66, 178, 130)])),
("gpripe.jpg", np.array([
(12, 30, 76, 94),
(12, 36, 76, 100),
(72, 36, 200, 164),
(84, 48, 212, 176)]))]
# 循环遍历所有的图像
for (imagePath, boundingBoxes) in images:
# 读取图⽚并进⾏复制
print ("[x] %d initial bounding boxes" % (len(boundingBoxes)))
二年级上册应用题image = cv2.imread(imagePath)
orig = py()
# 遍历每⼀个矩形框并绘制它们
for (startX, startY, endX, endY) in boundingBoxes:

本文发布于:2023-05-13 15:14:25,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/614980.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:算法   训练   检测   计算   特征   图像   梯度   边界
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图