关于 HOG 代码 的一些解释

2024-06-01 07:48
文章标签 代码 解释 hog

本文主要是介绍关于 HOG 代码 的一些解释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文转自:http://hi.baidu.com/nokltkmtsfbnsyq/item/e1328f39b3abedb0623aff52  http://hi.baidu.com/nokltkmtsfbnsyq/item/6103f8b1fe9ed0e34ec7fd52 感谢原创作者~~

 

去年我做一个作业和调研的时候看了HOG的那篇论文,没怎么看明白,于是就求助于opencv的代码,结果是也没看明白。在网上做了一些求助后只好自己硬着头皮慢慢抠了两周,最后写了matlab的程序《Histograms of Oriented Gradients (HOG)特征 MATLAB 计算》,我的代码长的比较直白,但是干活不给力,很慢。大家问了一些问题,有一些比较类似,我总结了下将回答写成了这个文档。虽然我很想用图把问题描述清楚,但是可是用画图板和PHOTOSHOP三脚猫的功夫只能到这种程度了。还有就是,我不是做行人检测方向的。。。我只是碰巧碰了下HOG。。。

 

代码中处理globalinterpolate的情况是没有理解HOG的情况下写的,比原始HOG的想法简陋。Localinterpolate的情况是按照原始HOG实现的,是一种naïve实现方式.

 

关于计算梯度方向角的:

首先用[-1,0,1]梯度算子对原图像做卷积运算,得到x方向(水平方向,以向右为正方向)的梯度分量gradscalx,然后用[1,0,-1]’梯度算子对原图像做卷积运算,得到y方向(竖直方向,以向上为正方向)的梯度分量gradscaly。然后当gradscalx>=0, gradscaly>=0时,说明梯度方向是朝向第一象限的,当gradscalx>=0, gradscaly<0时,说明梯度方向是朝向第二象限的,诸如此类,结合象限信息,就可以利用反正切函数atan求出在signed和unsigned各自情况下正确的梯度角度.

 

关于扫描循环(四层for循环…有没有快一点的?有!但是我功力不够。。当时没编出来,就只好还是来四层for):

假设检测窗为64(列)*128(行)大小,block为16*16大小,每个block划分为4个cell,block每次滑动8个像素(也就是一个cell的宽),以及梯度方向划分为9个区间,在0~180度范围内统计,以下的说明都以上述假设为例.

btly与btlx分别表示block所在位置左上角点处的坐标。对于前述假设,一个检测窗内会有105个block存在,因此第一个block左上角的坐标是(1,1),第二个是(9,1)…,此行最后一个是block的左上角坐标是(49,1),然后下一个block就需要向下滑动8个像素,并回到最左边,此时的block左上角坐标为(1,9),接着block重新开始新的横向滑动…如此这般,在检测窗内最后一个block的坐标就是(49,113).

block每滑动到一个新的位置,就需要停下来计算它内部的那四个cell中的梯度方向直方图.(bj,bi)就是来存储cell左上角的坐标的(cell的坐标以block左上角为原点).

 (j,i)就表示cell中的像素在整个检测窗(64*128的图像)中的坐标.另外,我在程序里有个jorbj与iorbi,这在Localinterpolate的情况下(也就是标准的原始HOG情况),就是bj与bi.

 

关于hist3dbig:

这是一个三维的矩阵,用来存储三维直方图。最常见的一维的直方图是这个样子,

二维直方图呢?是这个样子,一个一个的柱子是一个统计bin,柱子的高低代表统计值的大小


三维直方图呢?是这个样子,立体的一个一个的小格子,每个小格子是一个统计bin, 小格子用来装统计值。以上面的例子,那么对一个block来说,它的直方图是下面这样的:

 

再来说线性插值,线性插值时,一个统计值需被“按一定比例分配”到这个统计点最邻近的区间中去,下面的图显示了一维直方图时,落在虚线标记范围内的统计点,它最近邻的区间就是标有红色圆点的两个区间

若是二维直方图,那落在如下虚线矩形中的统计点,周围的这四个统计区间就是它最近邻的区间。这个虚线矩形由四个统计区间各自的1/4组成。

三维直方图,对一个统计点来说,它的最近邻的区间有八个,如下图,可以想象一下,只有当这个统计点落在由如下八个统计区间各自的1/8组成的一个立方体内内时,这八个区间才是对统计点最近邻的。

统计时如何分配权重呢?以一维直方图简单说一下线性插值的意思,对于下面绿色小方点(x)的统计值来说,假设标红点的两个bin的中心位置分别为x1,x2,那么对于x,它的分配权重为左边bin: 1-(x-x1)/s, 即 1-a/s = b/s, 右边bin: 1-(x2-x)/s, 即1-b/s = a/s.

类似,那么对三维直方图来说,统计时的累积式(从Dalal的论文里截来的)就是:

