目标检测——方向梯度直方图

一、方向梯度直方图

1.1 实验介绍

  • 介绍方向梯度直方图
  • 图片转换为方向梯度直方图的流程
  • 通过 scikit-image 工具实现方向梯度直方图。
     

1.1.1 知识点

  • 方向梯度直方图的基本概念
  • 梯度的计算
  • 计算方向梯度直方图
  • 归一化
  • 使用 scikit-image 实现方向梯度直方图

 
 

1.2 什么是方向梯度直方图?

回顾:传统的目标检测流程可分为三个步骤

  1. 第一步是使用滑动窗口和图像金字塔从图片中选择一些区域
  2. 第二步是将选择出来的区域转化为人工设计的特征,可称为特征提取
  3. 第三步是将这些特征输入分类器进行分类

 
方向梯度直方图(Histogram of Oriented Gradients):

  • 以下简称 HOG
  • 就是一种人工设计的特征
  • 用来简化图像表述的特征描述符
  • 下图中左边的图片是一只猫,我们不仅可以看出猫身体上的特征、颜色、纹理,而且还能看到背景
  • 右边的图片是使用 HOG 来表示的图片
  • 除了可以看到图中能看出猫的外形,其他的细节包括背景几乎都被去除
  • 故右边的图片是左边图片的一种简化表示形式
    图片描述

HOG 可以用来表示物体的形状、外形特征

  • 将这些特征输入分类器就可以实现目标的分类

 
在传统的算法中,使用 HOG 描述图片:

  • 可以保留有用信息,剔除无用的信息
  • 这样不仅减少计算量,还使得分类器的效果更好

HOG 可以分为以下几个步骤

  1. 预先归一化
  2. 计算水平和垂直方向梯度
  3. 计算梯度直方图
  4. 区域(Blocks)归一化

 
 

二、方向梯度直方图流程

2.1 预先归一化(Normalization)

  • 在计算梯度前可对图片归一化(Normalization)处理
  • 归一化的目的:
    • 使所有的数值落入到统一的范围
    • 从而使算法能有更好的表现

在 HOG 的原论文中提到使用伽马矫正的方法处理输入图片,伽马矫正可以增加图像的对比度
但是在很多情况下,伽马矫正对提升算法效果不明显,

  • 我们可以跳过图片预先归一化,直接计算图片梯度。

 

2.2 计算梯度

2.2.1 水平方向和垂直方向上的梯度

前面提到可以不用预先对图片进行归一化,故可以说

  • HOG 特征是从计算图像水平方向和垂直方向上的梯度开始的。

  • 图像的梯度计算是使用卷积核对图像进行卷积操作

  • 例如:

    • 我们可以使用矩阵 [[-1, 0, 1]][[-1], [0], [1]] 分别与图像上的每个像素进行运算
    • 来获得水平和垂直方向上的梯度

G x = I × W x G_x = I \times W_x Gx=I×Wx
G y = I × W y G_y = I \times W_y Gy=I×Wy

  • 上面两个公式分别计算水平、垂直方向上的梯度 G x G_x Gx G y G_y Gy
  • 其中:
  1. I I I输入图片
  2. W x W_x Wx 表示水平方向的卷积核
  3. W y W_y Wy 表示垂直方向的卷积核
     
     
    下面两张图片给我们展示了经过梯度计算后的图片是什么样子
    图片描述
  4. 左图表示计算图片的水平梯度
  5. 右图表示计算图片的垂直梯度

相较于原始图片,两张图片中的信息减少了很多

  • 整个 HOG 的过程就是:逐步减少图片中的无用信息,只展示给我们感兴趣的特征
     

 
 

2.2.2 计算梯度的幅值和方向

  • 现在已经有了水平方向的梯度 G x G_x Gx 和垂直方向的梯度 G y G_y Gy

  • 接下来我们要计算梯度的幅值和方向
    计算梯度幅值和方向是为了进一步计算方向梯度直方图。

  • 两个公式分别计算每个像素的梯度幅值 G G G梯度方向 θ \theta θ
    G = G x 2 + G y 2 G = \sqrt {G_x^2 + G_y^2} G=Gx2+Gy2
    θ = arctan ⁡ G y G x \theta = \arctan \frac{G_y}{G_x} θ=arctanGxGy


 
