`

【OpenCV】SIFT原理与源码分析:DoG尺度空间构造

 
阅读更多

《SIFT原理与源码分析》系列文章索引:http://blog.csdn.net/xiaowei_cqu/article/details/8069548

尺度空间理论


自然界中的物体随着观测尺度不同有不同的表现形态。例如我们形容建筑物用“米”,观测分子、原子等用“纳米”。更形象的例子比如Google地图,滑动鼠标轮可以改变观测地图的尺度,看到的地图绘制也不同;还有电影中的拉伸镜头等等……
尺度空间中各尺度图像的模糊程度逐渐变大,能够模拟人在距离目标由近到远时目标在视网膜上的形成过程。
尺度越大图像越模糊。

为什么要讨论尺度空间?

用机器视觉系统分析未知场景时,计算机并不预先知道图像中物体的尺度。我们需要同时考虑图像在多尺度下的描述,获知感兴趣物体的最佳尺度。另外如果不同的尺度下都有同样的关键点,那么在不同的尺度的输入图像下就都可以检测出来关键点匹配,也就是尺度不变性

图像的尺度空间表达就是图像在所有尺度下的描述。

 

尺度空间表达与金字塔多分辨率表达

 

高斯模糊

高斯核是唯一可以产生多尺度空间的核(《Scale-space theory: A basic tool for analysing structures at different scales》)。一个图像的尺度空间L(x,y,σ) ,定义为原始图像I(x,y)与一个可变尺度的2维高斯函数G(x,y,σ)卷积运算。

二维空间高斯函数:

尺度空间:

尺度是自然客观存在的,不是主观创造的。高斯卷积只是表现尺度空间的一种形式。

二维空间高斯函数是等高线从中心成正太分布的同心圆:

 

 

分布不为零的点组成卷积阵与原始图像做变换,即每个像素值是周围相邻像素值的高斯平均。一个5*5的高斯模版如下所示:

 

 


高斯模版是圆对称的,且卷积的结果使原始像素值有最大的权重,距离中心越远的相邻像素值权重也越小。
在实际应用中,在计算高斯函数的离散近似时,在大概距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。所以,通常程序只计算(6σ+1)*(6σ+1)就可以保证相关像素影响。

高斯模糊另一个很厉害的性质就是线性可分:使用二维矩阵变换的高斯模糊可以通过在水平和竖直方向各进行一维高斯矩阵变换相加得到。

O(N^2*m*n)次乘法就缩减成了O(N*m*n)+O(N*m*n)次乘法。(N为高斯核大小,m,n为二维图像高和宽)

其实高斯这一部分只需要简单了解就可以了,在OpenCV也只需要一句代码:

 

GaussianBlur(dbl, dbl, Size(), sig_diff, sig_diff);

我这里详写了一下是因为这块儿对分析算法效率比较有用,而且高斯模糊的算法真的很漂亮~

 

金字塔多分辨率

金字塔是早期图像多尺度的表示形式。图像金字塔化一般包括两个步骤:使用低通滤波器平滑图像;对平滑图像进行降采样(通常是水平,竖直方向1/2),从而得到一系列尺寸缩小的图像。

上图中(a)是对原始信号进行低通滤波,(b)是降采样得到的信号。

而对于二维图像,一个传统的金字塔中,每一层图像由上一层分辨率的长、宽各一半,也就是四分之一的像素组成:

多尺度和多分辨率

尺度空间表达和金字塔多分辨率表达之间最大的不同是:

  • 尺度空间表达是由不同高斯核平滑卷积得到,在所有尺度上有相同的分辨率;
  • 而金字塔多分辨率表达每层分辨率减少固定比率。
所以,金字塔多分辨率生成较快,且占用存储空间少;而多尺度表达随着尺度参数的增加冗余信息也变多。
多尺度表达的优点在于图像的局部特征可以用简单的形式在不同尺度上描述;而金字塔表达没有理论基础,难以分析图像局部特征。

DoG(Difference of Gaussian)


高斯拉普拉斯LoG金字塔

结合尺度空间表达和金字塔多分辨率表达,就是在使用尺度空间时使用金字塔表示,也就是计算机视觉中最有名的拉普拉斯金子塔(《The Laplacian pyramid as a compact image code》)。
高斯拉普拉斯LoG(Laplace of Guassian)算子就是对高斯函数进行拉普拉斯变换:

核心思想还是高斯,这个不多叙述。

高斯差分DoG金字塔

DoG(Difference of Gaussian)其实是对高斯拉普拉斯LoG的近似,也就是对的近似。SIFT算法建议,在某一尺度上的特征检测可以通过对两个相邻高斯尺度空间的图像相减,得到DoG的响应值图像D(x,y,σ)。然后仿照LoG方法,通过对响应值图像D(x,y,σ)进行局部最大值搜索,在空间位置和尺度空间定位局部特征点。其中:

k为相邻两个尺度空间倍数的常数。

上图中(a)是DoG的三维图,(b)是DoG与LoG的对比。

金字塔构建


构建高斯金字塔

为了得到DoG图像,先要构造高斯金字塔。我们回过头来继续说高斯金字塔~
高斯金字塔在多分辨率金字塔简单降采样基础上加了高斯滤波,也就是对金字塔每层图像用不同参数的σ做高斯模糊,使得每层金字塔有多张高斯模糊图像。金字塔每层多张图像合称为一组(Octave),每组有多张(也叫层Interval)图像。另外,降采样时,金字塔上边一组图像的第一张图像(最底层的一张)是由前一组(金字塔下面一组)图像的倒数第三张隔点采样得到。


以下是OpenCV中构建高斯金字塔的代码,我加了相应的注释:
// 构建nOctaves组(每组nOctaves+3层)高斯金字塔
void SIFT::buildGaussianPyramid( const Mat& base, vector<Mat>& pyr, int nOctaves ) const
{
    vector<double> sig(nOctaveLayers + 3);
    pyr.resize(nOctaves*(nOctaveLayers + 3));

    // precompute Gaussian sigmas using the following formula:
    //  \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2、
	// 计算对图像做不同尺度高斯模糊的尺度因子
    sig[0] = sigma;
    double k = pow( 2., 1. / nOctaveLayers );
    for( int i = 1; i < nOctaveLayers + 3; i++ )
    {
        double sig_prev = pow(k, (double)(i-1))*sigma;
        double sig_total = sig_prev*k;
        sig[i] = std::sqrt(sig_total*sig_total - sig_prev*sig_prev);
    }

    for( int o = 0; o < nOctaves; o++ )
    {
		// DoG金子塔需要nOctaveLayers+2层图像来检测nOctaves层尺度
		// 所以高斯金字塔需要nOctaveLayers+3层图像得到nOctaveLayers+2层DoG金字塔
        for( int i = 0; i < nOctaveLayers + 3; i++ )
        {
			// dst为第o组(Octave)金字塔
            Mat& dst = pyr[o*(nOctaveLayers + 3) + i];
			// 第0组第0层为原始图像
            if( o == 0  &&  i == 0 )
                dst = base;
            
			// base of new octave is halved image from end of previous octave
			// 每一组第0副图像时上一组倒数第三幅图像隔点采样得到
            else if( i == 0 )
            {
                const Mat& src = pyr[(o-1)*(nOctaveLayers + 3) + nOctaveLayers];
                resize(src, dst, Size(src.cols/2, src.rows/2),
                       0, 0, INTER_NEAREST);
            }
			// 每一组第i副图像是由第i-1副图像进行sig[i]的高斯模糊得到
			// 也就是本组图像在sig[i]的尺度空间下的图像
            else
            {
                const Mat& src = pyr[o*(nOctaveLayers + 3) + i-1];
                GaussianBlur(src, dst, Size(), sig[i], sig[i]);
            }
        }
    }
}

高斯金字塔的组数为:

代码10-17行是计算高斯模糊的系数σ,具体关系如下:

其中,σ为尺度空间坐标,s为每组中层坐标,σ0为初始尺度,S为每组层数(一般为3~5)。根据这个公式,我们可以得到金字塔组内各层尺度以及组间各图像尺度关系。
组内相邻图像尺度关系:

相邻组间尺度关系:

所以,相邻两组的同一层尺度为2倍的关系
最终尺度序列总结为:

o为金字塔组数,n为每组金字塔层数。

构建DoG金字塔

构建高斯金字塔之后,就是用金字塔相邻图像相减构造DoG金字塔。



下面为构造DoG的代码:
// 构建nOctaves组(每组nOctaves+2层)高斯差分金字塔
void SIFT::buildDoGPyramid( const vector<Mat>& gpyr, vector<Mat>& dogpyr ) const
{
    int nOctaves = (int)gpyr.size()/(nOctaveLayers + 3);
    dogpyr.resize( nOctaves*(nOctaveLayers + 2) );

    for( int o = 0; o < nOctaves; o++ )
    {
        for( int i = 0; i < nOctaveLayers + 2; i++ )
        {
			// 第o组第i副图像为高斯金字塔中第o组第i+1和i组图像相减得到
            const Mat& src1 = gpyr[o*(nOctaveLayers + 3) + i];
            const Mat& src2 = gpyr[o*(nOctaveLayers + 3) + i + 1];
            Mat& dst = dogpyr[o*(nOctaveLayers + 2) + i];
            subtract(src2, src1, dst, noArray(), CV_16S);
        }
    }
}
这个比较简单,就是一个subtract()函数。

至此,SIFT第一步就完成了。参见《SIFT原理与源码分析

(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu未经允许请勿用于商业用途)

 

 






分享到:
评论

相关推荐

    openCV-2.2_collection.rar_opencv 2.2 SIFT_opencv2.2_opencv源码分析

    这个名为"openCV-2.2_collection.rar"的压缩包包含了一个针对OpenCV 2.2版本的源码分析,特别关注了SIFT(尺度不变特征变换)算法的实现。SIFT是一种经典且广泛使用的特征检测和描述方法,它在图像识别、匹配和3D...

    opencv2.4.9源码分析——SIFT

    SIFT算法,全称为尺度不变特征变换(Scale-Invariant Feature Transform),是一种在...通过深入分析OpenCV中的SIFT源码,可以更好地理解和应用SIFT算法,以及如何在不侵犯专利的前提下,开发类似的特征提取方法。

    基于Opencv的sift算法

    **OpenCV中的SIFT(尺度不变特征变换)算法详解** SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是一种强大的计算机视觉算法,用于在不同尺度和旋转下识别图像的关键点。OpenCV库,一个开源的...

    SIFT,python源码实现及基于opencv实现

    **SIFT(尺度不变特征变换)**是一种在计算机视觉领域广泛应用的局部特征检测算法,由David G. Lowe在1999年提出。SIFT特征具有尺度不变性、旋转不变性和部分遮挡抗干扰能力,使得它在图像匹配、物体识别、三维重建...

    SIFT算法源码(OpenCv C++)

    通过阅读和理解这段代码,你可以深入学习SIFT算法的工作原理,以及如何利用OpenCV进行实际的图像处理任务。 在实际应用中,SIFT算法与其他图像处理技术结合,如RANSAC(随机样本一致性)进行几何变换的估计,可以...

    opencv实现的SIFT特征提取与匹配算法

    **OpenCV实现的SIFT特征提取与匹配算法详解** ...总结,这个项目为学习和实践SIFT特征提取与匹配提供了一个基础平台,通过运行和分析代码,可以帮助开发者深入理解SIFT算法的工作原理,并为实际应用提供参考。

    基于OPENCV的SIFT代码

    **基于OpenCV的SIFT(尺度不变特征转换)代码详解** SIFT(Scale-Invariant Feature Transform,尺度不变特征转换)是一种强大的图像特征检测方法,由David G. Lowe在2004年提出。该算法的核心在于它能检测出图像中...

    基于OpenCV的SIFT算法特征提取

    1. **尺度空间极值检测**:SIFT算法首先通过高斯差分金字塔来构建尺度空间,以寻找在不同尺度下的关键点。这样可以确保特征在缩放、旋转或光照变化等情况下依然稳定。 2. **关键点定位**:找到尺度空间中的局部极大...

    opencv SIFT

    **OpenCV SIFT (尺度不变特征变换) 知识详解** OpenCV(开源计算机视觉库)是一个强大的跨平台计算机视觉库,它包含了各种用于图像处理和计算机视觉的算法。SIFT(尺度不变特征变换)是其中一种关键的特征检测与...

    opencv实现的sift算法源码,包含了图像的SIFT特征提取,详细讲解SIFT关键点的提取过程,图像间的基于SIFT特征的图像匹配

    在这个OpenCV实现的SIFT算法源码中,我们可以深入理解SIFT的关键步骤: 1. **尺度空间极值检测**:SIFT算法首先在多尺度上寻找图像的局部极值点,通过高斯差分金字塔来实现。每个尺度层都通过高斯滤波器平滑图像,...

    python opencv sift光流.zip

    SIFT(尺度不变特征变换)和光流是其中两个关键的概念,它们在理解和分析图像序列时起着至关重要的作用。 SIFT特征是David Lowe在1999年提出的,是一种用于图像匹配和物体识别的鲁棒特征。它具有尺度不变性和旋转...

    opencv SIFT匹配

    OpenCV SIFT(尺度不变特征转换)匹配是计算机视觉领域中的一个重要技术,用于识别和匹配图像中的关键点。SIFT算法由David Lowe在1999年提出,它具有旋转、尺度、亮度和对比度不变性,使得它在图像处理和计算机视觉...

    计算机视觉SIFT算子OPENCV3.0详细实现(未调用opencv和sift相关的函数)

    计算机视觉是一种技术,它使计算机和软件系统能够识别和理解图像中的内容,SIFT(尺度不变特征变换)是其中一种重要的局部特征检测算法。本文将详细介绍如何在OpenCV3.0框架下,不直接调用预封装的SIFT函数,而是...

    基于OPENCV的SIFT特征提取与匹配算法代码

    包含完整的从图像高斯金字塔、DOG、空间极值点提取、关键点描述、KDtree匹配等关键步骤的全部函数实现,对全面深入理解Lowe的SIFT算法有莫大帮助。 程序运行前须安装 (1)OpenCV: ...

    sift VS2008&amp;OpenCV2 4 3 源码

    1. **尺度空间极值检测**:SIFT算法首先通过高斯差分金字塔来构建尺度空间,以寻找最佳的尺度空间局部极值点,这些点可能对应于图像中的关键点。 2. **关键点定位与稳定**:确定了潜在的关键点后,算法会进行精确...

    SIFT 算法的最新opencv 实现_1.1.2

    在实际应用中,SIFT与其它特征匹配算法(如SURF、ORB等)结合,可以提高识别和匹配的性能。 **总结:** SIFT算法是图像处理中重要的特征提取方法,OpenCV提供了方便的接口供开发者使用。通过这个特定的压缩包,用户...

    opencv实现PCASift算法

    PCA-SIFT(Principal Component Analysis Scale-Invariant Feature Transform)是一种结合了主成分分析(PCA)与SIFT(尺度不变特征变换)算法的方法,用于图像处理中的特征提取。OpenCV是一个强大的开源计算机视觉...

    基于OpenCV-Python的SIFT算法的实现.rar

    SIFT(尺度不变特征变换)是一种强大的特征检测算法,它能够在图像的尺度空间中找到稳定的兴趣点,并为这些点提供描述符,使其在不同的尺度、旋转和光照条件下保持不变性。 【描述】中提到,压缩包内包含了完整的...

    python opencv sift 手动区域光流跟踪

    Python作为当今最流行的编程语言之一,与OpenCV结合可以方便地实现各种视觉算法,包括SIFT(尺度不变特征变换)和手动区域光流跟踪。 SIFT是一种特征检测算法,它能在不同尺度和旋转下找到图像中的关键点,这些关键...

Global site tag (gtag.js) - Google Analytics