梯度直方图(Histogram of Gradients)

介绍

方向梯度直方图英语:Histogram of oriented gradient,简称HOG)是应用在计算机视觉和图像处理领域,用于目标检测的特征描述器。这项技术是用来计算局部图像梯度的方向信息的统计值。这种方法跟边缘方向直方图(edge orientation histograms)、尺度不变特征变换(scale-invariant feature transform descriptors)以及形状上下文方法( shape contexts)有很多相似之处,但与它们的不同点是:HOG描述器是在一个网格密集的大小统一的细胞单元(dense grid of uniformly spaced cells)上计算,而且为了提高性能,还采用了重叠的局部对比度归一化(overlapping local contrast normalization)技术。

思想

HOG描述器最重要的思想是:在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述。具体的实现方法是:首先将图像分成小的连通区域,我们把它叫细胞单元。然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。为了提高性能,我们还可以把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能对光照变化和阴影获得更好的效果。

优点

与其他的特征描述方法相比,HOG描述器有很多优点。首先,由于HOG方法是在图像的局部细胞单元上操作,所以它对图像几何的(geometric)和光学的(photometric)形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。其次,作者通过实验发现,在粗的空域抽样(coarse spatial sampling)、精细的方向抽样(fine orientation sampling)以及较强的局部光学归一化(strong local photometric normalization)等条件下,只要行人大体上能够保持直立的姿势,就容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。综上所述,HOG方法是特别适合于做图像中的行人检测的。 

实现

1)图像归一化

归一化图像的主要目的是提高检测器对光照鲁棒性,因为实际的人体目标可能出现的各种不同的场合,检测器,必须对光照不太敏感才会有好的效果。

2)利用一阶微分计算图像梯度

图像平滑 

对于灰度图像,一般为了去除噪点,所以会先利用离散高斯平滑模板进行平滑:高斯函数在不同平滑的尺度下进行对灰度图像进行平滑操作,Dalal等实验表明在下,人体检测效果最佳(即不做高斯平滑),使得错误率缩小了约一倍。不做平滑操作,可能原因:图像时基于边缘的,平滑会降低边缘信息的对比度,从而减少图像中的信号信息。

梯度法求图像梯度

一阶微分处理一般对灰度阶梯有较强的响应  

一阶微分:

对于函数f(x,y),在其坐标(x,y)上的梯度是通过如下二维列向量定义的: 

这个向量的模值由下式给出:

因为模值的计算开销比较大,一般可以按如下公式近似求解:

Dalal等人利用许多一阶微分模板进行求梯度近似值,但在实验中表明模板[-1,0,1]效果最好。

采用模板[-1,0,1]为例计算图像梯度以及方向,通过梯度模板计算水平和垂直方向的梯度分别如下:

其中,分别表示该像素点的水平,垂直梯度值。计算该像素点的梯度值(梯度强度)以及梯度方向

对于梯度方向的范围限定,一般采用无符号的范围,故梯度方向可表示为:

3)基于梯度幅值的方向权重投影

HOG结构

通常使用的HOG结构大致有三种:矩形HOG(简称为R-HOG),圆形HOG和中心环绕HOG。它们的单位都是Block(即块)。Dalal的试验证明矩形HOG和圆形HOG的检测效果基本一致,而环绕形HOG效果相对差一些。

矩形HOG块的划分:

一般一个块(Block)都由若干单元(Cell)组成,一个单元都有如干个像素点组成。

在每个Cell中有独立做梯度方向统计,从而以梯度方向为横轴的的直方图,前面我们已经提到过,梯度方向可取0度到180度或0度~360度,但dalal实验表明,对于人体目标检测0度~180度这种忽略度数正负级的方向范围能够取得更好的结果。然后又将这个梯度分布平均分成n个方向角度(orientation bins),每个方向角度范围都会对应一个直方柱。

