经典算法研究(1):SIFT算法2

作者:qxl 邮箱: 1183129553@qq.com


系列文章链接

一、经典算法研究(1):SIFT算法1
二、经典算法研究(1):SIFT算法2
三、



前言

学习sift算法记录

1.1特征点位置确定

为什么使用差分高斯金字塔寻找极值点
1)差分高斯图像可以直接由高斯图像相减获得,简单高效
2)差分高斯函数是尺度规范化的高斯拉普拉斯函数的近似,而高斯拉普拉斯函数的极大值和极小值点是一种非常稳定的特征点(与梯度特征、Hessian特征和Harris角点相比(梯度特征和Hessian特征的差别))

确定潜在特征点
上文已经阐述,高斯拉普拉斯函数的极大值和极小值点是一种非常稳定的特征点,因此我们从差分高斯金字塔中寻找这些潜在特征点。差分高斯金字塔是一个三维空间(平面图像二维加上尺度一维,共三维),因此我们在三维空间中在寻找极大值点和极小值点。具体方法是比较当前特征点的灰度值和其他26个点的灰度值的大小,这26个点包括:当前尺度下该点的8邻域以及前一尺度和后一尺度下与该点最近的9个点(9*2+8=26),(如果此部分区域全部为平坦无细节区域,计算出的极大和极小值和邻域灰度值差别并不大,怎样进一步处理?)如下图所示:
在这里插入图片描述
opencv源代码:

