文章目录
Hog(Histograms of Oriented Gradients,又称方向梯度直方图)概念出自于一篇2005年CVPR论文(Author:Navneet Dalal、Bill Triggs),内容为:使用HOG+SVM做行人检测
论文链接:Histogram of oriented gradients for human detection
由于它的巨大成功和可靠性,HOG 已成为计算机视觉中应用最广泛的目标检测算法之一。
Hog流程
Hog特征原理
1.梯度方向和模的计算
假设有这么一幅图片(gray格式),取出64*128大小的部分,通过选择其中的一个像素点及其周围的3x3区域,计算梯度和大小,如下:
A是像素点,周围的灰度值大小依次为32、20、30、64
g
x
=
30
−
20
=
10
g
y
=
64
−
32
=
32
g
=
g
x
2
+
g
y
2
g
y
=
64
−
32
=
32
θ
=
arctan
g
y
g
x
\begin{array}{ll} g_{x}=30-20=10 & g_{y}=64-32=32 \\ g=\sqrt{g_{x}^{2}+g_{y}^{2}} &g_{y}=64-32=32 \theta=\arctan \frac{g_{y}}{g_{x}} \end{array}
gx=30−20=10g=gx2+gy2gy=64−32=32gy=64−32=32θ=arctangxgy
所以,可以得到梯度长度/梯度方向
这里需要注意的是:梯度方向和图像边缘方向是互相正交的
2.计算cell的梯度直方图
经过上面的计算,我们知道每一个像素点都有两个值:梯度长度/梯度方向
我们将图像分为若干个的8x8的小单元(这里我们简称为cell
),并计算每个cell的梯度直方图。
我们来看一下图片中的一个cell中的梯度
-
我们先按第一步,计算出每一个像素点的梯度方向(G.Direction)和大小(G.Magnitude)
-
从图片中取出8x8的cell(中间那张图),箭头方向表示梯度方向,箭头长度表示梯度大小。在这里,
0°和180°的方向不考虑相反,视作同一方向
-
现在我们来计算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。
还有一个细节需要注意,如果某个像素的梯度角度大于20°,也就是在20°到40°之间,那么把这个像素对应的梯度值按比例分给20°和40°对应的bin
例如:某像素的梯度幅值为13.6,方向为36,36°两侧的角度bin分别为20°和40°,那么就按一定加权比例分别在20°和40°对应的bin加上梯度值
,加权公式为:
20°对应的bin:((40-36)/20) * 13.6,分母的20表示20等份,而不是20°;
40°对应的bin:((36-20)/20) * 13.6,分母的20表示20等份,而不是20°;
如果某个像素的梯度角度大于160°,也就是在160°到180°之间,那么把这个像素对应的梯度值按比例分给0°和160°对应的bin。如左下图绿色圆圈中的角度为165°,幅值为85,则按照同样的加权
方式将85分别加到0°和160°对应的bin中
这样,我们就得到了一个cell中的梯度直方图
x轴是角度的范围,而y轴是对应角度的加权幅度
3.block归一化
HOG特征将8×8的一个局部区域作为一个cell,再以2×2个cell作为一组,称为一个block,也就是说一个block表示16x16的区域
例:长度为3的向量是如何归一化的?
假设我们有一个向量 [128,64,32]
,向量的长度为146.64,这叫做向量的L2范数。将这个向量的每个元素除以146.64就得到了归一化向量 [0.87, 0.43, 0.22]
。
假设环境光照增强,那么会有一个新向量,是第一个向量的2倍 [128x2, 64x2, 32x2],也就是 [256, 128, 64]
,我们将这个向量进行归一化,你可以看到归一化后的结果与第一个向量归一化后的结果相同。所以,对向量进行归一化可以消除整体光照的影响
一个block有4个cell,一个cell有4个数值,所以一个block有36个数值
而block每一次只滑动一个cell的步长
这样,我们就大大压缩了图像的数据,仅保留这105个数据
这个特征描述符是一个一维的向量,长度为3780
理解直方图
下面分析一下上图的几个静态截图,看看所选单元格的直方图如何表示边缘?我们选取不同地方的单元格,并观察其直方图和Hog特征的缩放窗口
1.三角形内部
在这种情况下,由于三角形几乎都是相同的颜色,因此在所选单元格中不应存在任何主要梯度。 正如我们在缩放窗口和直方图中可以清楚地看到的那样,情况确实如此。 我们有很多渐变但没有一个明显地支配着另一个。
2.靠近水平边缘
边缘是图像中强度突然变化的区域。 在这些情况下某个特定方向上具有高强度的梯度。 这正是我们在所选单元格的相应直方图和缩放窗口中看到的内容。 在缩放窗口中可以看到主导梯度向上,几乎在90°,因为这是强度急剧变化的方向。 因此,我们应该期望直方图中的90°区域比其他区域更强。 这实际上就是我们所看到的。
3.靠近垂直边缘
在这种情况下,我们期望单元中的主导梯度是水平的,接近 180° ,因为这是强度急剧变化的方向。 因此,我们应该期望直方图中的 170° 区域比其他区域梯度影响更大。 这就是我们在直方图中看到的,但我们也看到单元中还有另一个主导梯度,即 10 度 bin 中的梯度。这是因为 HOG 算法使用无符号梯度,这意味着 0° 和 180° 被认为是相同的。 因此,当创建直方图时,160 度和 180 度之间的角度与 10 °(bin)和 170 °(bin)成比例(上文已提过)。 这导致在垂直边缘附近的单元中存在两个主要梯度而不是仅一个
4.靠近对角线边缘
为了理解我们所看到的,让我们首先记住梯度由 x 部分(分量)和 y 部分(分量)组成,就像向量一样。因此,梯度的最终方向将由其分量的向量和给出。因此,在垂直边缘上,渐变是水平的,因为它们只有 x 分量,如上图所示。在水平边缘上,渐变是垂直的,因为它们只有 y 分量,正如上上图所示。因此,在对角线边缘,梯度也将是对角线,因为 * x * 和 * y * 分量都是非零的。由于图像中的对角线边缘接近 45 °,我们应该期望在 50 °(bin)中看到显著的梯度方向。而这实际上就是我们在直方图中看到的,但是,如上图所示,我们看到有两个主导梯度而不是一个。其原因在于,当创建直方图时,靠近区间边界的角度与相邻区间成比例地起作用。例如,角度为 40 °的梯度位于 30 °和 50 °的中间。因此,梯度的大小均匀地分成30°和50°的bin。这导致在对角线边缘附近的单元中存在两个主要梯度而不是仅一个
Hog可视化
导入scikit-image
库
from skimage import feature,exposure
import cv2
image = cv2.imread('D:\opencv\CV\Haar\girl.jpg')
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
fd, hog_image = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),
cells_per_block=(2, 2), visualize=True)
hog_image_rescaled = exposure.rescale_intensity(hog_image,in_range=(0,10))
cv2.imshow('img',image)
cv2.imshow('hog',hog_image_rescaled)
cv2.waitKey()
cv2.destroyAllWindows()
注意事项
feature.hog()函数
rescale_intensity
是skimage.exposure.exposure 模块中的函数,在对图像进行拉伸或者伸缩强度水平后返回修改后的图像
参考资料
一文讲解方向梯度直方图(hog) - 知乎 (zhihu.com)
计算机视觉基础:HOG特征描述算⼦ - 知乎 (zhihu.com)
HOG 特征提取算法(实践篇) - Alex777 - 博客园 (cnblogs.com)