下面左图是合并水平、垂直方向上的梯度获得的梯度幅值

  • 可以看到相较于水平、垂直方向上的图片,左图中猫的轮廓更清晰明显。
  • 右图表示图片中的梯度方向

图片描述


 

2.3 方向梯度直方图

2.3.1 平均分割

  • 现在我们已经有了梯度幅值 G G G梯度方向 θ \theta θ
  • 接下来我们就可以计算方向梯度直方图了。
     
    在计算方向梯度直方图之前:
  • 我们需要将图片分成若干个小方格(Cells)
  • 为避免歧义下文皆书写为 CellCells
    图片描述

上图是一张宽高为 649 × 385 649\times 385 649×385 的图片

  • 我们将其平均分割成若干个 Cells
  • 每个 Cell 内包含 8 × 8 8\times 8 8×8 个像素

所以:

  1. 图片的被分为 ⌊ 385 ÷ 8 ⌋ = 48 \lfloor 385\div8 \rfloor = 48 385÷8=48
  2. 图片的被分为 ⌊ 649 ÷ 8 ⌋ = 81 \lfloor 649\div8 \rfloor = 81 649÷8=81 份( ⌊ ⌋ \lfloor\quad\rfloor 表示向下取整)
  3. 整张图片 48 × 81 48\times 81 48×81 个 Cells。

 
 

2.3.2 构建方向梯度直方图

  • 至此我们已经将图片分成许多 Cells
     

对于每一个 Cell,使用 G G G θ \theta θ 来构建方向梯度直方图。

  1. 首先我们先选择梯度方向的范围
  • 梯度方向的范围可分为 **0 到 180 度(无符号)**和 0 到 360 度(有符号)
  • 通常使用 0 到 180 度的范围。
  1. 然后将 0 到 180 度的范围分成 9 个区间(bins)
    分别为 0 到 20 度,20 到 40 度, 40 到 60 度 …… 160 到 180 度。

 

每个像素都有一个梯度幅值和一个梯度方向

  • 所以方向梯度直方图的计算就是每个像素所对应的梯度方向落在 9 个区间中的哪一个
  • 那么该像素的梯度幅值就在该区间中累加

图片描述

上图是一个计算方向梯度图的例子

  • 对于红色方框中的像素
    1. 假设其中有些像素对应的梯度方向落在 0 到 20 区间
    2. 那么将这些像素对应的梯度幅值0 到 20 区间内进行累加
  • 同理其他区间也做同样的运算
  • 最终得到上图中右边的方向梯度直方图

同样地,整张图片中的所有 Cells 都用同样的方法计算方向梯度直方图。


 
 

2.4 区域(Blocks)归一化

  • 我们已经将图像分成若干个 Cells,并且计算了每个 Cell 的方向梯度直方图。
  • 接下来我们要对图像进行区域归一化处理

归一化的目的:

  • 是减少光照变化对图像梯度的影响。
     

2.4.1 什么是区域(Blocks)?

  • 首先我们先来介绍什么是区域(Blocks),为避免歧义下文皆书写为 BlockBlocks
  1. 前面我们将图像分成若干个 Cells,每个 Cell 内有若干个像素
  2. 类似地,一个 Block 是一块由若干个 Cells 组成的矩形。

图片描述
 

2.5 归一化

  • 对图像进行归一化的过程
    • 类似于前面实验学习的滑动窗口
    • 将一个 Block 从左向右、从上向下在图中滑动
    • 然后在每个 Block 区域内进行归一化计算。

 
在每个 Block 内有 2 × 2 2\times 2 2×2 个 Cells

  • 前面我们将梯度方向分为 9 个区间并为每个 Cell 计算了方向梯度直方图,故每个 Cell 有 9 个向量
  • 则在一个 Block共有 2 × 2 × 9 2\times 2\times 9 2×2×9 个向量

然后我们可以使用 L 1 L1 L1 范数或 L 2 L2 L2 范数对 Block 内的向量进行归一化

  • 其中使用 L 2 L2 L2 范数进行归一化的效果相对较好
  • 下面就是使用 L 2 L2 L2 范数归一化的公式

即 Block 内的每个向量除以由 Block 内所有向量计算得到的 L 2 L2 L2 范数

  1. 其中 v i v_i vi 表示 Block 内的向量
  2. ϵ \epsilon ϵ 的作用是防止出现分母为 0的情况,它是一个很小的值。
    图片描述

从上图中可以看出每一个 Cell 不止出现在一个 Block 内:

  • 也就是说一个 Cell 将被重复的用于归一化计算中
  • 这样做会看似比较冗余,但是会提高特征描述的表现
  • 最后对所有的 Block 完成归一化计算,合并所有获得的归一化后的向量
  • 这样我们就完成了图像的 HOG 特征化表示。
     

 
 

2.6 使用 Scikit-image 实现方向梯度直方图

以上所述的概念或公式也许没法在短时间内理解消化,但这并不影响我们接下来的实验

  • 因为 HOG 已经在现有的一些算法库中实现,所以我们完全不用花时间再去复现它。
  • 通过几行简单的代码来实现 HOG 算法。
     

2.6.1 Scikit-image

  • 从 Scikit-image 导入 featureexposure 模块。
    • feature 模块里存放着一些用于计算特征的算法
    • exposure 模块具有一些直方图处理的功能。
  • 我们还需要导入 cv2 模块用于图片的读取
from skimage import feature
from skimage import exposure
from matplotlib import pyplot as plt
import cv2

%matplotlib inline

 

接着使用 cv2.imread 函数读取图片

image = cv2.imread("pets.jpg")

 
 

2.6.2 feature.hog

  • 使用 feature.hog 用于计算图片的方向梯度直方图

该函数的参数意义如下所示:

  1. 第一个参数 image 表示输入图像
  2. orientations 表示要将梯度方向分成几个区间
    这里我们将梯度方向分为 9 个区间
  3. pixels_per_cell 表示 Cell 的尺寸
    • 即一个 Cell 中有几个像素,需要传递一个元组给该参数
    • 我们将 (8, 8) 传递给该参数。
  4. cells_per_block 表示每个 Block 的尺寸
    • 一个 Block 中有几个 Cells,这里需要传递一个元组给该参数
    • 我们将 (2, 2) 传递给该参数。
  5. transform_sqrt 表示伽马校正
    • 我们将 True 传递给该参数
    • 表示使用伽马校正预先对图片进行归一化处理。
  6. visualize 表示可视化
    • True 传递给该参数
    • 表示返回 HOG 图像
       
(o, hog) = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),
    cells_per_block=(2, 2), transform_sqrt=True, visualize=True)

该函数返回 2 个值:

  1. 第一个值 oHOG 图像的一维展开数组
  2. 第二个值 hog 表示返回一个高和宽同输入图像一样二维数组
    这个值可用于可视化方向梯度直方图

 

2.6.3 exposure.rescale_intensity

接下来我们使用 exposure.rescale_intensity调整的输入图片的像素值大小或像素强度

  • 因为获得的 hog 中的元素值都为被归一化了,所以这些值都比较小
  • 如果直接将这些值作为图像的像素值,那么该图像看起来像一张全黑图片
  • 我们需要用该函数将这些值拉伸到一个较大的范围
     
hog = exposure.rescale_intensity(hog, out_range=(0, 255))
hog = hog.astype("uint8")
hog[hog > 50] = 255

我们传递 2 个参数给该函数

  1. 第一个参数 hog 表示前面获取的可视化二维数组
  2. 第二个参数 out_range 表示将输入图片的像素强度拉伸到设定的范围
  • 这里我们将 hog 中的每个元素值拉伸到 (0, 255) 范围内。
  • 接下来我们使用 astype 方法将 hog 中的元素转换为 uint8 类型
  • 最后我们将 hog大于 50 的元素赋值为 255

 

  • 使用 plt.figure 创建画板
  • 参数 dpi=150 表示图像的分辨率设置为 150
  • 最后使用 plt.imshow 函数显示图片
plt.figure(dpi=150)
plt.imshow(hog, cmap = 'gray', aspect='auto')

图片描述

下图:

  • 左边图片是输入图片,右边是对输入图片使用 HOG 提取特征后的图片,
  • 可以看到相较于左边图片,右边图片仅保留了动物的外形特征
    图片描述

 
 

三、实验总结

  1. 学习了方向梯度直方图的基本概念
  2. 对图片使用 HOG 提取特征的几个关键步骤
  3. 通过调用算法库中的相关算法来对一张图片提取 HOG 特征

HOG 方法是传统目标检测算法中有名的方法。

  • 如何使用 HOG 特征提取特征并实现一个目标检测的小项目
  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HHHTTY-

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值