根据Dalal等人实验,在人体目标检测中,在无符号方向角度范围并将其平均分成9份(bins)能取得最好的效果,当bin的数目继续增大效果改变不明显,故一般在人体目标检测中使用bin数目为9范围0~180度的度量方式。

Block中各个参数的最终选取:

对于人体对象检测,块的大小为3×3个单元格,单元格的大小为6×6个象素时,检测效果是最好的,错误率约为10%左右。块的大小为2×2个单元格,单元格大小为8×8个象素时,也相差无几。6-8个象素宽的单元格,2-3个单元格宽的块,其错误率都在最低的一个平面上。块的尺寸太大时标准化的作用被削弱了从而导致错误率上升,而如果块的尺寸太小时,有用的信息反而会被过滤掉。

在实际应用中,在Block和Cell划分之后,对于得到各个像区域中,有时候还会为了进行一次高斯平滑,但是对于人体目标检测等问题,该步骤往往可以忽略,实际应用效果不大,估计在主要还是去除区域中噪点,因为梯度对于噪点相当敏感。

对梯度方向的投影权重方式的选取: 

对于梯度方向的加权投影,一般都采用一个权重投影函数,它可以是像素点的梯度幅值,梯度幅值的平方根或梯度幅值的平方,甚至可以使梯度幅值的省略形式,它们都能够一定程度上反应出像素上一定的边缘信息。根据Dalal等人论文的测试结果,采用梯度幅值量级本身得到的检测效果最佳,使用量级的平方根会轻微降低检测结果,而使用二值的边缘权值表示会严重降低效果(约为5%个单位10-4FPPW(False Positives Per Window))。

4)HOG特征向量归一化

对block块内的HOG特征向量进行归一化。对block块内特征向量的归一化主要是为了使特征向量空间对光照,阴影和边缘变化具有鲁棒性。还有归一化是针对每一个block进行的,一般采用的归一化函数有以下四种:

在人体检测系统中进行HOG计算时一般使用L2-norm,Dalal的文章也验证了对于人体检测系统使用L2-norm的时候效果最好。

5)得出HOG最终的特征向量

3.HOG的应用:

主要用在object detection 领域,特别是行人检测,智能交通系统,当然也有文章提到把HOG用在手势识别,人脸识别等方面。

4.HOG与SIFT区别

HOG和SIFT都属于描述子,以及由于在具体操作上有很多相似的步骤,所以致使很多人误认为HOG是SIFT的一种,其实两者在使用目的和具体处理细节上是有很大的区别的。HOG与SIFT的主要区别如下:

① SIFT是基于关键点特征向量的描述。

② HOG是将图像均匀的分成相邻的小块,然后在所有的小块内统计梯度直方图。

③ SIFT需要对图像尺度空间下对像素求极值点,而HOG中不需要。

④ SIFT一般有两大步骤,第一个步骤是对图像提取特征点,而HOG不会对图像提取特征点。

5.HOG的优点:

HOG表示的是边缘(梯度)的结构特征,因此可以描述局部的形状信息

位置和方向空间的量化一定程度上可以抑制平移和旋转带来的影响

采取在局部区域归一化直方图,可以部分抵消光照变化带来的影响

由于一定程度忽略了光照颜色对图像造成的影响,使得图像所需要的表征数据的维度降低了。

而且由于它这种分块分单元的处理方法,也使得图像局部像素点之间的关系可以很好得到的表征。

6.HOG的缺点:

描述子生成过程冗长,导致速度慢,实时性差

很难处理遮挡问题

由于梯度的性质,该描述子对噪点相当敏感

方向梯度直方图(hog)

接下来讲一下计算图像的HOG特征描述符的具体步骤。

我们以下面这张图片为例(宽高为100x200):

1、图像预处理

可以对图像进行裁剪,并缩放到固定尺寸。

灰度处理是可选操作,因为灰度图像和彩色图像都可以用于计算梯度图,对于彩色图像,先对三通道颜色值分别计算梯度,然后取梯度值最大的那个作为该像素的梯度。

