深入浅出理解HOG特征---梯度方向直方图

article/2025/9/10 3:43:03

梯度方向直方图
原文路径:https://www.learnopencv.com/histogram-of-oriented-gradients/
最近在搞车牌识别的时候,训练样本去识别车牌的时候用到HOG特征。国外一篇文章让我受益良多

什么是特征描述符?
特征描述符是指通过提取有用的信息并抛弃无关的信息来表示这一张图片或者一张图片的一部分

典型地,特征描述符将大小宽度x高度x 3(通道)的图像转换为特征向量数组,长度n。例如:在HOG特征描述器的情况下,输入图像大小为64×128×3,输出特征向量长度为3780。


中间有一个循环装箱的过程
划分为8x8大小的图像补丁块处理,装到9个箱子(其中8x8、9 这些参数都是不固定的,但是是推荐的)
移动步伐:8个像素
width:64 /8 == 8 份
Height:128 /8 ==16份
用一个16x16的窗口来处理,可以包含4个8X8的图像补丁,那么处理一次会有得到49个箱子数据。循环处理
最后能循环 7
15=105次
105*36=3780个箱子数据,存储的是每个像素的梯度大小和梯度方向

记住,HOG特征描述符能够用其他的尺寸大小来计算,但是在下面的具体例子里为了让你更加容易理解相关概念,选择使用图像宽高:64×128,图像补丁 8x8 窗口 16X16 移动步长 8个像素

首先来了解什么是“有用的信息”、什么是“无关的信息”?我们需要明确知道“有用”是指对什么有用。
特征向量对查看图像是没有用的,但是,对于图像识别和目标检测这些任务是非常有用的。将这些算法生成的特征向量引入到支持向量机(SVM)等图像分类算法中,可以取得不错的效果。

但是,哪一种“特征”对分类任务才是真正有用的呢?让我们用一个例子来讨论这一点。 假设我们要建立一个物体检测仪,用来检测衬衫和大衣的纽扣。按钮是圆形的(在图像中可能看起来是椭圆的),通常有几个洞用于缝纫。 你可以在一个按钮的图像上运行一个边缘检测器,只需简单地观察边缘图像就可以很容易地判断它是否是一个按钮。在这种情况下,边缘信息是“有用的”,而颜色信息不是。 此外,该功能还需要有鉴别能力。例如,从图像中提取的良好特征应该能够分辨按钮和其他圆形物体,如硬币和汽车轮胎的区别。

在HOG特征描述器中,梯度方向(梯度)的分布(直方图)作为特征。 图像的梯度(x和y导数)是有用的,因为梯度的大小在边缘和拐角处(突然强度变化的区域)很大,而且我们知道边和角在物体形状上的信息比平面区域要多得多。

怎么去计算方向梯度直方图?
在这一节中,我们将深入研究计算HOG特征描述符的细节。为了说明每一步,我们将使用一个图像块。

步骤1:预处理

如前所述的HOG特征描述符用于行人检测,是在64×128片图像计算。当然,图像可能是任意大小的。通常在多个尺度上分析多个图像位置,唯一的限制是被分析的补丁具有固定的长宽比(纵横比)。在我们的例子中,补丁需要有一个长宽比为1:2。例如,他们可以100×200, 128×256,或1000×2000而不是101×205。

为了说明这一点,下面展示了一个大尺寸的720×475图像。我们计算我们的HOG特征描述符选择一块大小100×200。这个补丁被裁剪的图像并调整其大小以64×128。现在已经准备好计算这个图像补丁的HOG描述符了。

这里写图片描述

还有一个预处理步骤就是“伽玛校正”,但性能提升非常小,所以这里跳过该步骤。

步骤2:计算图像梯度

要计算一个HOG描述符,我们首先需要计算水平和垂直梯度;毕竟,我们要计算梯度直方图。通过用以下内核过滤图像很容易做到这一点。
这里写图片描述

我们可以在opencv中使用内核大小为1的Sobel算子实现同样的结果。

    // Read imageMat img = imread("F:/data/car/test1.jpg");img.convertTo(img, CV_32F, 1 / 255.0);// Calculate gradients gx, gyMat gx, gy;//对X梯度绝对值Sobel(img, gx, CV_32F, 1, 0, 1);//对Y梯度绝对值Sobel(img, gy, CV_32F, 0, 1, 1);

