目录
简介
提取HOG特征的步骤
1、预处理获取要计算其特征的输入图像
2、计算图像的梯度
3、计算8×8细胞梯度直方图
4、直方图归一化
5、计算HOG特征向量
Opencv利用HOG特征实现行人检测
简介
HOG特征与SVM分类器结合,已经被广泛应用于图像识别中,尤其在行人检测,HOG的核心思想是所检测的局部物体外形能够被光强梯度或边缘方向的分布所描述。通过将整幅图像分割成小的连接区域,称为cells,每个cell生成一个方向梯度直方图或者cell中像素的边缘方向,这些直方图的组合可表示出所检测目标的目标的HOG特征。
提取HOG特征的步骤
具体计算图像HOG特征的方法步骤如下:
1、预处理获取要计算其特征的输入图像
图像调整为128x64像素的大小,该设置在行人检测任务中可以获得更好的结果。为了说明这一点,下面展示了一个大尺寸的512×480图像。我们选择一块大小100×200的区域计算我们的HOG特征。并且调整我们裁剪的窗口图像大小为64×128。
图 9-8 获得输入图像
2、计算图像的梯度
梯度是通过结合图像的大小和角度来获得的。考虑3x3像素的块,首先计算每个像素的
和
。对于每个像素值,首先使用以下公式计算
和
:
其中r为像素点的横坐标,c为像素点的纵坐标,
为图像像素点的像素值,在计算
和
后,使用下面提到的公式计算每个像素的梯度幅值和角度:
使用opencv中内核大小为1的Sobel算子实现计算图像的水平和垂直梯度,并计算每个像素的梯度和角度如下:
import cv2
#导入图片
img = cv2.imread("G:\workdate\python\demo\image\soccer2.bmp",0)
#计算水平和垂直梯度
gx=cv2.Sobel(img,cv2.CV_32F,1,0,ksize=1)
gy=cv2.Sobel(img,cv2.CV_32F,0,1,ksize=1)
#计算梯度图像与角度图像
m,arg=cv2.cartToPolar(gx,gy)
cv2.imshow("gx",gx)
cv2.imshow("gy",gy)
cv2.imshow("m",m)
cv2.imshow("arg",arg)
cv2.waitKey(0)
图 9-9 运行结果
如图9所示图水平梯度在垂直线方向延伸,垂直梯度在水平线方向延伸。
3、计算8×8细胞梯度直方图
8x16个大小为8x8的单元细胞(cell),如下图10所示。
图 9-10 8x8细胞单元
细胞的图像梯度的面貌。
图 9-11 细胞梯度与角度矩阵
上图显示了用箭头表示梯度的图像的贴片,箭头显示梯度的方向,其长度显示大小。注意箭头的方向指向强度的变化方向,其大小表示差异的大小。在右边,我们看到原始的数字表示在8×8细胞有一个小的差异,那就是角度是0度和180度的梯度,而不是0到360度之间。这些被称为“无符号”渐变,因为梯度正值和它的负值用相同的数字表示。换句话说,梯度箭头和与之相对的180度箭头被认为是相同的。但是,为什么不使用0 - 360度呢?经验表明,无符号梯度课要更好地用于行人检测。在计算HOG的一些实现方法中,将允许您指定是否使用带符号的渐变。下面我们创建一个8×8细胞梯度直方图。直方图包含9个数对应角度0, 20, 40…160,其实现过程如图12所示。
图 9-12 计算8×8细胞梯度直方图
如上图所示,我们寻找在8×8细胞梯度和方向矩阵同一位置的数值。根据方向选择箱子,并根据大小选择投票(进入箱子的值)。让我们首先关注环绕在蓝色中的像素。它的角度(方向)为80度,大小为2。所以它放入到第五个箱子。用红色包围的像素的梯度方向为10度,大小为4。由于10度是0和20之间的一半,所以像素的也是均匀地分成两个箱子。还有一个细节需要注意。如果角度大于160度,则在160到180之间,我们知道角度绕成0和180相等。比如角度为165度的像素正比于0度的箱子和160度的箱子。从180-165/165-160=3可知,梯度数值在分配时,0箱子分4/1,160箱子分4/3。
4、直方图归一化
在前面的步骤中,我们根据图像的梯度创建了一个直方图。图像的梯度对整体亮度是敏感的。如果通过将所有像素值除以2来使图像变暗,则梯度矩阵元素将改变一半,因此直方图值将改变一半。理想情况下,我们希望特征描述符不受光照变化的影响。换句话说,我们希望使直方图归一化,这样它们不会受到光照变化的影响。你可能会认为在计算HOG特征时可以将9x1的直方图直接看成的9×1矢量进行归一化。可以是可以,但更好的办法是归一化一个更大尺寸的16×16的图像块,而不是8×8的单元细胞矩阵大小。16×16图像块用4个直方图可级联成一个36×1元矢量,最后归一化36×1的向量。
5、计算HOG特征向量
计算整个图像的单元细胞后的最终的特征向量,36×1载体连接成一个巨大的载体。这个向量的大小是多少?原图截取100*200—>resize—>64*128,我们有多少个16×16图像块吗?有7个水平和15个垂直位置,总共105个16×16图像块。每16×16块由36×1矢量表示。所以当我们连接成一个巨大的载体,最后得到了36×105 = 3780维向量。
用opencv实现输入图像的HOG特征的可视化代码如下:
from skimage import feature, exposure
import cv2
image = cv2.imread('image/soccer2.bmp')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
fd, hog_image = feature.hog(image,orientations=3,pixels_per_cell=(8, 8), cells_per_block=(2, 2), block_norm='L2-Hys',feature_vector=True,visualize=True)
cv2.imshow('hog', hog_image)
cv2.waitKey(0)
图 9-13 hog特征可视化
HOG 是根据细胞单元格创建的,这些细胞单元格组合成区块,并且区块之间可以重叠,因此很难对它进行直观显示。不过可以通过显示每个单元格的直方图来表示HOG。如图14所示,显示方向直方图时,不使用柱状图,而是采用更加直观的星形图,每个线条的方向与 bin 对应,长度与 bin 的数量成正比。可以用这种方法在图像上绘制 HOG。
Opencv利用HOG特征实现行人检测
Opencv利用HOG特征实现行人检测,包括了HOG的特征提取和SVM识别两部分。利用OpenCV自带的行人检测其实现行人检测主要有三步:
- 初始化HOG描述子
- 设置HOG中的SVM为已训练好的SVM模型;
- 读取图像,检测,并在图像中显示出检测结果
使用opencv的自带的hog目标检测模型结合其训练好的SVM实现行人检测的代码如下:
import cv2
base_path = 'image/people.jpg'#待检测图像的文件路径
img=cv2.imread(base_path)
hog = cv2.HOGDescriptor() #初始化HOG描述子
# 设置支持向量机,其为一个预先训练好的行人检测器
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
#检测行人
rects, wei = hog.detectMultiScale(img, winStride=(4, 4), padding=(8, 8), scale=1.05)
for (x, y, w, h) in rects:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) #将检测结果在图像中圈出来
cv2.imshow("people detect", img) #显示图像
cv2.waitKey(0)
图 9-18 行人检测
如上图所示我们使用opencv自带模型很好的实现了图像中行人的检测,下面对我们用到的检测器进行简单的介绍。
cv2.HOGDescriptor():OpenCV中的HOG特征提取功能使用了HOGDescriptor这个类来进行封装。其中包含了许多函数,下面列举了常用的一些函数:
- getDetectorSize(self):获得设置的hog描述子的维数
- compute(self,,img,,winStride=None,padding=None, locations=None):计算输入的检测窗口的hog描述子
- computeGradient(self,,img,grad,angleOfs,paddingTL=None, paddingBR=None):计算输入图像的梯度幅度图像
- setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()):设置训练好的支持向量机检测器
- detectMultiScale(self,img,hitThreshold=None,winStride=None,padding=None,scale=None, finalThreshold=None, useMeanshiftGrouping=None):对输入图像进行检测,并且返回目标位置与目标的权重。