高斯金字塔的构建步骤

article/2025/8/15 8:12:02

转自:
https://www.cnblogs.com/starfire86/p/5735061.html


SIFT(Scale-Invariant Feature Transform,尺度不变特征转换)在目标识别、图像配准领域具有广泛的应用,下面按照SIFT特征的算法流程对其进行简要介绍对SIFT特征做简要介绍。

高斯金字塔是SIFT特征提取的第一步,之后特征空间中极值点的确定,都是基于高斯金字塔,因此SIFT特征学习的第一步是如何建立的高斯金字塔。

明白几个定义:

高斯金字塔 对于高斯金字塔,很容易直观地理解为对同一尺寸的图像,然后进行不同程度的高斯平滑,这些图像构成高斯金字塔,这种是不对的,这描述的图像集合叫做一个八度。金字塔总要有个变“尖”的过程,真正的高斯金字塔要有个平滑以及下采样的过程,因此整个图像平滑以及下采样再平滑,构成的所有图像集合才构成了图像的高斯金字塔。

八度(octave) 简单地说八度就是在特定尺寸(长宽)下,经不同高斯核模糊的图像的集合。八度的集合是高斯金字塔。


为什么要构建高斯金字塔:

整个高斯金字塔,或者说是差分高斯金字塔是我们确定SIFT特征的基础,让我们首先想想高斯金字塔到底干了一件什么事情,他到底模仿的是什么?答案很容易确定,高斯金字塔模仿的是图像的不同的尺度,尺度应该怎样理解?对于一副图像,你近距离观察图像,与你在一米之外观察,看到的图像效果是不同的,前者比较清晰,后者比较模糊,前者比较大,后者比较小,通过前者能看到图像的一些细节信息,通过后者能看到图像的一些轮廓的信息,这就是图像的尺度,图像的尺度是自然存在的,并不是人为创造的。好了,到这里我们明白了,其实以前对一幅图像的处理还是比较单调的,因为我们的关注点只落在二维空间,并没有考虑到“图像的纵深”这样一个概念,如果将这些内容考虑进去我们是不是会得到更多以前在二维空间中没有得到的信息呢?于是高斯金字塔横空出世了,它就是为了在二维图像的基础之上,榨取出图像中自然存在的另一个维度:尺度。因为高斯核是唯一的线性核,也就是说使用高斯核对图像模糊不会引入其他噪声,因此就选用了高斯核来构建图像的尺度。

下图两幅图像是典型的图像高斯金字塔,这就是模仿的图像离你远去时在你视网膜上的成像,图像分别以动态方式表示。

高斯金字塔的构建步骤:

高斯金字塔的构建还是比较简单的,高斯卷积和是尺度变换的唯一的线性核。

高斯金字塔构建过程中,一般首先将图像扩大一倍,在扩大的图像的基础之上构建高斯金字塔,然后对该尺寸下图像进行高斯模糊,几幅模糊之后的图像集合构成了一个八度,然后对该八度下的最模糊的一幅图像进行下采样的过程,长和宽分别缩短一倍,图像面积变为原来四分之一。这幅图像就是下一个八度的初始图像,在初始图像图像的基础上完成属于这个八度的高斯模糊处理,以此类推完成整个算法所需要的所有八度构建,这样这个高斯金字塔就构建出来了。构建出的金字塔如下图所示:




什么是尺度空间:

以上已经从人视觉感知的角度让大家感性认识了“尺度”,上文也提到使用高斯核来实现尺度的变换,那么具体实现过程中,尺度体现在哪里?是如何量化的呢?怎么在高斯金字塔中,两个变量很重要,即第几个八度(o)和八度中的第几层(s),这两个量合起来(o,s)就构成了高斯金字塔的尺度空间。尺度空间也不难理解,首先一个八度中图像的长和宽是相等的,即变量o控制的是塔中尺寸这个尺度;区分同一个尺寸尺度下的图像,就需要s了,s控制了一个八度中不同的模糊程度。这样(o,s)就能够确定高斯金字塔中的唯一一幅图像了,这是个三维空间,两维坐标,一维是图像。

根据lowe的论文,(o,s)作用于一幅图像是通过公式

      