上面,w 就是准备被分配的统计值。(x1,y1,z1)…共八个点表示八个统计区间的中心位置坐标,上式用h(x1,y1,z1)这样的标记来表示所要累积的统计区间。我在编程时就使用的这个式子,只不过我用bin的下标号来表示bin块,就像前面三维直方图示意中(binx=1,biny=2,binθ=9),不过在程序中θ轴是用z轴表示了。

                binx1 = floor((jorbj-1+cellpw/2)/cellpw) + 1;

                biny1 = floor((iorbi-1+cellph/2)/cellph) + 1;

                binz1 = floor((go+(or*pi/nthet)/2)/(or*pi/nthet)) + 1;

                binx2 = binx1 + 1;

                biny2 = biny1 + 1;

                binz2 = binz1 + 1;

这几句,就是用来计算八个统计区间中心点的坐标的。

 

 

在计算前面所讲的统计区间的中心坐标,分配权值之前,我为了处理边缘时程序简洁点,就给那个2*2*9的立体直方图外边又包了一层,形成了一个4*4*11的三维直方图(示意图如下),原来的2*2*9直方图就是被包在中间的部分。这样,在原来直方图里坐标为(binx=1,biny=2,binz=9)的bin,在新的直方图里坐标为(binx=2,biny=3,binz=10)。




对上面的4*4*11的直方图来个与xoy平面平行的剖面图:


粗实线框就是原三维直方图的剖面,也就是一个block,对于像落在粗实线框与粗虚线框之间的点,其最近邻区间是不够8个的,我为了写程序时省点脑力。。。,就用外扩了的这一圈bin,这样落在粗实线框与粗虚线框之间的统计点有了8个区间,用matlab编程时,那个四层for循环中的部分就只用把那八个累积公式写上,也不用判断是不是在落在像上面粗实线框与粗虚线框之间的那种区域。在程序中2*2*9的直方图为hist3d,4*4*11的直方图为hist3dbig.当在这个hist3dbig中计算都结束后,我把外层这一圈剥去,就是hist3d了。


有了这些准备,我就可以计算出当前像素点的梯度方向幅值应该往hist3dbig中的哪八个bin块累积了。binx1,biny1,binz1 在这里就是那个八个bin块之中离  当前要统计的像素点在直方图中对应的位置  最接近的bin块的下标。binx2,biny2,binz2对应就是最远的bin块的下标了。x1,y1,z1就是bin块(binx1,biny1,binz1)中心点对应的实际像素所在的位置(x1,y1)与梯度方向的角度(z1). 我仍然以原block(即没扩前的block)左上角处作为x1,y1的原点,因为matlab以1作为图像像素索引的开始,我把原点就认为是(1,1),那(1,1)左边外扩出来的部分,就给以0,-1,-2,-3…这样的坐标,向上也类似,如下图所示,(1,1)位置为红点所示,蓝点处坐标就是(-3.5,1).


 

扩展出来的绿块的下标是(binx=1,biny=1,binz1=1),由于像素坐标在红点处为(1,1),而黄块才是block的第一个cell,对应bin块的下标(2,2).因为下标设计的原因,我在求x1,y1,z1时减了1.5而非0.5.

                x1 = (binx1-1.5)*cellpw + 0.5;

                y1 = (biny1-1.5)*cellph + 0.5;

                z1 = (binz1-1.5)*(or*pi/nthet);

上面的式子中x1,y1还加了0.5,因为像素坐标是离散的,而第一个坐标总是从1开始,这样对如图中第一个cell的中心(黑点)处应该是4.5. z1没加0.5,是因为角度值是从0开始的,并且是连续的。

 

在signed(即梯度方向从0度到360度)情况下,因为实际上角度的投票区间是首尾相接环形的,若统计间隔是40度,那么0-40度和320-360度就是相邻区间,那么在4*4*11的直方图中,投给binz==11区间(相当于360-380度)的值应该返给binz==2(0-40度),投给binz==1区间的值应该返给binz==10区间,如4*4*11直方图中所示,对应在程序中就是

    if or == 2

        hist3dbig(:,:,2) = hist3dbig(:,:,2) + hist3dbig(:,:,nthet+2);

        hist3dbig(:,:,(nthet+1)) = hist3dbig(:,:,(nthet+1)) + hist3dbig(:,:,1);

    end

 

 

 

这篇关于关于 HOG 代码 的一些解释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1020402

相关文章

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

CSS自定义浏览器滚动条样式完整代码

《CSS自定义浏览器滚动条样式完整代码》:本文主要介绍了如何使用CSS自定义浏览器滚动条的样式,包括隐藏滚动条的角落、设置滚动条的基本样式、轨道样式和滑块样式,并提供了完整的CSS代码示例,通过这些技巧,你可以为你的网站添加个性化的滚动条样式,从而提升用户体验,详细内容请阅读本文,希望能对你有所帮助...

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT