SIFT解析(一)建立高斯金字塔

2023-11-08

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

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

明白几个定义:

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

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

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

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

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


高斯金字塔的构建步骤:

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

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


什么是尺度空间:

以上已经从人视觉感知的角度让大家感性认识了“尺度”,上文也提到使用高斯核来实现尺度的变换,那么具体实现过程中,尺度体现在哪里?是如何量化的呢?怎么在高斯金字塔中,两个变量很重要,即第几个八度(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*δ了。

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

[cpp]  view plain copy
  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.     forint 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.     forint o = 0; o < nOctaves; o++ )  
  16.     {  
  17.         forint 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.         forint o = 0; o < nOctaves; o++ )  
  41.         {   
  42.                forint 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拥有版权。

SIFT金字塔构建完毕,需要在金字塔中寻找特征点了,请关注本博客SIFT系列下一篇文章:SIFT解析(二)特征点位置确定

(转载请注明作者和出处 :honpey  http://blog.csdn.net/wendy709468104/article/details/8639617 )



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SIFT解析(一)建立高斯金字塔 的相关文章

  • 使用 OpenCV 绘制固定的网格线集

    是否可以根据 OpenCV 示例文件中颜色检测示例的输出 在所有交叉点处绘制具有定义点的用户定义网格线 基本上 网络摄像头需要从您上方检测人的头部和肩膀 然后 当检测到一个人时 我需要网格线在那里 以便我能够知道在 x 轴和 y 轴 前额和
  • Opencv - Features2D + 单应性不正确的结果

    我在将检测到的物体的轮廓放置在正确的位置时遇到了一些问题 就好像坐标位于错误的位置一样 我将粗麻布设置为 2000 并过滤了小于最小距离 3 倍的匹配 任何帮助 将不胜感激 运行匹配和单应性的结果 代码示例如下 public static
  • OpenCV:处理每一帧

    我想使用 OpenCV 编写一个跨平台应用程序进行视频捕获 在所有示例中 我发现来自相机的帧是使用抓取功能进行处理并等待一段时间 我想处理序列中的每一帧 我想定义自己的回调函数 每次当一个新帧准备好处理时都会执行该函数 例如直播对于 Win
  • 如何使用 python cv2 api 将 xy 点格式化为 unactorPoints?

    我在格式化要传递给 unactorPoints 的 x y 点列表时遇到问题 opencv 2 4 1 该错误消息是 C 特定的 并抱怨点数组不是 CV 32FC2 类型 我不应该能够传入 Nx2 numpy 数组吗 import cv2
  • 将 RGB 转换为黑色或白色

    我如何在Python中获取RGB图像并将其转换为黑白图像 不是灰度 我希望每个像素要么是全黑 0 0 0 要么是全白 255 255 255 流行的 Python 图像处理库中是否有任何内置功能可以完成此任务 如果不是 最好的方法是循环遍历
  • 如何在没有 OpenCv Manager 的情况下运行 OpenCV 代码

    我正在使用 OpenCV4Android 版本 2 4 10 并在 Samsung Galayx GT I9300 上测试我的代码 我遇到的问题是 我必须从 Play 商店下载 Opencv Manager 以便我的 opencv 代码运行
  • 有没有办法检测图像是否模糊? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道是否有一种方法可以通过分析图像数据来确定图像是否模糊 估计图像清晰度的另一种非常简单的方法是使用拉普拉斯 或 LoG 滤波器并
  • Pyinstaller“无法执行脚本 pyi_rth_pkgres”并且缺少软件包

    这是我第一次在这里发布问题 因为我的大部分问题已经被其他人回答了 我正在 python 中开发 GUI 应用程序 并尝试使用 pyinstaller 将其打包到单个文件夹和 exe 中 以便于移植 目前 我使用 Windows 10 和 a
  • 如何计算立体视觉的基本矩阵

    我正在尝试编写一些代码来计算基本矩阵以确定立体图像之间的关系 我从大多数人推荐的 Hartley 和 Zisserman 书开始 但它没有任何实际示例 并且示例代码是在 MATLAB 中 而我没有 然后我切换到这个比较实用 里面有实际例子
  • 如何将图像从 np.uint16 转换为 np.uint8?

    我正在创建一个图像 image np empty shape height width 1 dtype np uint16 之后我将图像转换为 BGR 模型 image cv2 cvtColor image cv2 COLOR GRAY2B
  • 有人曾经在 MacOS 10.6 上使用过 OpenCV 和 Python 2.7 吗?

    在过去的 6 个月里 我一直断断续续地尝试让 OpenCV 在 MacOS 上与 Python 配合使用 每次有新版本发布时 我都会再次尝试并失败 我已经尝试过 64 位和 32 位 并且 xcode gcc 和 gcc 都是通过 macp
  • OpenCV Android - 无法解析相应的JNI函数

    我正在尝试按照此处概述的本教程使用 Opencv 设置 Android Studio https www youtube com watch v OTw GIQNbD8 https www youtube com watch v OTw G
  • MATLAB 教程中的 SIFT 实现

    我正在寻找 MATLAB 中的一些基本 SIFT 实现 我需要从第一原则来写它 另外 我正在寻找一些可以解释程序中发生的事情的内容 Vedali 的代码和 David Lowe 的代码超出了我的理解范围 如果您是 Matlab 用户 您一定
  • OpenCV 旋转图像而不裁剪澄清

    我想扩展这个主题 参考用户 Lars Schillingmann 给出的这个 SO 问题和接受的答案 在 C 中的 OpenCV 中旋转图像而不裁剪 https stackoverflow com questions 22041699 ro
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • OpenCV 读取视频文件时内存不足

    此示例从文件中读取视频cv2 VideoCapture在 python OpenCV 中内存不足 import cv2 cap cv2 VideoCapture file mp4 while True ret frame cap read
  • Android for OpenCV - 打开跟踪文件时出错,UnsatisfiedLinkError

    我对 Android 开发和 OpenCV 都是新手 我从 Android 下载了 OpenCV 库http sourceforge net projects opencvlibrary files opencv android http
  • 如何将 OpenCV 的测试框架与 CMake 结合使用?

    好像 OpenCV 有一个测试框架 https github com Itseez opencv tree ef91d7e8830c36785f0b6fdbf2045da48413dd76 modules ts include opencv
  • 在OpenCV中将YUV转换为BGR或RGB

    我有一个电视采集卡 其输入内容为 YUV 格式 我在这里看到了与此问题类似的其他帖子 并尝试尝试所述的所有可能的方法 但它们都没有提供清晰的图像 目前最好的结果是 OpenCVcvCvtColor scr dst CV YUV2BGR 函数
  • 如何使用Android opencv使图像的白色部分透明

    我无法链接超过 2 个网址 因此我将我的照片发布到此博客 请在这里查看我的问题 http blog naver com mail1001 220650041897 http blog naver com mail1001 220650041

随机推荐

  • scrapy爬取动态网页_基于scrapy的动态网页采集方案总结

    基于scrapy的动态网页采集一直是个难点 而且如果想达到工程级别的抓取 需要有个高效率的解决方案 我列出了几个曾经尝试过的方案和它们的特点 基于PyV8等脚本解析引擎 这类方案的原理是利用开源浏览器项目中的脚本解释引擎 实现相关脚本片段的
  • unity 切换camera 渲染层

    camera有个属性cullingMask 改变cullingMask就可以改变camera渲染层 在做GUI时特别有用 camera cullingMask 1 lt lt 8 渲染除了层8的所有层 camera cullingMask
  • Redis生存时间TTL

    文章目录 为什么要设置key生存时间 设置key的生存时间 访问key的生存时间 清除生存时间 毫秒级时间 为什么要设置key生存时间 设置key的生存时间 可以用于以下使用场景 在登录网站后 将用户session存储在内存 设置一个过期时
  • Second season fifteenth episode,How are Ross and Rachel doing

    Scene Chandler and Joey s apartment Joey and Chandler enter with Chandler covering his eyes and Joey leading him JOEY Al
  • y2第一章 初始mybatis的上机3_MyBatis3.2.x从入门到精通之第一章

    第一章 一 引言 mybatis是一个持久层框架 是apache下的顶级项目 mybatis托管到goolecode下 再后来托管到github下 百度百科有解释 二 概述 mybatis让程序将主要精力放在sql上 通过mybatis提供
  • 改进遗传算法的参数反演--实例复现(详细注释)

    目录 主函数 计算适应度大小 选择操作 论文中的竞争选择法 锦标赛选择法 交叉操作 论文中的离散交叉法 变异操作 论文中的非均匀变异法 生成测试数据 某次运行结果 主函数 清除变量 导入数据 clear clc load Data Crea
  • hihoCoder_1014

    include
  • 以 Animated Drawings APP 为例,用 TorchServe 进行模型调优

    内容导读 上节介绍了 TorchServe 模型部署调优的 5 个步骤 将模型部署到生产环境中 本节以 Animated Drawings APP 为例 实际演示 TorchServe 的模型优化效果 本文首发自微信公众号 PyTorch
  • C++中报错: E0289:没有与参数列表匹配的构造函数“Employee::Employee”实例的解决方案

    仅为学习笔记 大佬请跳过 解决 将构造函数代码中的char pName改为const char pName即可 背景 构造函数等成员函数全部都写了 仍出现这个报错 解决 将构造函数代码中的char pName改为const char pNa
  • 【机器学习期末总结】5-感知机

    分离超平面 随机梯度下降 对偶形式 感知机简介 感知机1957年由Rosenblatt提出 是神经网络与支持向量机的基础 感知机是二类分类的线性分类模型 输入是实例的特征向量 输出是实例的类型 1 1 感知机模型是一个分离超平面 感知机预测
  • Linux crontab命令 定时任务 用法详解以及no crontab for root解决办法

    一 Linux系统安装crontab服务 1 确认crontab是否安装 crontab l 如果报 command not found 就说明该crontab服务没有安装 如果报 no crontab for root 就说明已经安装cr
  • python------线程池的应用

    在python中经常会使用异步 线程池 进程池 解决io操作 在爬虫中并不建议使用进程池 消耗过大 目标 会使用线程池 1 导入 import time def demo1 for i in range 3 print f 我饿了 i ti
  • MVCC与BufferPool缓存机制

    今天学习了MVCC与BufferPool缓存机制 这里记录一下学习笔记 有错误 还望指出 文章目录 MVCC多版本并发控制机制 undo日志版本链与read view机制 Innodb引擎SQL执行的BufferPool缓存 MVCC多版本
  • 《前端》jQuery-ajax例子

    我的jQuery ajax的笔记 https blog csdn net bellediao article details 104239715 从其他博主那里截取的例子 并附有疑问解答 例1 将接口中的result字段绘制成表格
  • Windows官方Linux子系统C/C++开发环境搭建

    关于利用 Windows 10 适用于 Linux 的 Windows 子系统 WSL 安装 Linux 在 Windows 平台直接运行而不依赖虚拟机并通过 Visual Studio Code 在 Windows 平台直接开发并调试Li
  • 搜索+防抖

    搜索 防抖 1 以每时每刻这个项目为例 很多页面都有搜索功能 而且跳转的时同一个搜索页面 在完成搜索功能后 在返回原页面 需要一个唯一标识来记载 搜索 goSearch this router push path search query
  • 详解Python进程与线程

    一 进程 1 1 进程概念 进程是资源分配的最小单位 程序隔离的边界 CPU的时间片轮转 在不同的时间段切换执行不同的进程 但是切换进程是比较耗时的 就引来了轻量级进程 也就是所谓的线程 一个进程中包括多个线程 代码流 其实也就是进程中同时
  • 如何进行安全性测试?

    1 功能验证 功能验证是采用软件测试当中的黑盒测试方法 对涉及安全的软件功能 如 用户管理模块 权限管理模块 加密系统 认证系统等进行测试 主要验证上述功能是否有效 具体方法可使用黑盒测试方法 2 漏洞扫描 安全漏洞扫描通常都是借助于特定的
  • [Git]记录Git Rebase和PR经验

    1 Git Pull Request 大概说一下 PR这个操作是你作为一个collaborator切出来了一个分支 在上面做了某些操作 可能是协作开发 可能是优化等 在此之后希望owner把你的代码pull到某个分支 比如master 上的
  • SIFT解析(一)建立高斯金字塔

    SIFT Scale Invariant Feature Transform 尺度不变特征转换 在目标识别 图像配准领域具有广泛的应用 下面按照SIFT特征的算法流程对其进行简要介绍对SIFT特征做简要介绍 高斯金字塔是SIFT特征提取的第