接下来,我们可以用下面的公式找到梯度的大小和方向

这里写图片描述

如果你是使用opencv,计算梯度的大小和方向可以使用函数carttopolar,如下所示。

	Mat mag, angle;//mag 坡度梯度 大小//mag就是大小 //angle就是方向cartToPolar(gx, gy, mag, angle, 1);

下图显示了梯度

这里写图片描述

注意,图x梯度在垂直线方向延伸,图y-梯度在水平线方向延伸。图坡度梯度在强度上有急剧的变化。当图片区域光滑时,都没有延伸。我故意遗漏了显示渐变方向的图像,因为作为图像显示的方向不能传达太多信息。

注意看图像的变化
渐变图像去除了许多非必要的信息(例如恒定的彩色背景),但突出显示了轮廓。换句话说,你可以看到渐变图像,并且很容易地辨别出图片中有一个人。

图x梯度 注意水平方向基本没有延伸
图y梯度 注意垂直方向基本没有延伸

这里写图片描述

步骤3:计算在8×8细胞梯度直方图

在这一步中,图像被分为8×8细胞和梯度直方图计算每个8×8细胞。

这里写图片描述

我们将学习了解在一瞬间的直方图,但是在我们去之前就让我们先了解为什么我们把图像分为8×8细胞。使用特征描述符描述图像补丁的一个重要原因是它提供了一个紧凑的表示。8×8图像补丁包含8x8x3 = 192像素值。这个补丁梯度每像素包含2个值(大小和方向),那就变成8x8x2 = 128个数。通过这一部分的最后我们会看到这128个数字是用9-bin直方图(可存储为长度9的数组,通俗地说是分别装到9个箱子里)表示。不仅是表示更简洁,计算在补丁直方图具有更强的健壮性。个别的颜色梯度可能有噪音,但用一个8x8图像补丁来表示梯度直方图对噪声不敏感,换句话说,就是受噪音影响不大。

但是什么是8x8图像补丁?为什么不是32x32?这是我们通过特征缩放来寻找到的明确的选择。HOG最初用于检测行人。在一张行人照片缩放到64×128,使用8×8细胞足以捕捉有趣的功能(如面部、头部的等)。

让我们看一个8×8补丁在图像梯度的面貌

这里写图片描述

中间的图像信息量是非常大的。它显示了用箭头表示梯度的图像的贴片,箭头显示梯度的方向,其长度显示大小。注意箭头的方向如何指向强度的变化方向,其大小表示差异的大小。

在右边,我们看到原始的数字表示在8×8细胞有一个小的差异,那就是角度是0度和180度的梯度,而不是0到360度之间。这些被称为“无符号”渐变,因为梯度正值和它的负值用相同的数字表示。换句话说,梯度箭头和与之相对的180度箭头被认为是相同的。但是,为什么不使用0 - 360度呢?经验表明,无符号梯度比签名梯度更好地用于行人检测。HOG的一些实现将允许您指定是否使用带符号的渐变。

下一步是创建一个8×8细胞梯度直方图。直方图包含9个箱子对应角度0, 20, 40…160。

下图说明了这个过程。我们正在前面的图寻找在同8×8补丁梯度的幅值和方向。根据方向选择箱子,并根据大小选择投票(进入箱子的值)。让我们首先关注环绕在蓝色中的像素。它的角度(方向)为80度,大小为2。所以它放入到第五个箱子。用红色包围的像素的梯度方向为10度,大小为4。由于10度是0和20之间的一半,所以像素的也是均匀地分成两个箱子。

这里写图片描述

还有一个细节需要注意。如果角度大于160度,则在160到180之间,我们知道角度绕成0和180相等。因此,在下面的例子中,角度为165度的像素正比于0度的箱子和160度的箱子。
从160-180
180-165/165-160=3
所以0箱子分4/1,160箱子分4/3

在8×8细胞中所有像素的贡献加起来创造9-bin直方图。对于上面的补丁,它看起来像这样

这里写图片描述

在我们的表示中,y轴是0度。你可以看到直方图在0度和180度附近占很大比重。

这里写图片描述

步骤4:16x16步块归一化

在前面的步骤中,我们根据图像的梯度创建了一个直方图。图像的梯度对整体亮度是敏感的。如果通过将所有像素值除以2来使图像变暗,则渐变幅度将改变一半,因此直方图值将改变一半。理想情况下,我们希望描述符不受光照变化的影响。换句话说,我们希望使直方图正常化(归一化),这样它们不会受到光照变化的影响。
在解释直方图是如何规范化之前,让我们看看长度为3的向量是如何规范化的。
这里写图片描述