void SIFT::findScaleSpaceExtrema( const vector<Mat>& gauss_pyr, const vector<Mat>& dog_pyr,
                                  vector<KeyPoint>& keypoints ) const
{
    ......
    for( int o = 0; o < nOctaves; o++ )//每一个八度
        for( int i = 1; i <= nOctaveLayers; i++ )//对八度中的存在具有第1至第nOctaveLayers层高斯差分图像提取特征点
        {
            ......
            for( int r = SIFT_IMG_BORDER; r < rows-SIFT_IMG_BORDER; r++)//图像二维空间.行  边界处理->开头结尾截掉一部分
            {
                ......
                for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)//图像二维空间.列
                {
                    .......
                     // 当前点与26个点比较,比较两次,分别确定是否是极大值,是否是极小值
                     if( std::abs(val) > threshold &&
                       ((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&//step表示列宽
                         val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
                         val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
                         val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
                         val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
                         val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
                         val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
                         val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
                         val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
                        (val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
                         val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
                         val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
                         val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
                         val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
                         val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
                         val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
                         val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
                         val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
                    {
                           ......
                        
                    }
                }
            }
        }
}

尺度空间中的极值点已经确定出来了,下面有两个问题需要解决:

(1)这些点是最终我们确定的SIFT特征点集的超集,该超集里包含许多“间谍”-----不稳定的特征点,因此必须去掉这些不稳定的特征点。这些不稳定的特征点主要包含两类:低对比度的点(对噪声敏感,平坦无细节区域也是属于低对比度点,通过此步骤去除掉)和边缘点

(2)这一步骤中极值点的坐标还是离散的整数值,如何精确确定特征点的位置。

由于在计算上(2)问题的解决可以捎带解决(1)中低对比度点的问题,因此我们先讨论问题(2)。本部分的OpenCV源码位于sift.cpp文件的adjustLocalExtrema函数中,本文最后会贴出此部分源码,下面首先分析如何解决以上两个问题。

精确确定特征点的位置
由于图像是一个离散的空间,特征点的位置的坐标都是整数,但是极值点的坐标并不一定就是整数,如下图所示。
在这里插入图片描述
因此,如何从离散空间中估计出极值点的精确位置是重要的。为了精确确定极值点坐标,Brown和Lowe使用了三元二次函数,通过迭代确定极值点的位置,具有良好的效果(从上图推断,应该是根据离散点,使用三元二次函数去拟合一条曲线,曲线确定之后,极值点的位置自然而然也就确定了)。主要是根据泰勒公式,泰勒公式作用:用值已知的点A估计点A附近的某点B的值。
待补充…
去除不稳定特征点

  • 去除对比度低的点

以上求出了极值点的精确的位置,将求出的 x 带入原式,得:
公式
我们就利用这个函数去除对比度低的点,lowe文中,当D(x)<=0.03时,去除这个特征点。

  • 去除边缘点

差分高斯金字塔中的极值点会有许多边缘点,边缘点对一些噪声不稳定,因此需要去除这些边缘相应点。
差分高斯金字塔中会有一些不是很好的极值点,这些点的特征是:在跨越边缘的方向有较大的主曲率,在与边缘相切的方向主曲率较小。在本步骤中,需要去除这些不好的边缘相应。主曲率可以通过2阶Hessian方阵获得:
矩阵公式
D函数中某点的主曲率和该点的H矩阵的特征值是成比例的,因此我们可以通过H矩阵的特征值来确定某点在差分高斯金字塔中的主曲率。设矩阵H的特征值分别为α(较大)和β(较小),有如下公式:
通过以上两式,α和β就可以计算出来了,但是,不急!
如上文所述,那些不好的边缘点:跨越边缘的方向有较大的主曲率,与边缘相切的方向主曲率较小。因此,我们通过α/β的比率函数并确定阈值来体现表征那些不好的边缘点,α/β越大,说明这个点就越糟糕,就越应该被删掉,但是这样就要真真切切计算α和β的值,前面让大家不急了,是的,先不用着急计算,设定r=α/β(即 α=rβ),使用如下公式:
以上函数是关于r的增函数(已经假设α是特征值中较大的一个),r 越大,以上函数值就越大,反之,以上函数值越大,r 就是越大的,因此我们可以通过已知的Tr(H)和Det(H)“曲线地”去判断 r的大小!所以在本步骤中,去除不好的边缘点的阈值是:
lowe论文中设定r=10。

到这里,在差分高斯金字塔中提取的特征点就完成了提纯的步骤。

下面是OpenCV源码中特征点精确位置的确定过程以及特征点提纯过程,主要实现函数为sift.cpp中adjustLocalExtrema函数:

1.2 生成特征描述子

梯度方向和幅值
特征点确定之后,其相关信息为高斯图像 L ( x , y , σ ) L(x,y,\sigma) L(x,y,σ) σ \sigma σ。下一步是确定特征点方向。以特征点为中心,统计与该特征点在3 σ \sigma σ距离内像素的梯度幅值及方向,梯度方向和幅值的计算公式如下:
m ( x , y ) = ( L ( x + 1 , y ) − L ( x − 1 , y ) ) 2 − ( L ( x , y + 1 ) − L ( x , y − 1 ) ) 2 m(x,y)=\sqrt{(L(x+1,y)-L(x-1,y))^{2}-(L(x,y+1)-L(x,y-1))^2} m(x,y)=(L(x+1,y)L(x1,y))2(L(x,y+1)L(x,y1))2
θ ( x , y ) = t a n − 1 L ( x , y + 1 ) − L ( x , y − 1 ) L ( x + 1 , y ) − L ( x − 1 , y ) \theta(x,y)=tan^{-1}\frac{L(x,y+1)-L(x,y-1)}{L(x+1,y)-L(x-1,y)} θ(x,y)=tan1L(x+1,y)L(x1,y)L(x,y+1)L(x,y1)
根据上述公式构建邻域梯度直方图,将一个圆周360度,每10度为一个档位,均分成36份。同时根据距离特征点的远近,计算权重,距离特征点越近,权重越大,越远,则权重越小。权重乘以梯度值作为梯度直方图的统计值。
    梯度直方图峰值所对应的角度就是当前特征点A的方向。如果直方图中,某个角度的梯度幅值大于峰值的80%,那么认为当前特征点可能存在多个可能的梯度方向,使用另外一个特征点来描述这种可能性,这个点的坐标和尺度等参数与峰值点相同,但是角度不同。
在这里插入图片描述
生成图像局部描述符
目前,图像中每个特征点的坐标、尺度方向都已经确定,接下来需要根据这些信息生成描述子。
“方向不变性的表达”–受限根据特征点的尺度选择高斯金字塔中的图像,然后计算特征点邻域范围内各点的梯度方向和梯度的幅值,并根据上文得到的特征点梯度方向来调整邻域点的梯度方向,从而实现描述子的方向不变性。如下图所示,

1.2 sift算法步骤

      sift算法可以同时处理亮度、平移、旋转、尺度的变化,利用特征点来提取特征描述符,最后在特征描述符之间寻找匹配。–描述不清???
      该算法主要包括5个步骤进行匹配。

  1. 构建尺度空间,检测极值点,获得尺度不变性。
  2. 特征点过滤并进行精确定位,提出不稳定的特征点。
  3. 在特征点处提取特征描述符,为特征点分配方向值
  4. 生成特征描述子,利用特征描述符寻找匹配点;
  5. 计算变换参数。
    当两幅图像的sift特征向量生成以后,下一步就可以采用关键点特征向量的欧氏距离来作为两幅图像中关键点的相似度判定度量。
    取图1的某个关键点,通过遍历找到图像2中的距离最近的两个关键点。
    在这两个关键点中,如果次近距离除以最近距离小于某个阈值,则判定为一对匹配点。

1.3 sift算法描述

      在上述sift算法步骤中提到了尺度空间,那什么是尺度和尺度空间呢?

      原始图像 I ( x , y ) I(x,y) I(x,y)和离散化的二维高斯函数构建的矩阵 G ( x , y , σ ) G(x,y,\sigma) G(x,y,σ)进行卷积得到一个新的尺度空间用 L ( x , y , σ ) L(x,y,\sigma) L(x,y,σ)表示。公式如下表示:

L ( x , y , σ ) = G ( x , y , σ ) ∗ I ( x , y ) L(x,y,\sigma) = G(x,y,\sigma)*I(x,y) L(x,y,σ)=G(x,y,σ)I(x,y)

其中,

G ( x , y , σ ) = [ 1 / 2 ∗ π ∗ σ 2 ] ∗ e x p ( − ( x 2 + y 2 ) / 2 σ 2 G(x,y,\sigma) = [1/2*\pi*\sigma^2]*exp(-(x^2 + y^2)/2\sigma^2 G(x,y,σ)=[1/2πσ2]exp((x2+y2)/2σ2)

      σ \sigma σ是尺度坐标,其大小决定平滑程度,大尺度对应图像的概貌特征,生成低分辨率图像,小尺度对应图像的细节特征,生成高分辨率图像。

如何离散成(2*k+1) (2k+1)的矩阵?

      为了更有效的在尺度空间检测到稳定的关键点,提出了高斯差分尺度空间(DOG scale-space)。
利用不同尺度的高斯差分核与原始图像 I ( x , y ) I(x,y) I(x,y)进行卷积生成图像。

      Gaussian卷积核可以是不同的大小,使用同一尺寸的滤波器对两幅包含有不同尺寸的同一物体的图像求局部最值将有可能出现一方求得最值,而另一张图片没有求得最值的情况,为了解决此问题,可以将两幅图像认为是连续的两张图片,分别以他们作为地面做四棱锥,好比金字塔,那么每一个截面与原图像相似,那么两个金字塔必然包含大小一致的物体的无穷个截面。但实际由于计算效率,只能离散下采样,在采样数和处理时间之间进行权衡。不可避免,也存在向下采样的截面中找不到尺寸大小一致的两个图片。

      通过图像金字塔可以对每一层求出局部最值,但是这样的稳定点数据比较多,需要使用某种方法抑制取出一部分点,同时保证同一尺度下的稳定点数目得以保存。

1.4 sift算法优缺点

二、sift算法实现

参考
【1】SIFT解析(一)建立高斯金字塔:https://blog.csdn.net/alecsophia/article/details/17509195
【2】https://blog.csdn.net/hujingshuang/article/details/44995829
【3】SIFT原理与源码分析:https://blog.csdn.net/xiaowei_cqu/article/details/8069548

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值