然后进行伽马矫正,调节图像对比度,减少光照对图像的影响(包括光照不均和局部阴影),使过曝或者欠曝的图像恢复正常,更接近人眼看到的图像。

伽马矫正公式:

f(x)=xγ

即输出图像是输入图像的幂函数,指数为 γ ​。

代码实现如下:

import cv2
import numpy as np
img = cv2.imread('gamma.jpg', 0)
img2 = np.power(img/float(np.max(img)), 1.5)

γ ​越大,图像越暗;为1时,表示没有变化。

2、计算梯度图

为了得到梯度直方图,那么首先需要计算水平和垂直梯度,这可以通过使用以下内核过滤图像来实现,分别用于计算水平梯度和垂直梯度。

我们可以使用内核大小为1的Sobel算子,来获得相同的结果。

关于Sobel计算梯度的详细内容,可以去看 这篇文章,本文不过多介绍了哈。

然后再计算x和y方向梯度的合梯度,包括幅值和方向:

g=gx2+gy2θ=arctangygx

注意:梯度方向会取绝对值,因此得到的角度范围是 [0,180°]。

代码如下:

import cv2
import numpy as np
​
# Read image
img = cv2.imread('runner.jpg')
img = np.float32(img) / 255.0  # 归一化
​
# 计算x和y方向的梯度
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)
​
# 计算合梯度的幅值和方向(角度)
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)

如下分别为x方向梯度图,y方向梯度图,梯度幅值图,梯度方向图:

在每个像素处,梯度有一个大小和一个方向。x方向梯度图会强化垂直边缘特征,y方向梯度图会强化水平边缘特征。这就使得有用的特征(轮廓)得到保留,无关不重要的信息被去除。

3、计算梯度直方图

在这一步,我们先把整个图像划分为若干个8x8的小单元,称为cell,并计算每个cell的梯度直方图。这个cell的尺寸也可以是其他值,根据具体的特征而定。

为什么我们要把图像分成若干个8x8的小单元?

这是因为对于一整张梯度图,其中的有效特征是非常稀疏的,不但运算量大,而且效果可能还不好。于是我们就使用特征描述符来表示一个更紧凑的特征。一个8x8的小单元就包含了8x8x2 = 128个值,因为每个像素包括梯度的大小和方向。

现在我们要把这个8x8的小单元用长度为9的数组来表示,这个数组就是梯度直方图。这种表示方法不仅使得特征更加紧凑,而且对单个像素值的变化不敏感,也就是能够抗噪声干扰。

我们来看一下图片中的一个cell中的梯度:

中间那张图中的箭头表示梯度,箭头方向表示梯度方向,箭头长度表示梯度大小。

右图是 8×8 的cell中表示梯度的原始数字,注意角度的范围介于0到180度之间,而不是0到360度, 这被称为“无符号”梯度,因为两个完全相反的方向被认为是相同的。

现在我们来计算cell中像素的梯度直方图,先将角度范围分成9份,也就是9 bins,每20°为一个单元,也就是这些像素可以根据角度分为9组。将每一份中所有像素对应的梯度值进行累加,可以得到9个数值。直方图就是由这9个数值组成的数组,对应于角度0、20、40、60... 160。

比如上面方向图中蓝圈包围的像素,角度为80度,这个像素对应的幅值为2,所以在直方图80度对应的bin加上2。红圈包围的像素,角度为10度,介于0度和20度之间,其幅值为4,那么这个梯度值就被按比例分给0度和20度对应的bin,也就是各加上2。

还有一个细节需要注意,如果某个像素的梯度角度大于160度,也就是在160度到180度之间,那么把这个像素对应的梯度值按比例分给0度和160度对应的bin。

将这 8x8 的cell中所有像素的梯度值加到各自角度对应的bin中,就形成了长度为9的直方图:

可以看到直方图中,0度和160附近有很大的权重,说明了大多数像素的梯度向上或者向下,也就是这个cell是个横向边缘。

现在我们就可以用这9个数的梯度直方图来代替原来很大的三维矩阵,即代替了8x8x2个值。

4、Block 归一化

HOG将8×8的一个区域作为一个cell,再以2×2个cell作为一组,称为block。由于每个cell有9个值,2×2个cell则有36个值,HOG是通过滑动窗口的方式来得到block的,如下图所示:

在前面的步骤中,我们基于图像的梯度对每个cell创建了一个直方图。

但是图像的梯度对整体光照非常敏感,比如通过将所有像素值除以2来使图像变暗,那么梯度幅值将减小一半,因此直方图中的值也将减小一半。 理想情况下,我们希望我们的特征描述符不会受到光照变化的影响,那么我们就需要将直方图“归一化” 。

在说明如何归一化直方图之前,先看看长度为3的向量是如何归一化的。

假设我们有一个向量 [128,64,32],向量的长度为 1282+642+322=146.64 ,这叫做向量的L2范数。将这个向量的每个元素除以146.64就得到了归一化向量 [0.87, 0.43, 0.22]

现在有一个新向量,是第一个向量的2倍 [128x2, 64x2, 32x2],也就是 [256, 128, 64],我们将这个向量进行归一化,你可以看到归一化后的结果与第一个向量归一化后的结果相同。所以,对向量进行归一化可以消除整体光照的影响。

知道了如何归一化,现在来对block的梯度直方图进行归一化(注意不是cell),一个block有4个直方图,将这4个直方图拼接成长度为36的向量,然后对这个向量进行归一化。

因为使用的是滑动窗口,滑动步长为8个像素,所以每滑动一次,就在这个窗口上进行归一化计算得到长度为36的向量,并重复这个过程。

5、计算HOG特征向量

终于可以计算整个图像的特征描述符了,每滑动一次,一个block就得到一个长度为36的特征向量,那会得到多少个特征向量呢?

比如上面这个图,将整幅图像划分成cell的个数为8x16,就是横向有8个cell,纵向有16个cell。每个block有2x2个cell的话,那么block的个数为:(16-1)x(8-1)=105。即有7个水平block和15个竖直block。

再将这105个block合并,就得到了整个图像的特征描述符,长度为 105×36=3780。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
方向梯度直方图Histogram of Oriented Gradients,HOG)是一种常用的像特征提取方法,在物体检测和识别中广泛应用。下面我将简单介绍如何使用MATLAB进行HOG特征提取。 首先,我们需要加载像,并将其转换为灰度。使用MATLAB的imread函数读取像,并将其转换为灰度像,可以使用rgb2gray函数实现。 然后,我们使用MATLAB的gradient函数计算像的水平梯度和垂直梯度。这可以通过以下代码实现: [dx, dy] = gradient(image_gray); 接下来,我们可以计算每个像素点的梯度幅值和梯度方向。可以使用以下代码实现: grad_magnitude = sqrt(dx.^2 + dy.^2); grad_direction = atan2(dy, dx); 然后,我们需要将像划分为小的区域(Cell)。每个Cell中包含多个像素点。例如,可以将像划分为16x16像素的Cell,可以使用MATLAB的mat2cell函数实现。 接下来,我们需要计算每个Cell中的梯度方向直方图。我们将梯度方向划分为多个方向的bins(例如8个bins),然后使用MATLAB的histcounts函数计算每个bin中梯度方向的数量。 最后,我们需要将所有Cell中的梯度方向直方图连接起来,形成最终的特征向量。可以使用MATLAB的reshape函数将所有直方图连接起来。 综上所述,通过上述步骤,我们可以使用MATLAB实现方向梯度直方图的特征提取。特征提取后的HOG向量可以用于物体检测和识别任务,例如使用支持向量机进行分类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值