确定的。通过公式也可以看出,尺度空间是连续的,两个变量控制着δ的值,其中在第一个八度中有 1<(o+s/S)<=2 ,同理在第二个八度中有2<(o+s/S)<=3,以此类推,δ中的关键部分(o+s/S)部分是逐渐增大的(具体实现时,有些高斯金字塔中这个值是增大,但不是逐渐均匀增大,只能说是连续的)。 

 

上图中第一个八度的中图像的尺度分别是δ,kδ,k^2δ......,第二个八度的尺度分别是2δ,2kδ,2k^2δ........,同理第三个八度的尺度分别是4δ,4kδ,4k^2δ........。这个序列是通过下式来确定的:

所以每增加一级八度,δ都要扩大2倍,在一个八度中,k的上标s来区分不同的高斯核。


构建差分高斯金字塔

构建高斯金字塔是为了后续构建差分高斯金字塔。对同一个八度的两幅相邻的图像做差得到插值图像,所有八度的这些插值图像的集合,就构成了差分高斯金字塔。过程如下图所示,差分高斯金字塔的好处是为后续的特征点的提取提供了方便。

到这里,高斯金字塔构建的主要部分、关键点都弄好了,一些非常重要的认知就要呼之欲出了,下面解释整个空间的尺度连续性!这是差分高斯金字塔的重中之重!

尺度空间的连续性

这里注意,连续性的主语既不是高斯金字塔,也不是差分高斯金字塔,而是尺度空间。在弄清楚这个问题之前,我们还需要解决一个问题,即为什么高斯金字塔中每个八度有s+3幅高斯图像?s的意思是将来我们在差分高斯金字塔中求极值点的时候,我们要在每个八度中求s层点,通过lowe论文可知,每一层极值点是在三维空间(图像二维,尺度一维)中比较获得,因此为了获得s层点,那么在差分高斯金字塔中需要有s+2图像,好了,继续上溯,如果差分高斯金字塔中有s+2幅图像,那么高斯金字塔中就必须要有s+3幅图像了,因为差分高斯金字塔是由高斯金字塔相邻两层相减得到的。好了,到了这里似乎真相大白,但是我们上面的推导有一个致命的问题,我们上来就假设“我们要在每个八度中求s层点”,为什么要s层点呢?这才是这个小节的主题:是为了保持尺度的连续性!下面进行详细的分析:

以一个八度中的图像为例说明(此处最好结合OpenCV中金字塔构建部分的源码<下文已列出,可以参照>)

高斯金字塔和差分高斯金字塔那几个公式还要在这里贴出来一下:

高斯函数G对图像I的模糊函数:

高斯差分函数:

通过以上这两个公式,可以确定一个八度中(以第一个八度为例)高斯图像和差分高斯图像的尺度如下(以lowe论文为例,s=3,所以每个八度中会有3+3=6幅图像),每一幅图像的尺度也在图像标示了出来。

在lowe的论文中s=3,因此有

因此,当前八度中各高斯图像的尺度依次为:

σ,2^(1/3)σ,    2^(2/3)σ,     2^(3/3)σ,    2^(4/3)σ,     2^(5/3)σ;

    当前八度中各差分高斯图像的尺度依次为:

σ,2^(1/3)σ,    2^(2/3)σ,     2^(3/3)σ,   2^(4/3)σ。

同理,我们可以推断出,下一个八度中各高斯图像的尺度依次为:

2×σ,2×2^(1/3)σ,2×2^(2/3)σ,2×2^(3/3)σ,2×2^(4/3)σ,2×2^(5/3)σ;

 下一个八度中各差分高斯图像的尺度依次为:

2×σ,2×2^(1/3)σ,2×2^(2/3)σ,2×2^(3/3)σ,2×2^(4/3)σ。

可以观察到,其中红色标注数据所代表的层,是差分高斯金字塔中获得极值点的层,也就是说只有在这些层上才发生与上下两层比较获得极值点的操作。下面将这些红色数据连成一串:2^(1/3)σ, 2^(2/3)σ, 2^(3/3)σ,2×2^(1/3)σ,2×2^(2/3)σ,2×2^(3/3)σ......。发现了什么?对了,这些数据时连续的,我们通过在每个八度中多构造三幅高斯图像,达到了尺度空间连续的效果,这一效果带来的直接的好处是在尺度空间的极值点确定过程中,我们不会漏掉任何一个尺度上的极值点,而是能够综合考虑量化的尺度因子

