目标检测算法之HOG特征

article/2025/10/29 6:40:34

      HOG特征,即方向梯度直方图(Histogram of Oriented Gradient, HOG),是计算机视觉领域中用于目标检测的一种特征描述子。其通过计算图像部分区域的梯度信息,并进行统计梯度信息的直方图来构成特征向量。通常地,将HOG所提取到的特征向量喂入预训练好的SVM分类器,可实现图像识别的功能。HOG+SVM的思路在2005年CVPR上提出,在行人识别检测上表现出了很好的效果。

HOG特征核心思想

  1. 基于梯度:HOG特征用于目标检测,为了找到局部目标,寻找其轮廓是可行且必要的方法。一般来说,在物体的边缘部分才有比较明显的梯度(背景或物体内部色彩变化不明显,因此梯度也不明显),所以物体的表象与形状可以较好的被梯度描述。

  2. 特征描述子:特征描述子是一种图像特征的表示。在HOG里面,它可以将原来尺寸大小为 w ∗ h w*h wh的图像转化成为一个长度为n的向量,以此来保留原始图像中重要的信息(梯度),并且过滤掉一些不相关的信息(如背景)。例如在OpenCV的API中,一副64*128大小的图像,经过转化后变成一个长度为3780的向量(下文会有详细分析)

  3. 划分区域cell:将一副图像划分成若干个连通的小区域(一般为正方形),这些小区域成为细胞单元(cell)。一个cell中包含若干个像素点,如8*8。计算这个cell中每个像素点所对应的梯度,并构成方向梯度直方图,将每一个cell得到的直方图结合起来,即可得到特征描述器。

  4. 更大的区域block:为了消除光照和阴影对于图像的影响,需要在更大的区域内,对这些cell对应的直方图进行对比度归一化。

实现步骤

  1. 图像灰度化:若输入的图像是RGB三通道的图像,则首先需要将其转化为灰度图。

  2. Gamma矫正法:利用Gamma变换对 1 中得到的灰度图像进行标准化,以减少光照因素的影响。Gamma变换的公式如下:

    f ( I ) = I γ f(I) = I^{\gamma} f(I)=Iγ

    γ \gamma γ 此处可以取0.5等数值

  3. 计算每一个像素的梯度(梯度大小及方向):通常利用[-1,0,1]算子与原图像进行卷积,得到每个像素在水平方向的梯度;同时利用 [ − 1 , 0 , 1 ] T [-1,0,1]^T [101]T算子与原图像卷积,得到每个像素在竖直方向的梯度。利用两个方向的梯度的合成,得到总的梯度大小与方向,其计算公式如下:

    G x ( x , y ) = I ( x + 1 , y ) − I ( x − 1 , y ) G_{x}(x,y) = I(x+1,y) - I(x-1,y) Gx(x,y)=I(x+1,y)I(x1,y)

    G y ( x , y ) = I ( x , y + 1 ) − I ( x , y − 1 ) G_{y}(x,y) = I(x,y+1) - I(x,y-1) Gy(x,y)=I(x,y+1)I(x,y1)

    其中 G x G_{x} Gx G y G_{y} Gy 表示原图像在水平和竖直方向上的梯度, I I I代表数字图像的像素值,则对于点(x,y)来说,它的梯度计算公式如下:

    G ( x , y ) = G x ( x , y ) 2 + G y ( x , y ) 2 G(x,y) = \sqrt{G_{x}(x,y)^2 + G_{y}(x,y)^2 } G(x,y)=Gx(x,y)2+Gy(x,y)2

    θ ( x , y ) = tan ⁡ − 1 ( G y ( x , y ) G x ( x , y ) ) \theta (x,y) = \tan ^{-1}(\frac{G_{y}(x,y) }{G_{x}(x,y)} ) θ(x,y)=tan1(Gx(x,y)Gy(x,y))

    其中G表示梯度大小, θ \theta θ 表示梯度的方向。

    通过梯度的计算,我们不仅仅能够对于物体的边缘轮廓,纹理等特征进行捕捉,同时可以进一步减轻光照的影响。

  4. 为每个cell构建梯度直方图

    细胞单元中的每一个像素点,都为某个基于方向的直方图通道投票。

    假设一个cell中包含8*8个像素,则根据标号 3 中这64个像素值对应的梯度构建直方图:

    一个cell对应的直方图
    一般地,我们把直方图划分为9项(0-8),称之为9个bin,对应了9个梯度的方向区间。在每个像素的梯度中,梯度方向 θ \theta θ 的取值为 [ − 180 , 180 ] [-180,180] [180,180]。对于0-180度的梯度来说,将180度平分为9个区域(bin),即每个bin对应20度。因此,如果在这个cell中,有一个像素的梯度在20-40度之间,则直方图上对应标号为1的bin被投票,其数目就+1(先这么认为);同样的,如果有一个像素值在100-120度之间,则直方图上标号为5的bin的数值+1。

    那么梯度的方向用到了,梯度的大小怎么使用呢?其实我们发现,在找到梯度所对应的bin标号之后,加的这个数应该与梯度的的大小相关(不是简单的+1)。例如有个像素梯度方向为45度,大小为3。那么,应该在标号2上面+3。(也有说法是45度与40度相差5度,与60度相差15度,因此按照1:3的比例将梯度大小3加到对应的bin上面,感觉大同小异)

    类似的,对于梯度方向为-180 - 0的部分,先将其+180度以后,与正梯度方向同样计算。

    bin与其角度对应关系
    总结一下,就是对于每个8*8的cell,通过每个像素的梯度方向及大小进行直方图的构建。梯度方向决定了该像素为哪一个bin投票,而梯度的大小代表着投票权重的大小。

  5. 将cell组合成更大的块(block),进行块内归一化:

    为了进一步减轻光照对于梯度特征的影响,应当进行块内归一化操作。

    我们之前设定的cell的大小为 8 ∗ 8 8*8 88,在这里,假设一个block的大小为16*16。因此一个block包含 2 ∗ 2 2*2 22个cell。一个cell对应的特征是9维的,因此将一个块中的4个cell所对应的直方图串联起来,得到一个block对应的特征是36维。此时对于梯度强度做归一化处理,得到的向量成为HOG描述符。

  6. 关于HOG特征向量的维度

    对于一个128*64大小的图像,假设cell的大小为 8 ∗ 8 8*8 88,block的大小为 16 ∗ 16 16*16 1616,梯度被平均分为9个bin,窗口每次滑动的步长为8个像素值。那么横向滑动中,总共有 1 + ( 64 − 16 ) / 8 = 7 1+(64-16)/8 = 7 1+(6416)/8=7 个窗口;在纵向滑动中,总共有 1 + ( 128 − 16 ) / 8 = 15 1+(128-16)/8 = 15 1+(12816)/8=15 个窗口。对于每个cell,其特征向量对应9维;而对于每个cell,其HOG特征对应 9 ∗ 4 = 36 维 9*4=36维 94=36;对于要检测的整张图像来说,其HOG特征的维度为 36 ∗ 7 ∗ 15 = 3780 36*7*15 = 3780 36715=3780

  7. 通过以上六步的变换,我们从一张 128 ∗ 64 ∗ 3 128*64*3 128643(3表示channel)的图像中,提取到了一个3780维的向量。随后将该向量投入到与训练好的分类起(如SVM)中,就可以目标检测了。

