SFIT特征(四)

原创 2016年06月01日 10:28:09

在上一章节中,我们知道,对于每个稳定检测的关键点,我们赋予其三个信息:坐标位置、尺度(哪一组哪一层)以及主方向(统计邻域像素点的梯度方向和大小计算直方图而来)。接下来,我们需要为每个关键点建立一个128维度的描述符。

6.1采样区域
关键点的描述符是通过统计其邻域采样点的梯度方向和大小而来的,所以首先需要确定采样区域的范围。
首先邻域采样点的梯度计算是在关键点对应的高斯图像上进行的(根据关键点的尺度信息确定高斯过滤参数),然后,将关键点邻域划分为dd (Lowe中建议值为4)的子区域,每个子区域作为一个种子点,种子点包含8个方向,将子区域内的采样点按照其梯度方向分配至相应的8个方向之一。

每个子区域的为边长同样是3σoct(与确定关键点主方向相同)的正方形区域,所以总边长为3σoctd。但由于后期我们需要对采样点梯度进行插值,所以将窗口扩展至3σoct(d+1)。为了保证旋转不变性,所以我们将坐标轴旋转,使其与关键点的主方向对齐,则邻域区域的最终边长为radius=3(2)σoct(d+1)。邻域边长变换示意图如下所示,

这里写图片描述

6.2采样点子区域标号计算
每个采样点(x,y)T的梯度和方向按照5.1的公式进行计算,这里不再说明。(注意,这里的坐标(x,y)T 表示以关键点为原点的坐标系的坐标)
确定好采样区域之后,每个采样点(x,y)T在新坐标系(为了保证旋转不变性,将坐标轴旋转至于关键点主方向对齐)下的坐标方程(x,y)T 为,

(x,y)T=(cosθsinθsinθcosθ)(x,y)T

接下来,我们需要确定采样点在新坐标系下应当被分配到哪个子区域中(dd 子区域),由于每个子区域的边长大小为3σoct,所以采样点所对应的子区域标号为,
(x′′,y′′)T=13σoct(x,y)T+d/2

6.3采样点插值生成种子点向量
Lowe建议,每个采样点梯度采用大小为σ=0.5d 的高斯函数进行处理,即,

mag(a+x,b+y)e(x)2+(y)22(0.5d)2

其中,(a,b) 表示关键点在高斯图像中的坐标,(x,y) 表示采样点在采样区域内的局部坐标,mag() 表示对应像素点的梯度大小。

另外,每个采样点的梯度方向相对于关键点主方向进行旋转,即采样点的梯度方向减掉关键点主方向的值作为采样点的梯度方向进行后续计算。

经过上面的步骤,我们知道了每个采样点的梯度大小和方向,以及在新坐标下所分配的子区域标号,但注意的是,每个采样点的子区域标号往往不是整数的,也就说是采样点对周围邻近的几个子区域都有一定的贡献。所以,接下来,我们采用插值的方法计算每个采样点对邻近子区域,邻近bin方向的贡献程度。

插值思想如下,红色点表示的是采样点,dr1dr2dc1dc2do1do2 分别表采样点距离行r0r1,列c0c1 ,方向o1o1的距离比值。则以G为例,G表示最终对右下子区域方向o0 的贡献程度为magdr1dc1do1

这里写图片描述

如果关键点周围统计子区域大小44,每个子区域按照8个bin方向统计,那么对于一个关键点而言,其描述符向量总的长度为128维度。下图所示是关键点子区域大小为22,每个子区域取8个bin方向的示意图。

这里写图片描述

6.4归一化、设置阈值
经过上面的介绍,我们已经为每个关键点分配了一个128维度的描述符向量,为了增强鲁棒性,去除光照等的影响,需要归一化处理。另外,可能由于相机饱和度变化造成某些方向梯度值过大,可以通过设置阈值,截断较大的梯度值(Lowe中取阈值为0.2)。

至此,我们已经了解了如何针对一幅图像,生成旋转、尺度等不变性的特征描述符。



6.5C++源代码

