- 什么是特征描述符
文章图片
【openCV【实践系列】2——OpenCV方向梯度直方图】
图1:提取-裁剪-resize过程 Dalal和Triggs的论文也提到了伽马校正作为预处理步骤,但性能提升很小,因此我们正在跳过这一步。 第2步:计算渐变图像 要计算HOG描述符,我们需要首先计算水平和垂直梯度; 毕竟,我们想要计算梯度的直方图。通过使用以下核来对图像进行滤波可以轻松实现这一点。
文章图片
图2:滤波核 在OpenCV中使用核大小为1的Sobel运算符,我们也可以获得相同的结果。
- # Python 梯度计算
- # 读图像
- im = cv2.imread('bolt.png')
- im = np.float32(im) / 255.0
- # 计算梯度
- gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
- gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)
文章图片
在opencv中可以使用cartToPolar函数来实现
- # Python 计算梯度大小和方向 (度为单位)
- mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)
文章图片
图3:左:x-梯度的绝对值 中:y-梯度的绝对值 右梯度的大小 请注意,x-gradient在垂直线上触发,y-gradient在水平线上触发。梯度的大小会随着强度的急剧变化而发生。当该区域光滑时,它们都不会产生。我故意省略了显示渐变方向的图像,因为以图像的方向传达的信息不会太多。 梯度图像删除了许多非必要信息(例如恒定的彩色背景),但突出显示了轮廓。换句话说,你可以查看梯度图像,并且仍然可以轻松地说出图片中有人。 在每个像素处,梯度具有幅度和方向。对于彩色图像,评估三个通道的梯度(如图3所示)。一个像素处的梯度的大小是三个通道的梯度的最大值,并且角度是对应于最大梯度的角度。 步骤3:计算8×8单元中梯度的直方图 在该步骤中,将图像分成8×8个单元,并计算每个8×8单元的梯度直方图。
文章图片
图4:HOG的8*8cell 我们将在一瞬间了解直方图,但在我们做之前让我们先了解为什么我们将图像分成8×8个单元格。使用特征描述符描述图像块的一个重要原因是它提供了紧凑的表现。8×8图像块包含8×8×3 = 192个像素值。此块的每个像素的梯度包含2个值(幅度和方向),最多可添加8x8x2 = 128个数字。到本节结束时,我们将看到如何使用9-bin直方图表示这128个数字,这些直方图可以存储为9个数字的数组。不仅表示更紧凑,计算块上的直方图使得这种表示对噪声更加鲁棒。个别的梯度可能有噪声,但超过8×8块的直方图使得表示对噪音的敏感性降低。 但为什么8×8块呢?为什么不是32×32?它是我们正在寻找的特征尺度的设计选择。HOG最初用于行人检测。行人照片中的8×8个cell缩放到64×128,足以捕捉有趣的特征(例如,脸部,头顶等)。 直方图的本质是一个由9个bin组成的数组或向量,每个bin对应于角度0,20,40,60 ... 160。 让我们看看图像中的一个8×8块,看看梯度的外观。
文章图片
图5:中:箭头表示RGB块和梯度 右:同一块中的数字表示梯度 如果你是计算机视觉的初学者,那么图像中心的信息非常丰富。它显示图像的块用箭头表示梯度-箭头显示梯度的方向,其长度显示幅度。注意箭头的方向如何指向强度变化的方向,幅度表示差异有多大。 在右侧,我们看到原始数字代表8×8单元格中的梯度,只有一个小差异-角度介于0和180度之间,而不是0到360度。这些被称为“无符号”梯度,因为梯度的负方向也由相同的数字表示。换句话说,一个梯度箭头和与其相对的180度的箭头被认为是相同的。但是,为什么不使用0 - 360度?根据经验,已经表明无符号梯度比行人检测的有符号梯度更有效。HOG的某些实例将允许你指定是否要使用带符号的渐变。 下一步是在这些8×8单元格中创建梯度直方图。直方图包含9个bin对应于角度0,20,40 ...... 160。 下图说明了该过程。我们正在寻找与上图相同的8×8块的梯度的大小和方向。基于方向选择bin,并且基于幅度选择投票(进入bin中的值)。让我们首先关注蓝色环绕的像素。它的角度(方向)为80度,幅度为2.所以它在第5个箱子中加2。使用红色环绕的像素处的梯度具有10度的角度和4的大小。由于10度是0到20之间的一半,因此像素的投票均匀地分成两个bin。 图6:梯度直方图 还有一个细节需要注意。如果角度大于160度,则介于160和180之间,我们知道角度包围0和180等效。因此,在下面的示例中,角度为165度的像素与0度箱和160度bin成比例。
文章图片
图7:梯度直方图示例 将8×8cell中的所有像素的贡献相加以创建9-bin直方图。对于上面的块,它看起来像这样
文章图片
图8:梯度直方图化 在我们的表示中,y轴是0度。你可以看到直方图在0度和180度附近有很多权重,这只是另一种说法,即块的梯度要么方向向上要么方向向下。 步骤4:16×16块标准化 在上一步中,我们基于图像的梯度创建了直方图。图像的梯度对整体光照很敏感。如果将所有像素值除以2则使图像变暗,则梯度幅度将改变一半,因此直方图值将改变一半。理想情况下,我们希望描述符与光照变化无关。换句话说,我们希望“标准化”直方图,以便它们不受照明变化的影响。 在我解释直方图是如何规范化之前,让我们看看长度为3的向量是如何规范化的。 假设我们有一个RGB颜色矢量[128,64,32]。这个向量的长度是
文章图片
。这也称为向量的L2范数。将该向量的每个元素除以146.64得到归一化向量[0.87,0.43,0.22]。现在考虑另一个向量,其中元素是第一个向量2 x [128,64,32] = [256,128,64]的值的两倍。你可以自己解决这个问题,看看规范化[256,128,64]会产生[0.87,0.43,0.22],这与原始RGB矢量的标准化版本相同. 现在我们知道如何规范化矢量,你可能会想到在计算HOG时可以简单地将9×1直方图归一化,就像我们对上面的3×1矢量进行归一化一样。这不是一个坏主意,但更好的想法是在更大尺寸的16×16块上进行标准化。16×16块具有4个直方图,它们可以连接形成36×1元素向量,并且可以按照3×1向量归一化的方式进行归一化。然后将窗口以8个元素进行移动,并在该窗口上计算归一化的36×1矢量,并重复该过程。 步骤5:计算HOG特征向量 为了计算整个图像块的最终特征向量,将36×1向量连接成一个大矢量。这个载体的大小是多少?让我们计算一下 1.我们有多少个16×16块的位置? 有7个水平位置和15个垂直位置,总共7 x 15 = 105个位置。 2.每个16×16块由36×1向量表示。所以当我们将它们全部连接成一个大向量时,我们得到一个36×105 = 3780维向量。 可视化方向梯度直方图 通常通过在8×8的cell中绘制9×1标准化直方图来可视化图像块的HOG描述符。如图8所示,你会注意到直方图的主导方向捕捉了人的形状,特别是在躯干和腿部周围。 不幸的是,没有简单的方法可视化OpenCV中的HOG描述符。
文章图片
图9:可视化方向梯度直方图 openCV【实践系列】2——OpenCV方向梯度直方图
https://bbs.easyaiforum.cn/forum.php?mod=viewthread&tid=672&fromuid=7332
(出处: 易学智能)
推荐阅读
- openCV【实践系列】7——面部标志检测
- openCV【实践系列】9——使用OpenCV进行非真实感渲染
- [python] X2Go上安装pycharm
- openCV【实践系列】6——使用OpenCV进行面部交换(换脸)
- 机器学习入门实战 -- Titanic乘客生还预测-易学智能GPU云
- openCV【实践系列】8——OpenCV中的颜色空间