【SLAM学习笔记】13-ORB

【SLAM学习笔记】13-ORB,第1张

【SLAM学习笔记】13-ORB

2021SC@SDUSC

目录
  • 1.ORBextractor特征提取与描述
  • 2.代码分析

1.ORBextractor特征提取与描述

在ORBextractor中包括定义的两个类

  1. ExtractorNode
  2. ORBextractor

在ExtractorNode中,维护的是四叉树的数据结构,后面在关键点均匀化时,会用到其中的DvideNode函数。

具体可见这三篇博客:
ORBextractor.cc 代码原理分析
认真的虎ORBSLAM2源码解读(四):图解ORB特征提取ORBextractor
高斯图像金字塔

2.代码分析

这个函数用于计算特征点的方向,这里是返回角度作为方向。
计算特征点方向是为了使得提取的特征点具有旋转不变性。
方法是灰度质心法:以几何中心和灰度质心的连线作为该特征点方向

static float IC_Angle(const Mat& image, Point2f pt,  const vector & u_max)
{
	//图像的矩,前者是按照图像块的y坐标加权,后者是按照图像块的x坐标加权
    int m_01 = 0, m_10 = 0;

	//获得这个特征点所在的图像块的中心点坐标灰度值的指针center
    const uchar* center = &image.at (cvRound(pt.y), cvRound(pt.x));

    // Treat the center line differently, v=0
	//这条v=0中心线的计算需要特殊对待
    //由于是中心行+若干行对,所以PATCH_SIZE应该是个奇数
    for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)
		//注意这里的center下标u可以是负的!中心水平线上的像素按x坐标(也就是u坐标)加权
        m_10 += u * center[u];

    // Go line by line in the circular patch  
	//这里的step1表示这个图像一行包含的字节总数。参考[https://blog.csdn.net/qianqing13579/article/details/45318279]
    int step = (int)image.step1();
	//注意这里是以v=0中心线为对称轴,然后对称地每成对的两行之间进行遍历,这样处理加快了计算速度
    for (int v = 1; v <= HALF_PATCH_SIZE; ++v)
    {
        // Proceed over the two lines
		//本来m_01应该是一列一列地计算的,但是由于对称以及坐标x,y正负的原因,可以一次计算两行
        int v_sum = 0;
		// 获取某行像素横坐标的最大范围,注意这里的图像块是圆形的!
        int d = u_max[v];
		//在坐标范围内挨个像素遍历,实际是一次遍历2个
        // 假设每次处理的两个点坐标,中心线下方为(x,y),中心线上方为(x,-y) 
        // 对于某次待处理的两个点:m_10 = Σ x*I(x,y) =  x*I(x,y) + x*I(x,-y) = x*(I(x,y) + I(x,-y))
        // 对于某次待处理的两个点:m_01 = Σ y*I(x,y) =  y*I(x,y) - y*I(x,-y) = y*(I(x,y) - I(x,-y))
        for (int u = -d; u <= d; ++u)
        {
			//得到需要进行加运算和减运算的像素灰度值
			//val_plus:在中心线下方x=u时的的像素灰度值
            //val_minus:在中心线上方x=u时的像素灰度值
            int val_plus = center[u + v*step], val_minus = center[u - v*step];
			//在v(y轴)上,2行所有像素灰度值之差
            v_sum += (val_plus - val_minus);
			//u轴(也就是x轴)方向上用u坐标加权和(u坐标也有正负符号),相当于同时计算两行
            m_10 += u * (val_plus + val_minus);
        }
        //将这一行上的和按照y坐标加权
        m_01 += v * v_sum;
    }

    //为了加快速度还使用了fastAtan2()函数,输出为[0,360)角度,精度为0.3°
    return fastAtan2((float)m_01, (float)m_10);
}

乘数因子,一度对应着多少弧度

const float factorPI = (float)(CV_PI/180.f);

计算ORB特征点的描述子。注意这个是全局的静态函数,只能是在本文件内被调用