所确定的每一个尺度!

下一个八度的第一幅图像如何确定这个问题,是上面问题(尺度空间的连续性)的延伸,我们可以通过反推OpenCV中这一部分的源代码,来理解这个问题。

当前八度中的第一幅图像是通过前一个八度的倒数第三幅图像得到。OpenCV这段源码有个很重要的问题:不同的八度间的尺度不是会有一个2的差异吗?为什么本部分源码并没有体现这一点,而是在对每一个八度处理中都是用相同的数组sig[]。首先明确一下sig数组内.存储的并不是一个绝对的模糊核,而是相对的模糊核,这一点很重要,既然是相对的模糊核,那么第一幅图像的核就很重要了,所以尺度的连续就看每个八度的第一幅图像了。
对于以下列出的高斯金字塔的构建过程来看,每个八度中的第一幅图像并没有一个2倍的尺度跃进过程。但是,这个2倍的跃进式隐含在整个高斯金字塔的构建过程中了!
再看倒数第三幅图像,这幅图像的尺度是2^(3/3)*δ,3/3=1,也就是说,在这个八度中,第一幅图像的尺度是δ,而倒数第三幅图像的尺度是2*δ,正好发生了一个2的跃进!这就是以这幅图像作为基准进行下采样的原因,如此的话,下一个八度的第一幅图像的初始尺度就是2*δ了。

这就是真相,这就是为什么选用倒数第三幅图像进行下采样的原因。

 

  1. void SIFT::buildGaussianPyramid( const Mat& base, vector<Mat>& pyr, int nOctaves ) const  
  2. {  
  3.     vector<double> sig(nOctaveLayers + 3);  
  4.     pyr.resize(nOctaves*(nOctaveLayers + 3));  
  5.     // precompute Gaussian sigmas using the following formula:  
  6.     //  \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2  
  7.     sig[0] = sigma;  
  8.     double k = pow( 2., 1. / nOctaveLayers );  
  9.     for( int i = 1; i < nOctaveLayers + 3; i++ )  
  10.     {  
  11.         double sig_prev = pow(k, (double)(i-1))*sigma;  
  12.         double sig_total = sig_prev*k;  
  13.         sig[i] = std::sqrt(sig_total*sig_total - sig_prev*sig_prev);  
  14.     }  
  15.     for( int o = 0; o < nOctaves; o++ )  
  16.     {  
  17.         for( int i = 0; i < nOctaveLayers + 3; i++ )  
  18.         {  
  19.             Mat& dst = pyr[o*(nOctaveLayers + 3) + i];  
  20.             if( o == 0  &&  i == 0 )  
  21.                 dst = base;  
  22.             // base of new octave is halved image from end of previous octave  
  23.             else if( i == 0 )/*每一个八度中第一幅图像的确定过程*/  
  24.             {  
  25.                   const Mat& src = pyr[(o-1)*(nOctaveLayers + 3) + nOctaveLayers];  
  26.                   resize(src, dst, Size(src.cols/2, src.rows/2), 0, 0, INTER_NEAREST);  
  27.             }   
  28.            else  
  29.            {  
  30.                     const Mat& src = pyr[o*(nOctaveLayers + 3) + i-1];   
  31.                     GaussianBlur(src, dst, Size(), sig[i], sig[i]);   
  32.            }  
  33.         }   
  34.      }  
  35. }  
  36. void SIFT::buildDoGPyramid( const vector<Mat>& gpyr, vector<Mat>& dogpyr ) const  
  37. {   
  38.         int nOctaves = (int)gpyr.size()/(nOctaveLayers + 3);  
  39.         dogpyr.resize( nOctaves*(nOctaveLayers + 2) );   
  40.         for( int o = 0; o < nOctaves; o++ )  
  41.         {   
  42.                for( int i = 0; i < nOctaveLayers + 2; i++ )   
  43.                {   
  44.                      const Mat& src1 = gpyr[o*(nOctaveLayers + 3) + i];   
  45.                      const Mat& src2 = gpyr[o*(nOctaveLayers + 3) + i + 1];   
  46.                      Mat& dst = dogpyr[o*(nOctaveLayers + 2) + i];   
  47.                      subtract(src2, src1, dst, noArray(), DataType<sift_wt>::type);   
  48.                }  
  49.         }  
  50. }  

 

