zoukankan      html  css  js  c++  java
  • SIFT算法:特征描述子

    SIFT算法:DoG尺度空间生产 
    SIFT算法:KeyPoint找寻、定位与优化
    SIFT算法:确定特征点方向 
    SIFT算法:特征描述子

    目录:

    1、确定描述子采样区域

    2、生成描述子

      2.1 旋转图像至主方向

      2.2 生成特征向量

    3、归一化特征向量

    附:SIFT开源代码集


    1 确定描述子采样区域

      SIFI 描述子h(x, y, θ)是对特征点附近邻域内高斯图像梯度统计结果的一种表示,它是一个三维的阵列,但通常将它表示成一个矢量。矢量是通过对三维阵列按一定规律进行排列得到的。特征描述子与特征点所在的尺度有关,因此,对梯度的求取应在特征点对应的高斯图像上进行。将特征点附近邻域划分成Bp X Bp个子区域,每个子区域的尺寸为mσ个像元,其中,m=3,Bp=4。σ为特征点的尺度值。考虑到实际计算时,需要采用双线性插值,计算的图像区域为mσ(Bp+ 1)。如果再考虑旋转的因素,那么,实际计算的图像区域应大mσ(Bp+ 1)√2。

    2 生成描述子

    2.1 旋转图像至主方向

      为了保证特征矢量具有旋转不变性,需要以特征点为中心,将特征点附近邻域内(mσ(Bp+ 1)√2 x mσ(Bp+ 1)√2)图像梯度的位置方向旋转一个方向角θ,即将原图像x轴转到与主方向相同的方向。旋转公式如下。

      在特征点附近邻域图像梯度的位置和方向旋转后,再以特征点为中心,在旋转后的图像中取一个mσBp x mσBp大小的图像区域。并将它等间隔划分成Bp X Bp个子区域,每个间隔为mσ像元。

    2.2 生成特征向量

      在每子区域内计算8个方向的梯度方向直方图,绘制每个梯度方向的累加值,形成一个种子点。与求特征点主方向时有所不同,此时,每个子区域的梯度方向直方图将0° ~360°划分为8个方向范围,每个范围为45°,这样,每个种子点共有8个方向的梯度强度信息。由于存在4X4(Bp X Bp)个子区域,所以,共有4X4X8=128个数据,最终形成128维的SIFT特征矢量。同样,对于特征矢量需要进行高斯加权处理,加权采用方差为Bp/2的标准高斯函数,其中距离为各点相对于特征点的距离。使用高斯权重的是为了防止位置微小的变化给特征向量带来很大的改变,并且给远离特征点的点赋予较小的权重,以防止错误的匹配。

    问题1:对于旋转之后的点进行三线性插值,具体是怎样操作的?

    Lowe原文如下:

    It is important to avoid all boundary affects in which the descriptor abruptly changes as a sample shifts smoothly from being within one histogram to another or from one orientation to another. Therefore, trilinear interpolation is used to distribute the value of each gradient sample into adjacent histogram bins. In other words, each entry into a bin is multiplied by a weight of 1 − d for each dimension, where d is the distance of the sample from the central value of the bin as measured in units of the histogram bin spacing.

    表示看不懂OpenCV和vlfeat中插值这一部分具体实现。还请高人指点。

    3 归一化特征向量

      为了去除光照变化的影响,需对上述生成的特征向量进行归一化处理,在归一化处理后,对特征矢量大于0.2的要进行截断处理,即大于0.2的值只取0.2,然后重新进行一次归一化处理,其目的是为了提高鉴别性。

     1 float nrm2 = 0;
     2 len = d*d*n;
     3 for( k = 0; k < len; k++ )
     4     nrm2 += dst[k]*dst[k];
     5 float thr = std::sqrt(nrm2)*SIFT_DESCR_MAG_THR; // SIFT_DESCR_MAG_THR = 4
     6 for( i = 0, nrm2 = 0; i < k; i++ )
     7 {
     8     float val = std::min(dst[i], thr);  //截断大于0.2的值
     9     dst[i] = val;
    10     nrm2 += val*val;
    11 }
    12 nrm2 = SIFT_INT_DESCR_FCTR/std::max(std::sqrt(nrm2), FLT_EPSILON); // SIFT_INT_DESCR_FCTR = 512.f
    View Code

    SIFT开源代码:

    1. http://www.vlfeat.org vlfeat开源图像处理库,其中http://www.vlfeat.org/api/sift.html关于其代码中一些细节和SIFT原理的解释。
    2. http://robwhess.github.io/opensift/ RobHess sift
    3. http://www.cs.ubc.ca/~lowe/research.html  David Lowe Research Projects中的SIFT
    4. http://docs.opencv.org/2.4/modules/nonfree/doc/feature_detection.html OpenCV2.4以后的版本已实现了SIFT,其源码和RobHess的很相似。

    参考资料:

    1. David G. Lowe Distinctive Image Features from Scale-Invariant Keypoints 
    2. 王永明 王贵锦 《图像局部不变性特征与描述》 
    3. Trilinear interpolation http://en.wikipedia.org/wiki/Trilinear_interpolation
  • 相关阅读:
    Java/IO流
    Java实现IO通信(服务器篇)
    利用哈夫曼二叉树实现文件的压缩
    关于字符串构建,连接,查找
    线程小球
    准备造一个轮子,关于图片浏览器的
    IOS之循环引用
    ARC
    构造方法与快速创建对象
    autorelease
  • 原文地址:https://www.cnblogs.com/JiePro/p/sift_4.html
Copyright © 2011-2022 走看看