首页IT科技hog特征提取 opencv(【特征提取】Hog特征原理简介与代码实践)

hog特征提取 opencv(【特征提取】Hog特征原理简介与代码实践)

时间2025-06-15 03:02:05分类IT科技浏览6662
导读:前言 在【模式识别】SVM实现人脸表情分类一文中,我曾使用Hog特征+SVM的方式实现表情分类,但对于Hog特征的原理并未做深入整理。此篇将结合scikit-image来简单分析Hog特征的原理和维度关系。因为没看过原论文,因此自己的理解可能会有偏差,如有错误,欢迎评论区指正。...

前言

在【模式识别】SVM实现人脸表情分类一文中               ,我曾使用Hog特征+SVM的方式实现表情分类                     ,但对于Hog特征的原理并未做深入整理              。此篇将结合scikit-image来简单分析Hog特征的原理和维度关系                      。因为没看过原论文       ,因此自己的理解可能会有偏差               ,如有错误                     ,欢迎评论区指正       。

图像梯度

在进入到Hog之前       ,需要先了解图像中梯度的概念       。

以下图为例(图源:[1])        ,黑色像素点值为0                     ,白色像素点值为1              ,分别求X方向梯度和Y方向梯度        ,从后两幅图可以看出                      ,当箭头从0突变到1时              ,梯度为正值,图像中以白色边缘表示                      ,反之为负值                     ,以黑色的阴影表示                      。

更进一步,把X方向的梯度和Y方向的梯度进行融合               ,这样可以计算出每一个像素点的融合梯度大小和方向              。

例如                     ,上图中选择了一个像素点       ,其相邻位置的像素大小如宫格所示               ,X方向梯度大小为50                     ,Y方向梯度大小为50       ,那么其融合梯度大小为70.1        ,方向为45°       。

计算公式的数学表达如下[2]:

有了上面的概念之后                     ,下面进入到Hog特征提取的流程                      。

标准化gamma空间和颜色空间(Gamma/Colour Normalization)

标准化gamma空间和颜色空间是Hog特征提取的第一步              。

这一步主要做了3个操作:

1               、因为颜色信息影响不大              ,因此先转化为灰度图;

2                     、进行gamma校正:

gamma<1在高灰度值区域内        ,动态范围变小                      ,图像对比度降低              ,图像整体灰度值变大,显得亮一些;gamma>1在低灰度值区域内                      ,动态范围变小                     ,图像对比度降低,图像整体灰度值变小               ,变得暗淡[3]

校正公式如下:

校正的好处在于:能够有效地降低图像局部的阴影和光照变化

3       、对图像尺寸进行重新调整                     ,并让各像素进行归一化;

计算图像梯度

图像预处理之后       ,就要计算图中每一个像素点的梯度。之前已经给出了图像梯度的计算公式               ,但在实际使用中                     ,两个方向上的梯度分量可以用卷积的方式来快速计算                      。

x方向的梯度分量gradscalx:用[-1,0,1]梯度算子对原图像做卷积运算 y方向的梯度分量gradscaly:用[1,0,-1]梯度算子对原图像做卷积运算

为每个细胞单元构建梯度方向直方图

下面就需要引入一个细胞单元(Cell)的概念       ,这里Cell的尺寸可以自由设定        ,我这里以8 X 8 的尺寸为例                     ,如下图所示:

这张猫选自VOC2012数据集              ,我对其进行了一定的裁剪                      。

这里的8 X 8指代一个Cell中包含8 X 8个像素点        ,例如图中的网格                      ,每个网格代表一个像素点              ,对于每一个像素点可以计算出一个梯度值和方向。

下面就要统计每个Cell的梯度直方图,通常来说                      ,直方图是用来统计频率的              。这里也类似                     ,因此,需要先把360°角度进行分类                      。按照原作者的说法               ,分成9份效果最好       。于是就有了下面这张图[3]:

这里表示的是每一块为20°                     ,这里初次看可能会有个疑问:360°/9 = 40°       ,每一块是40°才对               ,为什么是20°呢?

这是由于角度只看了数值                     ,因此正角度和负角度的符号进行忽略       ,因此180°/9 = 20°

举个例子        ,第一个像素点梯度方向为45°                     ,40°<45°<60°              ,这样它就被划分到第三组              。

以此类推        ,统计一个Cell中每个像素点的角度                      ,就可以得到梯度方向直方图                      。

把细胞单元组合成大的块(block)              ,并归一化梯度直方图

下一步就要引入另一个新概念:块(block),一些博文中也称作窗口(windows)                      ,应该是同一个东西       。

还是拿这张猫图举例                     ,假设block的大小为2 X 2,那么就包含2 X 2个cell               ,所占据的尺寸为(16                     ,16)个像素       。

如图中的蓝框代表cell       ,黄框代表block               ,这里block的大小也是通过人为指定                      。

这样                     ,一个block内所有cell的特征向量串联起来便得到该block的HOG特征       ,同时        ,需要在块内进行归一化              。归一化的方法大致有四种:

根据原作者描述                     ,使用L2-Hys方法效果最好[3]       。

至于这里的大小设置              ,个人理解是和目标的尺寸有关                      。例如        ,行人检测的最佳参数设置是:3×3细胞/区间               、6×6像素/细胞                     、9个直方图通道[3]              。

移动block                      ,计算维度

下面就到最后一步              ,一张图里有多个像素,那么通过计算之后                      ,整张图的hog特征的维度是多少呢?

这里我们进入实践                     ,来通过实践来理解block是如何移动的。

首先导库,使用opencv和skimage

import cv2 from skimage.feature import hog

定义数据预处理过程               ,调整图片尺寸为256x256                     ,并将图片进行灰度化和归一化

def preprocessing(src): gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 将图像转换成灰度图 img = cv2.resize(gray, (256, 256)) # 尺寸调整g img = img/255.0 # 数据归一化 return img

提取Hog特征

img = cv2.imread("test.jpg") img_afterpro = preprocessing(img) image_features = hog(img_afterpro, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(16, 16), block_norm=L2-Hys)

这里有多个参数       ,主要的四个参数解释和默认取值如下:

orientations:方向数 pixels_per_cell:胞元大小 cells_per_block:块大小 block_norm:可选块归一化方法L2-Hys(L2范数)

这里图片的大小为(256,256)               ,cell的大小选择为(8,8)                     ,block设置为(16,16)       ,那么hog特征总的维度是多少呢?起初我的理解是多个block平铺整个图像        ,那么每个block大小为(8x16,8x16)=(128,128)                     ,即整幅图像有四个block              ,那么总维度应该是16x16x9x2x2=9216然而通过验证

image_features.shape

输出的实际维度应为665856        ,差得很远!

于是我想到了卷积神经网络中卷积核的滑动窗口的运动方式                      ,假设这里block也是以滑动窗口的方式进行运动              ,每次运动的步长为一个cell的宽度,如下图所示:

这里的block应该是(16,16)                      ,我这里为了作图方便                     ,仍保留为(2,2),旨在领会传达的意思                      。

如图所示               ,每个block计算完成之后                     ,向水平/垂直方向移动一个cell的宽度       ,这样前一部分的cell会和下一个block再次计算                      。

这样block总的个数可以这样计算:

水平方向block个数=(256-128)/8 + 1 =17

垂直方向block个数=水平方向block个数=17

那么总维度=16x16x9x17x17=665856

结果证实               ,该思路是正确的。

Reference

[1]https://www.bilibili.com/video/BV1dz411B7Rd

[2]https://blog.csdn.net/zouxy09/article/details/7929348

[3]https://blog.csdn.net/qq_37791134/article/details/81413758

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
jsp三元表达式(详解如何在JavaScript中使用三元运算符) 看新闻赚钱是真的吗,这个钱是谁出的(通过看新闻赚钱的软件是什么意思-普通人如何通过自媒体赚钱,中视频伙伴计划入门须知,你了解吗)