总结

      本文简单介绍了HOG特征的基本原理。目前还处于学习阶段,如有不当的地方,欢迎一起讨论交流~

参考网站:

https://blog.csdn.net/liulina603/article/details/8291093

https://blog.csdn.net/chaipp0607/article/details/70888899


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

相关文章

目标检测的图像特征提取之(一)HOG特征

目标检测的图像特征提取之(一)HOG特征 zouxy09qq.com http://blog.csdn.net/zouxy09 1、HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描…

数据库连接池c3p0

简介 c3p0是用于创建和管理连接,利用“池”的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制、连接可靠性测试、连接泄露控制、缓存语句等功能。目前,hibernate自带的连接池就是c3p0。 本文将包含以下内容(因为篇…

springboot配置C3P0数据库连接池

一、项目基础 参考&#xff1a;Springbootmybatismysql8.0 二、依赖引入 <!--c3p0连接池--><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency>三、配…

spring配置c3p0连接池

现在对学习spring框架里面的知识进行下记录&#xff0c;本人菜鸡一枚&#xff0c;希望看到的大神不要嘲讽我。 对spring配置c3p0连接池进行操作并使用jdbcTemplate模板进行crud操作&#xff0c;之前使用的时候是导入jar包&#xff0c;常见c3p0-config.xml文件&#xff0c;在里…

Maven下C3P0连接池配置及使用

1.在pom.xml文件中导入jar包同时不要忘记jdbc包&#xff0c;否则会报错 <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency> <dependency><groupId…

Java使用C3P0连接池详解

什么是C3P0连接池: 开源的JDBC连接池&#xff0c;C3P0连接池是在程序操作数据库之前预先根据配置文件创建一定数量的连接&#xff0c;当线程需要时直接取走&#xff0c;缩短了创建连接的时间&#xff0c;当使用完毕后&#xff0c;释放连接后放回连接池&#xff0c;以此类推&…

C3P0连接池的配置与使用

一、连接池的作用: 连接池是将已经创建好的连接保存在池中,当有请求来时,直接获取连接池中的有效连接对数据库进行访问,省略了创建连接和销毁连接的过程。这样性能上得到了提高。 基本原理是这样的: (1)建立数据库连接池对象(服务器启动)。 (2)按照事先指定的参数…

java代码c3p0连接池配置,c3p0连接池acquireincrement属性配置详解

一、c3p0数据库连接池介绍 c3p0是应用在Java项目中企业开发中的一个常用的连接池,一般都会配合Java开发框架spring、Hibernate、Mybatis等整合使用,属于开源连接池中性能比较强劲并且受市场比较欢迎的数据库连接池。 之所以项目中会应用连接池,主要是因为我们应用JDBC操作数…

配置springboot使用c3p0连接池

为什么要使用c3p0? 使用springboot默认的数据源配置方式&#xff1a; spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://…

详解C3P0(数据库连接池)

一、基本定义 C3P0是一个开源的JDBC连接池&#xff0c;它实现了数据源与JNDI绑定&#xff0c;支持JDBC3规范和实现了JDBC2的标准扩展说明的Connection和Statement池的DataSources对象。 即将用于连接数据库的连接整合在一起形成一个随取随用的数据库连接池&#xff08;Connecti…

C3P0连接池的使用

C3P0连接池的使用 什么是连接池&#xff1f;C3P0连接池的使用什么是C3P0&#xff1f;环境准备手动配置主要步骤开始编写&#xff01; 采用配置文件的方式主要步骤开始编写&#xff01; 完整代码及运行结果 什么是连接池&#xff1f; 既然叫做池&#xff0c;那么连接池(Connect…

C3P0连接池配置文档

一、导入jar包 下载链接 二、配置文件 配置文件名称&#xff1a;c3p0-config.xml (固定) 配置文件路径&#xff1a;src (类路径) 配置文件内容&#xff1a;命名配置 <c3p0-config><!-- 命名的配置 --><named-config name"test"><!-- 连接数…

C3P0数据库连接池的配置

在pom.xml文件中导入jar包 <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version> </dependency> 在src目录下创建c3p0-config.xml文件 <c3p0-config><named-config …

C3P0连接池的基本配置与使用

上一期我写了一篇Druid连接池的基本配置与使用&#xff0c;今天我要介绍一下C3P0连接池的基本使用。因为是介绍基本使用&#xff0c;所以我打算用一个非常简单的java应用来教大家如何对C3P0连接池进行基本配和使用。所以你只要有jdbc和Java基础就能看懂这篇文章&#xff0c;并学…

Windows API编程(一)最基础的知识介绍:Windows编程基础

主要内容简介&#xff1a; 1. Windows 编程基础&#xff1a;开发环境和开发过程。 2. Windows事件驱动模型和消息机制。 3. Windows的资源&#xff1a;图标、光标、菜单、位图等。 4. Windows绘图&#xff1a;图形和文字的显示。 5. 对话框和控件。 6. 静态库和动态库。 …

通过一个最简单的程序入门Windows编程

一、最简单的程序 我们首先先一个最简单的Windows程序&#xff0c;功能是显示一个消息框&#xff0c;随便提示一些文字就可以了。 看一下代码&#xff1a; #include <Windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, in…

windows编程 线程局部存储(TLS)详解

文章目录 一、基本概念二、基本使用三、例子分析&#xff1a; 总结 一、基本概念 线程局部存储&#xff08;TLS&#xff09;&#xff0c;是一种变量的存储方法&#xff0c;这个变量在它所在的线程内是全局可访问的&#xff0c;但是不能被其他线程访问到&#xff0c;这样就保持…

windows编程入门

记录一下windows编程编写一个消息框&#xff0c;算是学习windows编程的入门级程序吧 以下代码来自&#xff1a;《windows游戏编程大师技巧&#xff08;第二版&#xff09;》 #include<Windows.h> #include<windowsx.h> #include<string> #include<sstre…

Windows编程捕获特定窗口及键盘鼠标消息模拟

Windows编程捕获特定窗口及键盘鼠标消息模拟 一、简介二、使用到的API简介三、获取Windows记事本的编辑区窗口的句柄并模拟输入操作1、分析2、代码一3、代码二 四、后记 一、简介 窗口是Windows的核心组件&#xff0c;Windoows下的绝大部分应用都是利用Windows提供的原生窗口&…

【Windows编程】实时捕捉屏幕

实时捕捉屏幕 主要分为三个部分 获取屏幕 // 两个函数都可以进行位图复制&#xff0c;不过StretchBlt可以按照位图进行拉伸或者压缩 BitBlt(HDC hdc,int x,int y,int cx,int cy,HDC hdcSrc,int x1,int y1,DWORD rop); 或者 StretchBlt(HDC hdcDest,int xDest,int yDest,int …