例如:一个像素向量RGB【128,64,32】,向量的长度则为:sqrt{128^2 + 64^2 + 32^2} = 146.64
这也被称为向量的L2范数。将向量的每一个元素除以146.64得到归一化向量【0.87,0.43,0.22】,可以看到,归一化后的【256,128,32】将得到【0.87,0.43,0.22】可以看到归一化向量消除了规模。

现在我们知道了如何归一化一个矢量,你可能会认为在计算HOG特征时可以将9x1的直方图以上述的3×1矢量的方式归一化。可以是可以,但更好的办法是归一化一个更大尺寸的16×16块。16×16块用4个直方图可级联成一个36×1元矢量,使用3×1矢量归一化的方法。然后通过8像素的窗口移动(见动画)重复计算,归一化的36×1向量。

步骤5:计算HOG特征向量

计算整个图像补丁最终的特征向量,36×1载体连接成一个巨大的载体。这个向量的大小是多少?
原图截取100200—>resize—>64128
64/8=8
128/8=16
1、我们有多少个16×16块吗?有7个水平和15个垂直位置,总共7×15=105个块。
2、每16×16块由36×1矢量表示。所以当我们连接成一个巨大的载体,他们都得到了36×105 = 3780维向量。

定向梯度直方图的可视化

这里写图片描述

一个图像块的HOG特征描述符通常是通过在8×8组织的9×1归一化直方图可视化。见上图像。你会注意到,直方图的主导方向捕捉人的形状,特别是围绕躯干和腿。
不幸的是,没有简单的方法来可视化OpenCV的HOG描述符。

至此:翻译完成,英语水平有限,有错误的地方,希望不吝赐教。

笔者:
下一篇博客会用C++、Opencv、支持SVM向量机来训练提取HOG特征。


http://chatgpt.dhexx.cn/article/wCYpnYIo.shtml

相关文章

函数的梯度方向和切线方向_方向导数和梯度是什么?

原标题:方向导数和梯度是什么? 为什么梯度的方向是函数在该点的方向导数最大的方向,梯度的模是最大方向导数的值?大家在看复习全书时,有认真想过这个问题吗?小编在本文以二元函数为例详细讲解方向导数和梯度,并试图以尽可能通俗地语言回答上述问题。 1.梯度 首先看看二…

机器学习--什么是梯度?为什么梯度方向就是函数上升最快的方向?本文将给你解惑

本打算把梯度放在神经网络来讲,学习机器学习实战时发现用到梯度下降最优算法,所以就把这个知识点深入讲一下,等后面实战到神经网络时,直接复制这里的,这次讲解会深入讲解,简明易懂是目的,虽然网…

如何理解梯度方向是增长最快的方向

前言: 最近在看关于机器学习的书,里面提到了梯度下降算法,里面提到了梯度方向是增长最快的方向,虽然说很早之前就知道了这个概念,但是一直也没有仔细想过为什么,今天突然想弄懂这个问题,所以有…

什么是梯度?为什么梯度的方向总是指向函数值增大的方向?

闲谈 对于梯度这个概念,我是这样的, 学习时,正序:导数–>偏导数–>方向导数–>梯度,从导数开始一步一步学到梯度这个概念,脑子里想 着:“梯度这个玩意儿有什么用,得记下…

【梯度,方向导数,以及梯度方向为什么是函数增长最快的方向】

梯度,方向导数,以及梯度方向为什么是函数增长最快的方向 结论!!!多元函数的偏导数梯度的直观展示梯度与方向导数参考链接 结论!!! 对一元函数而言,梯度是标量&#xff0…

各种梯度下降法的简单理解

微分 如何看待微分的直观含义,有以下两种最普遍的理解: 1.函数图像中,某点的斜率 2.函数的变化率 单变量微分: 多变量微分(分别对多个变量求偏导数): 梯度 梯度其实就是变量偏导数的一般化…

AcWing 16. 替换空格