以上SIFT源码均摘自OpenCV nonfree模块,lowe对SIFT拥有版权。




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

相关文章

图像处理(九)高斯金字塔及拉普拉斯金字塔

高斯滤波的核就是一个求平均值的卷积核 高斯金字塔也是一个高斯核&#xff0c;只是步长为2&#xff0c;卷积后图片缩小二倍。高斯金字塔的目的是在图像不同大小时可以获得不同的信息&#xff0c;比如说图像较小时可以获得轮廓&#xff0c;图像较大时可以获得细节 使用函数cv2.p…

OpenCV SIFT源码讲解——构建高斯金字塔

目录 一、构建方法 二、函数重要点注释 一、构建方法 高斯金字塔每层图像的尺度为&#xff1a;。理论上金字塔每层图像可以从原图做的高斯滤波得到。但是实际操作中&#xff0c;每组的第一张影像&#xff08;除第一组&#xff09;是上一组倒数第三张影像降采样得到&#xff0c…

OpenCV中的图像金字塔(高斯金字塔、拉普拉斯金字塔)

最近在看关于数字图像的知识点&#xff0c;目前在图像金字塔部分&#xff0c;实在是懒得用手作笔记了&#xff0c;就以其中比较出名的“高斯金字塔”和“拉普拉斯金字塔”为例&#xff0c;基于OpenCV的源代码作解析存个档&#xff1b;毕竟属于基础部分&#xff0c;以后有需要就…

python 高斯金字塔_Python OpenCV 之图像金字塔,高斯金字塔与拉普拉斯金字塔

Python OpenCV 365 天学习计划&#xff0c;与橡皮擦一起进入图像领域吧。 基础知识铺垫 学习图像金字塔&#xff0c;发现网上的资料比较多&#xff0c;检索起来比较轻松。 图像金字塔是一张图像多尺度的表达&#xff0c;或者可以理解成一张图像不同分辨率展示。 金字塔越底层的…

图像金字塔和高斯金字塔

一&#xff1a;图像金字塔 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。图像金字塔实际上是一张图片在不同尺度下的集合&#xff0c;即原图的上采样和下采样集合。金字塔的底部是高分辨…

opencv学习-高斯金字塔和拉普拉斯金字塔

图像金字塔 一个图像金字塔是由一系列的图像组成&#xff0c;最底下一张是图像尺寸最大&#xff0c;最上方的图像尺寸最小&#xff0c;从空间上从上向下看就像一个古代的金字塔。金字塔的底部是待处理图像的高分辨率表示&#xff0c;而顶部是低分辨率的近似。我们将一层一层的…

高斯金字塔与拉普拉斯金字塔的原理与python构建

转载自:https://zhuanlan.zhihu.com/p/94014493 高斯金字塔和拉普拉斯金字塔【1】在图像相关领域应用广泛&#xff0c;尤其是图像融合和图像分割方面。本文从理论和opencv实现两个方面对两种金字塔进行了介绍&#xff0c;并给出了二者的视觉效果。 1、高斯金字塔 在计算机视觉…

图像金字塔、高斯金字塔、拉普拉斯金字塔是怎么回事?附利用拉普拉斯金字塔和高斯金字塔重构原图的Python-OpenCV代码

图像金字塔是对图像进行多分辨率表示的一种有效且简单的结构。 一个图像金字塔是一系列以金字塔形状排列的分辨率逐步降低的图像。图像金字塔的底部是待处理图像的高分辨率表示&#xff0c;而顶部是低分辨率表示。 图像金字塔有什么作用&#xff1f; 图像金字塔常用于图像缩放…

高斯金字塔

1、为什么要构建高斯金字塔 高斯金字塔模仿的是图像的不同的尺度&#xff0c;尺度应该怎样理解&#xff1f;对于一副图像&#xff0c;你近距离观察图像&#xff0c;与你在一米之外观察&#xff0c;看到的图像效果是不同的&#xff0c;前者比较清晰&#xff0c;后者比较模糊&am…

系统集成项目管理工程师知识点

信息化知识 在这个学时里&#xff0c;将学习有关信息化的许多知识点&#xff0c;这些知识点的试题大多出现在上午试 题中。这引起知识点主要是&#xff1a; &#xff08;1&#xff09;信息与信息化的定义。 &#xff08;2&#xff09;国家信息化发展战略&#xff08;2006-2020&…

快速了解Scala技术栈

http://www.infoq.com/cn/articles/scala-technology/ 我无可救药地成为了Scala的超级粉丝。在我使用Scala开发项目以及编写框架后&#xff0c;它就仿佛凝聚成为一个巨大的黑洞&#xff0c;吸引力使我不得不飞向它&#xff0c;以至于开始背离Java。固然Java 8为Java阵营增添了一…

一篇博客带你掌握pytorch基础,学以致用(包括张量创建,索引,切片,计算,Variable对象的创建,和梯度求解,再到激活函数的使用,神经网络的搭建、训练、优化、测试)

一篇博客带你掌握pytorch基础&#xff0c;学以致用 1.将numpy的 ndarray对象转换为pytorch的张量 在 Pytroch 中&#xff0c;Tensor 是一种包含单一数据类型元素的多维矩阵&#xff0c;译作张量。熟悉 numpy 的同学对这个定义应该感到很熟悉&#xff0c;就像ndarray一样&…

AI题目整理

文章目录 1、网络配置时batchsize的大小怎样设置?过小和过大分别有什么特点?2、设置学习率衰减的原因?3、有哪些分类算法?4、分类和回归的区别?5、请描述一下K-means聚类的过程?6、训练集、测试集、验证集的作用?7、请讲解一下k折交叉验证?8、分类和聚类的区别?9、讲述…

【深度学习】对迁移学习中域适应的理解和3种技术的介绍

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 1 『如何理解域适应』 域适应是计算机视觉的一个领域&#xff0c;我们的目标是在源数据集上训练一个神经网络&#xff0c;并确保在显著不同于源数据集的目标数据集上也有…

协议模糊的堆叠式Seq2seq注意模型

摘要--通过生成大量异常数据作为程序的输入&#xff0c;模糊测试是发现软件漏洞的有效方法。很难自动模糊协议&#xff0c;因为必须手动构造一个满足协议规范的模板以生成测试用例。在本文中&#xff0c;我们建立了堆叠的seq2seq注意模型来自动生成协议测试用例。Seq2seq-atten…

【推荐收藏】3.5万字图解Pandas

文章目录 第一部分&#xff1a;Pandas 展示技术提升1. 排序2.按多列排序3. 添加一列4. 快速元素搜索5. 按列连接&#xff08;join&#xff09;6.按列分组7. 数据透视表8、Pandas速度 第二部分. Series 和 Index索引(Index)按值查找元素缺失值比较追加、插入、删除统计数据重复数…

层次分析法原理及应用案例

层次分析法是指将一个复杂的多目标决策问题作为一个系统&#xff0c;将目标分解为多个目标或准则&#xff0c;进而分解为多指标&#xff08;或准则、约束&#xff09;的若干层次&#xff0c;通过定性指标模糊量化方法算出层次单排序&#xff08;权数&#xff09;和总排序&#…

论文研读-AI4VIS-可视化推荐-VizML: 一种基于机器学习的可视化推荐方法

VizML: 一种基于机器学习的可视化推荐方法 1 论文概述1.1 摘要1.2 引言 2 问题陈述3 相关工作3.1 基于规则的可视化推荐系统3.2 基于机器学习的可视化推荐系统 4 数据4.1 Plotly介绍4.2 数据描述和分析&#xff0c;收集和清理4.2 数据特征提取4.3 设计选择提取 5 方法5.1 特征处…

《python数据分析与挖掘实战》笔记第3章

文章目录 第3章&#xff1a;数据探索3.1、数据质量分析3.2、数据特征分析3.2.1、分布分析3.2.2、对比分析3.2.3、统计量分析1.集中趋势度量2.离中趋势度量 3.2.4、周期性分析3.2.5、贡献度分析3.2.6、相关性分析1. 直接绘制散点图2. 绘制散点图矩阵3. 计算相关系数 3.3、python…

对迁移学习中域适应的理解和3种技术的介绍

域适应是计算机视觉的一个领域&#xff0c;我们的目标是在源数据集上训练一个神经网络&#xff0c;并确保在显著不同于源数据集的目标数据集上也有良好的准确性。为了更好地理解域适应和它的应用&#xff0c;让我们先看看它的一些用例。 我们有很多不同用途的标准数据集&#…