/*
* 生成关键点描述符。
* img:高斯图像(按照keypoint的scale高斯滤波的图像)
* ptf:keypoints坐标
* ori:keypoint的主方向
* d/n:keypoints邻域子区域边长为4,每个区域内取8个直方图bins
*/
static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float scl,
                               int d, int n, float* dst )
{
    Point pt(cvRound(ptf.x), cvRound(ptf.y));
    //转换为弧度值
    float cos_t = cosf(ori*(float)(CV_PI/180));
    float sin_t = sinf(ori*(float)(CV_PI/180));
    float bins_per_rad = n / 360.f;
    float exp_scale = -1.f/(d * d * 0.5f);
    float hist_width = SIFT_DESCR_SCL_FCTR * scl;//3*\sgima_oct
    //采样半径为:3*\sigma_oct*\sqrt(2)*(d+1)
    int radius = cvRound(hist_width * 1.4142135623730951f * (d + 1) * 0.5f);
    cos_t /= hist_width;
    sin_t /= hist_width;

    int i, j, k, len = (radius*2+1)*(radius*2+1), histlen = (d+2)*(d+2)*(n+2);
    int rows = img.rows, cols = img.cols;

    AutoBuffer<float> buf(len*6 + histlen);
    float *X = buf, *Y = X + len, *Mag = Y, *Ori = Mag + len, *W = Ori + len;
    float *RBin = W + len, *CBin = RBin + len, *hist = CBin + len;

    for( i = 0; i < d+2; i++ )
    {
        for( j = 0; j < d+2; j++ )
            for( k = 0; k < n+2; k++ )
                hist[(i*(d+2) + j)*(n+2) + k] = 0.;
    }

    //依次遍历每个采样点
    for( i = -radius, k = 0; i <= radius; i++ )
        for( j = -radius; j <= radius; j++ )
        {
            // Calculate sample's histogram array coords rotated relative to ori.
            // Subtract 0.5 so samples that fall e.g. in the center of row 1 (i.e.
            // r_rot = 1.5) have full weight placed in row 1 after interpolation.

            // 旋转采样点与keypoint的主方向对齐后的位置
            float c_rot = j * cos_t - i * sin_t;
            float r_rot = j * sin_t + i * cos_t;
            float rbin = r_rot + d/2 - 0.5f;
            float cbin = c_rot + d/2 - 0.5f;

            //采样点在高斯图像中的坐标
            int r = pt.y + i, c = pt.x + j;

            if( rbin > -1 && rbin < d && cbin > -1 && cbin < d &&
                r > 0 && r < rows - 1 && c > 0 && c < cols - 1 )
            {
                //计算采样点梯度
                float dx = (float)(img.at<sift_wt>(r, c+1) - img.at<sift_wt>(r, c-1));
                float dy = (float)(img.at<sift_wt>(r-1, c) - img.at<sift_wt>(r+1, c));

                X[k] = dx; Y[k] = dy; RBin[k] = rbin; CBin[k] = cbin;
                W[k] = (c_rot * c_rot + r_rot * r_rot)*exp_scale;//权重
                k++;
            }
        }

    //计算每个像素点的梯度方向、大小和权重
    len = k;
    fastAtan2(Y, X, Ori, len, true);
    magnitude(X, Y, Mag, len);
    exp(W, W, len);

    for( k = 0; k < len; k++ )
    {
        float rbin = RBin[k], cbin = CBin[k];
        float obin = (Ori[k] - ori)*bins_per_rad;//梯度方向为像素点的方向-关键点主方向(保持旋转不变性)
        float mag = Mag[k]*W[k];

        //计算采样点距离周围子区域及相邻bin的距离
        int r0 = cvFloor( rbin );
        int c0 = cvFloor( cbin );
        int o0 = cvFloor( obin );
        rbin -= r0;
        cbin -= c0;
        obin -= o0;

        if( o0 < 0 )
            o0 += n;
        if( o0 >= n )
            o0 -= n;

        // histogram update using tri-linear interpolation(x/y/orientation)
        float v_r1 = mag*rbin, v_r0 = mag - v_r1;
        float v_rc11 = v_r1*cbin, v_rc10 = v_r1 - v_rc11;
        float v_rc01 = v_r0*cbin, v_rc00 = v_r0 - v_rc01;

        float v_rco111 = v_rc11*obin, v_rco110 = v_rc11 - v_rco111;
        float v_rco101 = v_rc10*obin, v_rco100 = v_rc10 - v_rco101;
        float v_rco011 = v_rc01*obin, v_rco010 = v_rc01 - v_rco011;
        float v_rco001 = v_rc00*obin, v_rco000 = v_rc00 - v_rco001;

        int idx = ((r0+1)*(d+2) + c0+1)*(n+2) + o0;
        hist[idx] += v_rco000;
        hist[idx+1] += v_rco001;
        hist[idx+(n+2)] += v_rco010;
        hist[idx+(n+3)] += v_rco011;
        hist[idx+(d+2)*(n+2)] += v_rco100;
        hist[idx+(d+2)*(n+2)+1] += v_rco101;
        hist[idx+(d+3)*(n+2)] += v_rco110;
        hist[idx+(d+3)*(n+2)+1] += v_rco111;
    }
   ......
版权声明:本文为博主原创文章,未经博主允许不得转载。

最新sfit算法matlab库

  • 2017年12月09日 10:41
  • 368KB
  • 下载

漫谈高数(四) 特征向量物理意义

  • 2016年03月07日 14:52
  • 137KB
  • 下载

OpenCV学习笔记(30)KAZE 算法原理与源码分析(四)KAZE特征的性能分析与比较

KAZE系列笔记:1.  OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波2.  OpenCV学习笔记(28)KAZE 算法原理与源码分析(二)非线性尺度空间构建3.  O...

《python+opencv实践》四、图像特征提取与描述——30Harris 角点检测

目标 • 理解Harris 角点检测的概念 • 学习函数:cv2.cornerHarris(),cv2.cornerSubPix() 原理 在上一节我们已经知道了角点的一个特性:向任何方向移动变化...

Java 面向对象的四大特征

计算机软件系统是现实生活中的业务在计算机中的映射,而现实生活中的业务其实就是一个个对象协作的过程。面向对象编程就是按现实业务一样的方式将程序代码按一个个对象进行组织和编写,让计算机系统能够识别和理解用...

决策树算法(四)——选取最佳特征划分数据集

写在前面的话咦,好神奇,我今天发现我莫名其妙的成了小三。原来我被卖了还不知道,还帮人家宣传博客和微信公众账号。我放弃了自己规划好的人生,然后决定跟另一个在一起,然后发现原来他有女朋友。我今天有点头大哎...

机器学习降维算法四:Laplacian Eigenmaps 拉普拉斯特征映射

原创书写,转载请注明此文出自:http://www.cnblogs.com/xbinworld,http://blog.csdn.net/xbinworld   Laplacian Eigenma...

图像处理特征不变算子系列之FAST算子(四)

本文接着前面图像特征不变检测的基础上,接着介绍一种极为优秀的基于机器学习的特征检测算子--FAST算子。FAST算子通过对固定半径圆上的像素进行分割测试,通过逻辑测试可以去处大量的非特征候选点,并且利...

itk中的特征提取算法(四)

本文的重点是图像处理中经典hough变换直线检测,类名叫做itkHoughTransform2DLinesImageFilter(它还有个兄弟叫做itkHoughTransform2DCirclesI...

四、面向对象介绍 结构化程序设计、面向对象程序设计、面向对象设计的特征和优缺点

一、结构化程序设计 传统的程序设计方法可以归结为“程序=算法+数据结构”,将程序定义为处理数据的一系列过程。这种设计方法的着眼点是面向过程的,特点是数据与程序分离,即数据与数据处理分离。 结构化程...
  • tianttt
  • tianttt
  • 2014年12月14日 15:04
  • 1485
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SFIT特征(四)
举报原因:
原因补充:

(最多只允许输入30个字)