您的位置:

SIFT特征详解

一、SIFT特征介绍

SIFT全称是Scale Invariant Feature Transform,即为尺度不变特征变换,是由David Lowe在1999年提出的一种特征检测算法,它可以检测出图像中独特的、稳定的局部特征并进行描述。SIFT特征对于缩放、旋转、仿射变换都具有不变性,也具有一定的光照鲁棒性。

通过对SIFT算法的实现,图像中的每个特征点都可以被描述成一个向量,这个向量可以作为后续计算识别的基础。SIFT特征在图像识别、增强现实、物体跟踪等领域都有广泛的应用。

二、SIFT特征提取

在SIFT算法中,特征的提取一般包含四个步骤:尺度空间极值检测、关键点定位、方向确定和特征描述。

1. 尺度空间极值检测

由于物体在图像中出现的大小和方向是不确定的,所以SIFT算法使用了一个高斯金字塔来对图像进行尺度空间的处理。在高斯金字塔的不同层次上,使用高斯差分来检测各个尺度下图像的极值点。

/**
 * 尺度空间极值检测函数
 * @param  DogPyr 差分金字塔
 * @param  octvs  金字塔的组数
 * @param  intvls 每组中相邻两层的差分结果个数
 * @param  contr_thr 极值点的阈值
 * @param  r	   极值点的邻域半径
 * @return 关键点
 */
vector ScaleSpaceExtrema(const vector
   
    >& DogPyr,
                                   const int octvs, const int intvls,
                                   const double contr_thr, const int r);

    
   
  

2. 关键点定位

在检测到尺度空间中的极值点后,需要对每个极值点进行更加精确的定位,确定其精确位置和尺度大小。

/**
 * 关键点定位函数
 * @param  DogPyr 差分金字塔
 * @param  octvs  金字塔的组数
 * @param  intvls 每组中相邻两层的差分结果个数
 * @param  extrema  尺度空间极值点
 * @param  contr_thr   极值点的阈值
 * @param  curv_thr 极值点的曲率阈值
 * @return 关键点和尺度
 */
vector 
Localization(const vector
   
    >& DogPyr, const int octvs, 
             const int intvls, vector
     & extrema, 
             const double contr_thr, const double curv_thr);

     
    
   
  

3. 方向确定

在确定了极值点的位置和尺寸后,还需要确定这个点的主要方向。SIFT算法选择使用极值点周围一定范围内梯度幅值最大的方向作为该点的主方向。

/**
 * 方向直方图生成函数
 * @param  img     关键点所在图像
 * @param  kpt     关键点
 * @param  bins    直方图个数
 * @param  sigma   高斯权重方差
 * @return 方向直方图
 */
vector 
OrientationHistogram(const Mat& img, const Keypoint& kpt, const int bins, 
                     const double sigma);

/**
 * 方向确定函数
 * @param  gauss_pyr 已经计算好的高斯差分金字塔
 * @param  kpt 关键点
 * @param  octv 关键点所在组
 * @param  intvl 关键点所在层
 * @param  n 关键点附近每个直方图的直方图个数
 * @param  sigma 关键点周围邻域的高斯系数
 * @return 关键点方向(弧度)
 */
double 
GetOrientation(const vector
   
    >& gauss_pyr, const Keypoint& kpt,
               const int octv, const int intvl, const int n,
               const double sigma);

    
   
  

4. 特征描述

在确定了极值点的位置、尺寸和主要方向后,针对每个关键点的周围区域,选取一些关键点方向的特征点来进行描述。SIFT特征描述子被设计为对每个关键点周围的16x16个像素块生成一个128维的向量。向量中每个维度反映的是该像素块的梯度幅值和方向。

/**
 * 描述子生成函数
 * @param  img 关键点所在图像
 * @param  kpt 关键点
 * @param  ori 关键点方向
 * @param  scl 关键点尺度
 * @param  d 关键点描述子所在的维度
 * @return 关键点描述子
 */
vector 
Descriptor(const Mat& img, const Keypoint& kpt, const double ori, 
           const double scl, const int d);

  

三、SIFT特征匹配

在使用SIFT特征进行图像匹配时,通常采用关键点描述子之间的相似度来计算两幅图像之间的相似度。我们可以通过计算两个描述子之间的欧式距离,来衡量他们之间的相似性。

/**
 * 计算描述子之间的距离
 * @param  desc1 描述子1
 * @param  desc2 描述子2
 * @return 描述子之间的距离
 */
double 
Distance(const vector& desc1, const vector
   & desc2);

/**
 * 通过比较两个特征点的描述子,计算它们之间的距离
 * @param  desc1 特征点1的描述子
 * @param  desc2 特征点2的描述子
 * @return 特征点1和2之间的距离
 */
double 
MatchScore(const vector
    & desc1, const vector
     & desc2);

/**
 * 特征点匹配函数
 * @param  desc1 特征点说明子1
 * @param  desc2 特征点描述子2
 * @return 最佳匹配的位置
 */
int 
BestMatch(const vector
      & desc1, const vector
       
        
         >& desc2);
        
       
      
     
    
   
  

四、SIFT特征的应用

SIFT特征在计算机视觉中有着广泛的应用,在图像识别、目标检测、增强现实、全景图像拼接、物体跟踪等领域都有着非常重要的作用。

例如在目标检测领域,通过提取图像中所有的SIFT特征,可以构建一个描述图像信息和特征向量信息的数据库。当需要检测一张未知图像是否包含相同的目标时,我们可以提取这张图像的SIFT特征并在数据库中进行匹配,最终找到相同目标所在的图像。