文章目录 AcWing 16. 替换空格AC代码 AcWing 16. 替换空格 本题链接:AcWing 16. 替换空格 本博客给出本题截图: AC代码 代码: class Solution { public:string replaceSpaces(string &str) {string res;for (auto x : str)if (x …

c++替换空格

请实现—个函数&#xff0c;把字符串s中的每个空格替换成”%20""。 示例1: 输入:s "we are happy ."输出:""Me%20are%20happy ." #define _CRT_SECURE_NO_WARNINGS //vs2017下使用strcpy #include <iostream> #include <string…

替换空格符

任务描述 本关任务&#xff1a;替换文本流中的空格符。 相关知识 参照第一关&#xff0c;第三关相关知识。 编程要求 在右侧编辑器中的 Begin-End 之间补充代码 &#xff0c;读入一行文本&#xff0c;将输入复制到输出&#xff0c;要求将其中连续的多个空格用一个空格代替…

~替换空格~

问题描述&#xff1a;请实现一个函数&#xff0c;将一个字符串中的空格替换成“%20”。 例如&#xff0c;当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 问题分析&#xff1a; 1.解决这道题应该关注的点&#xff1a; 1&#xff09;字符串的长度 2&…

替换空格

一、需求 请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 二、遍历法 2,1 思路分析 新建字符串临时变量str和temp&#xff0c;str初始化为空串&#xff1b;截取给定字符串s的每单个字串&#xff0c;若字串为空格&#xff0c;temp赋值为"%…

[字符串]替换空格

一、题目描述 原文链接&#xff1a;Offer 05. 替换空格 具体描述&#xff1a; 请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 示例 1&#xff1a; 输入&#xff1a;s “We are happy.” 输出&#xff1a;“We%20are%20happy.” 限制&#xff…

js 用replace替换空格 替换空格包含换行符 替换空格不包含换行符

第一种&#xff1a;替换所有的空格&#xff08;包含换行符&#xff09; let str 123AD asadf asadfasf\n adf\n let a str.replace(/\s/g," ") console.log(a) // 123AD asadf asadfasf adf 由上可看出是把所有空格替换为&nbsp&#xff1b;了&#xff0c;其中…

5. 替换空格

文章目录 剑指 Offer 05. 替换空格解法一&#xff1a;暴力解解法二&#xff1a;从后往前填充思想 第五题的扩展题&#xff1a;合并两个有序数组 LeetCode 8888. 合并两个有序数组解法一&#xff1a;暴力解解法二&#xff1a;从后往前填充思想 举一反三 剑指 Offer 05. 替换空格…

字符串中的空格替换

输入一个字符串&#xff0c;需要我们使用其他的字符替换空格字符。 例如&#xff1a;一个字符串&#xff1a;“We are happy.”&#xff0c;将其中的空格字符用%20替换。怎么做呢&#xff1f; **第一种思路&#xff1a;**暴力法则&#xff0c;就是直接遍历字符串&#xff0c;遇…

1.【刷爆LeetCode】替换空格(多方法、多思路解决)

大家好我是Liyuyue&#xff01; 接下来我会讲我刷的LeetCode好题用到的好思路、好方法分享给大家一起学习&#xff0c;如果大家在看的过程中还有好的方法&#xff0c;可以评论区或者直接找我继续讨论&#xff0c;感谢大家的支持~&#xff01; 我们先来看要求&#xff1a; 简要分…

学习笔记 - excel筛选分组

整理excel的时候&#xff0c;遇到一个分组功能筛选功能&#xff0c;原始excel内容如下&#xff1a; excel右上角有个筛选功能框 点击下拉列中的“筛选”&#xff0c;excel界面如下显示&#xff0c;标识可以进行筛选功能了&#xff0c;所有列都加入了筛选项目。 点击City Name下…

excel 分组计数

采用数据透视表的方法对数据进行分组技数 1.现在需要对 下表中各类型出现的次数进行统计。 2.选中区域点击数据透视表 3.首先&#xff0c;把类型拖到“值”和“行”中&#xff0c;需要注意的是在值中要选择“计数项&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

excel自动分组

1.将年龄分组&#xff08;设置步长&#xff09; 2.日期按照季度分组

excel 手动分组和自动分组

1某个类别下有多个条目&#xff0c;我们想打开折叠显示 方法一&#xff1a;一个个的设置分组 2方法二&#xff1a; 自动分级显示 上面的实现方式&#xff0c;还是直接使用excel的分组功能&#xff0c;只不过在处理过程中&#xff0c;会遇到组成员一个时&#xff0c;处理就会麻…