static void computeOrbDescriptor(const KeyPoint& kpt,
                                 const Mat& img, const Point* pattern,
                                 uchar* desc)
{
	//得到特征点的角度,用弧度制表示。kpt.angle是角度制,范围为[0,360)度
    float angle = (float)kpt.angle*factorPI;
	//然后计算这个角度的余弦值和正弦值
    float a = (float)cos(angle), b = (float)sin(angle);

	//获得图像中心指针
    const uchar* center = &img.at(cvRound(kpt.pt.y), cvRound(kpt.pt.x));
	//获得图像的每行的字节数
    const int step = (int)img.step;

	//原始的BRIEF描述子不具有方向信息,通过加入特征点的方向来计算描述子,称之为Steer BRIEF,具有较好旋转不变特性
	//具体地,在计算的时候需要将这里选取的随机点点集的x轴方向旋转到特征点的方向。
	//获得随机“相对点集”中某个idx所对应的点的灰度,这里旋转前坐标为(x,y), 旋转后坐标(x',y')推导:
    // x'= xcos(θ) - ysin(θ),  y'= xsin(θ) + ycos(θ)
    #define GET_VALUE(idx) center[cvRound(pattern[idx].x*b + pattern[idx].y*a)*step + cvRound(pattern[idx].x*a - pattern[idx].y*b)]        
    // y'* step
    // x'
	//brief描述子由32*8位组成
	//其中每一位是来自于两个像素点灰度的直接比较,所以每比较出8bit结果,需要16个随机点,这也就是为什么pattern需要+=16的原因
    for (int i = 0; i < 32; ++i, pattern += 16)
    {
		
        int t0, 	//参与比较的一个特征点的灰度值
			t1,		//参与比较的另一个特征点的灰度值	
			val;	//描述子这个字节的比较结果
		
        t0 = GET_VALUE(0); t1 = GET_VALUE(1);
        val = t0 < t1;							//描述子本字节的bit0
        t0 = GET_VALUE(2); t1 = GET_VALUE(3);
        val |= (t0 < t1) << 1;					//描述子本字节的bit1
        t0 = GET_VALUE(4); t1 = GET_VALUE(5);
        val |= (t0 < t1) << 2;					//描述子本字节的bit2
        t0 = GET_VALUE(6); t1 = GET_VALUE(7);
        val |= (t0 < t1) << 3;					//描述子本字节的bit3
        t0 = GET_VALUE(8); t1 = GET_VALUE(9);
        val |= (t0 < t1) << 4;					//描述子本字节的bit4
        t0 = GET_VALUE(10); t1 = GET_VALUE(11);
        val |= (t0 < t1) << 5;					//描述子本字节的bit5
        t0 = GET_VALUE(12); t1 = GET_VALUE(13);
        val |= (t0 < t1) << 6;					//描述子本字节的bit6
        t0 = GET_VALUE(14); t1 = GET_VALUE(15);
        val |= (t0 < t1) << 7;					//描述子本字节的bit7

        //保存当前比较的出来的描述子的这个字节
        desc[i] = (uchar)val;
    }//通过对随机点像素灰度的比较,得出BRIEF描述子,一共是32*8=256位

    //为了避免和程序中的其他部分冲突在,在使用完成之后就取消这个宏定义
    #undef GET_VALUE
}

下面就是预先定义好的随机点集,256是指可以提取出256bit的描述子信息,每个bit由一对点比较得来;4=2*2,前面的2是需要两个点(一对点)进行比较,后面的2是一个点有两个坐标

static int bit_pattern_31_[256*4] =
            {
                    8,-3, 9,5,
                    4,2, 7,-12,
                    -11,9, -8,2,
                    7,-12, 12,-13,
                    2,-13, 2,12,
                    1,-7, 1,6,
                    -2,-10, -2,-4,
                    -13,-13, -11,-8,
                    -13,-3, -12,-9,
                    10,4, 11,9,
                    -13,-8, -8,-9,
                    -11,7, -9,12,
                    7,7, 12,6,
                    -4,-5, -3,0,
                    -13,2, -12,-3,
                    -9,0, -7,5,
                    12,-6, 12,-1,
                    -3,6, -2,12,
                    -6,-13, -4,-8,
                    11,-13, 12,-8,
                    4,7, 5,1,
                    5,-3, 10,-3,
                    3,-7, 6,12,
                    -8,-7, -6,-2,
                    -2,11, -1,-10,
                    -13,12, -8,10,
                    -7,3, -5,-3,
                    -4,2, -3,7,
                    -10,-12, -6,11,
                    5,-12, 6,-7,
                    5,-6, 7,-1,
                    1,0, 4,-5,
                    9,11, 11,-13,
                    4,7, 4,12,
                    2,-1, 4,4,
                    -4,-12, -2,7,
                    -8,-5, -7,-10,
                    4,11, 9,12,
                    0,-8, 1,-13,
                    -13,-2, -8,2,
                    -3,-2, -2,3,
                    -6,9, -4,-9,
                    8,12, 10,7,
                    0,9, 1,3,
                    7,-5, 11,-10,
                    -13,-6, -11,0,
                    10,7, 12,1,
                    -6,-3, -6,12,
                    10,-9, 12,-4,
                    -13,8, -8,-12,
                    -13,0, -8,-4,
                    3,3, 7,8,
                    5,7, 10,-7,
                    -1,7, 1,-12,
                    3,-10, 5,6,
                    2,-4, 3,-10,
                    -13,0, -13,5,
                    -13,-7, -12,12,
                    -13,3, -11,8,
                    -7,12, -4,7,
                    6,-10, 12,8,
                    -9,-1, -7,-6,
                    -2,-5, 0,12,
                    -12,5, -7,5,
                    3,-10, 8,-13,
                    -7,-7, -4,5,
                    -3,-2, -1,-7,
                    2,9, 5,-11,
                    -11,-13, -5,-13,
                    -1,6, 0,-1,
                    5,-3, 5,2,
                    -4,-13, -4,12,
                    -9,-6, -9,6,
                    -12,-10, -8,-4,
                    10,2, 12,-3,
                    7,12, 12,12,
                    -7,-13, -6,5,
                    -4,9, -3,4,
                    7,-1, 12,2,
                    -7,6, -5,1,
                    -13,11, -12,5,
                    -3,7, -2,-6,
                    7,-8, 12,-7,
                    -13,-7, -11,-12,
                    1,-3, 12,12,
                    2,-6, 3,0,
                    -4,3, -2,-13,
                    -1,-13, 1,9,
                    7,1, 8,-6,
                    1,-1, 3,12,
                    9,1, 12,6,
                    -1,-9, -1,3,
                    -13,-13, -10,5,
                    7,7, 10,12,
                    12,-5, 12,9,
                    6,3, 7,11,
                    5,-13, 6,10,
                    2,-12, 2,3,
                    3,8, 4,-6,
                    2,6, 12,-13,
                    9,-12, 10,3,
                    -8,4, -7,9,
                    -11,12, -4,-6,
                    1,12, 2,-8,
                    6,-9, 7,-4,
                    2,3, 3,-2,
                    6,3, 11,0,
                    3,-3, 8,-8,
                    7,8, 9,3,
                    -11,-5, -6,-4,
                    -10,11, -5,10,
                    -5,-8, -3,12,
                    -10,5, -9,0,
                    8,-1, 12,-6,
                    4,-6, 6,-11,
                    -10,12, -8,7,
                    4,-2, 6,7,
                    -2,0, -2,12,
                    -5,-8, -5,2,
                    7,-6, 10,12,
                    -9,-13, -8,-8,
                    -5,-13, -5,-2,
                    8,-8, 9,-13,
                    -9,-11, -9,0,
                    1,-8, 1,-2,
                    7,-4, 9,1,
                    -2,1, -1,-4,
                    11,-6, 12,-11,
                    -12,-9, -6,4,
                    3,7, 7,12,
                    5,5, 10,8,
                    0,-4, 2,8,
                    -9,12, -5,-13,
                    0,7, 2,12,
                    -1,2, 1,7,
                    5,11, 7,-9,
                    3,5, 6,-8,
                    -13,-4, -8,9,
                    -5,9, -3,-3,
                    -4,-7, -3,-12,
                    6,5, 8,0,
                    -7,6, -6,12,
                    -13,6, -5,-2,
                    1,-10, 3,10,
                    4,1, 8,-4,
                    -2,-2, 2,-13,
                    2,-12, 12,12,
                    -2,-13, 0,-6,
                    4,1, 9,3,
                    -6,-10, -3,-5,
                    -3,-13, -1,1,
                    7,5, 12,-11,
                    4,-2, 5,-7,
                    -13,9, -9,-5,
                    7,1, 8,6,
                    7,-8, 7,6,
                    -7,-4, -7,1,
                    -8,11, -7,-8,
                    -13,6, -12,-8,
                    2,4, 3,9,
                    10,-5, 12,3,
                    -6,-5, -6,7,
                    8,-3, 9,-8,
                    2,-12, 2,8,
                    -11,-2, -10,3,
                    -12,-13, -7,-9,
                    -11,0, -10,-5,
                    5,-3, 11,8,
                    -2,-13, -1,12,
                    -1,-8, 0,9,
                    -13,-11, -12,-5,
                    -10,-2, -10,11,
                    -3,9, -2,-13,
                    2,-3, 3,2,
                    -9,-13, -4,0,
                    -4,6, -3,-10,
                    -4,12, -2,-7,
                    -6,-11, -4,9,
                    6,-3, 6,11,
                    -13,11, -5,5,
                    11,11, 12,6,
                    7,-5, 12,-2,
                    -1,12, 0,7,
                    -4,-8, -3,-2,
                    -7,1, -6,7,
                    -13,-12, -8,-13,
                    -7,-2, -6,-8,
                    -8,5, -6,-9,
                    -5,-1, -4,5,
                    -13,7, -8,10,
                    1,5, 5,-13,
                    1,0, 10,-13,
                    9,12, 10,-1,
                    5,-8, 10,-9,
                    -1,11, 1,-13,
                    -9,-3, -6,2,
                    -1,-10, 1,12,
                    -13,1, -8,-10,
                    8,-11, 10,-6,
                    2,-13, 3,-6,
                    7,-13, 12,-9,
                    -10,-10, -5,-7,
                    -10,-8, -8,-13,
                    4,-6, 8,5,
                    3,12, 8,-13,
                    -4,2, -3,-3,
                    5,-13, 10,-12,
                    4,-13, 5,-1,
                    -9,9, -4,3,
                    0,3, 3,-9,
                    -12,1, -6,1,
                    3,2, 4,-8,
                    -10,-10, -10,9,
                    8,-13, 12,12,
                    -8,-12, -6,-5,
                    2,2, 3,7,
                    10,6, 11,-8,
                    6,8, 8,-12,
                    -7,10, -6,5,
                    -3,-9, -3,9,
                    -1,-13, -1,5,
                    -3,-7, -3,4,
                    -8,-2, -8,3,
                    4,2, 12,12,
                    2,-5, 3,11,
                    6,-9, 11,-13,
                    3,-1, 7,12,
                    11,-1, 12,4,
                    -3,0, -3,6,
                    4,-11, 4,12,
                    2,-4, 2,1,
                    -10,-6, -8,1,
                    -13,7, -11,1,
                    -13,12, -11,-13,
                    6,0, 11,-13,
                    0,-1, 1,4,
                    -13,3, -9,-2,
                    -9,8, -6,-3,
                    -13,-6, -8,-2,
                    5,-9, 8,10,
                    2,7, 3,-9,
                    -1,-6, -1,-1,
                    9,5, 11,-2,
                    11,-3, 12,-8,
                    3,0, 3,5,
                    -1,4, 0,10,
                    3,-6, 4,5,
                    -13,0, -10,5,
                    5,8, 12,11,
                    8,9, 9,-6,
                    7,-4, 8,-12,
                    -10,4, -10,9,
                    7,3, 12,4,
                    9,-7, 10,-2,
                    7,0, 12,-2,
                    -1,-6, 0,-11
            };

特征点提取器的构造函数

ORBextractor::ORBextractor(int _nfeatures,		//指定要提取的特征点数目
						   float _scaleFactor,	//指定图像金字塔的缩放系数
						   int _nlevels,		//指定图像金字塔的层数
						   int _iniThFAST,		//指定初始的FAST特征点提取参数,可以提取出最明显的角点
						   int _minThFAST):		//如果因为图像纹理不丰富提取出的特征点不多,为了达到想要的特征点数目,
												//就使用这个参数提取出不是那么明显的角点
    nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
    iniThFAST(_iniThFAST), minThFAST(_minThFAST)//设置这些参数
{
	//存储每层图像缩放系数的vector调整为符合图层数目的大小
    mvScaleFactor.resize(nlevels);  
	//存储这个sigma^2,其实就是每层图像相对初始图像缩放因子的平方
    mvLevelSigma2.resize(nlevels);
	//对于初始图像,这两个参数都是1
    mvScaleFactor[0]=1.0f;
    mvLevelSigma2[0]=1.0f;
	//然后逐层计算图像金字塔中图像相当于初始图像的缩放系数 
    for(int i=1; i= vmin; --v)
    {
        while (umax[v0] == umax[v0 + 1])
            ++v0;
        umax[v] = v0;
        ++v0;
    }
}

计算特征点的方向

static void computeOrientation(const Mat& image, vector& keypoints, const vector& umax)
{
	// 遍历所有的特征点
    for (vector::iterator keypoint = keypoints.begin(),
         keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
    {
		// 调用IC_Angle 函数计算这个特征点的方向
        keypoint->angle = IC_Angle(image, 			//特征点所在的图层的图像
								   keypoint->pt, 	//特征点在这张图像中的坐标
								   umax);			//每个特征点所在图像区块的每行的边界 u_max 组成的vector
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5690959.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存