ORB-SLAM2 ---- ORBextractor::ORBextractor

一、函数的作用

这个函数是ORBextractor类的构造函数,该函数的作用为
1. 计算每层金字塔分配的特征点数量
2. 计算灰度圆的边界(umax[v]),用于后续计算特征点的角度信息『在IC_Angle()函数中使用』

二、函数源码

ORBextractor::ORBextractor(int _nfeatures, float _scaleFactor, int _nlevels,
         int _iniThFAST, int _minThFAST):         // 特征点数目,缩放因子(1.2),金字塔层数(8),
         										  //角点的阈值,降低后的阈值(若无角点,降低阈值后继续提取)
    nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
    iniThFAST(_iniThFAST), minThFAST(_minThFAST)
{
    // 开辟存放各层级缩放因子的容器
    mvScaleFactor.resize(nlevels);

    // 开辟存放各缩放因子平方的容器
    mvLevelSigma2.resize(nlevels);

    // 初始化容器内容 
    mvScaleFactor[0]=1.0f;
    mvLevelSigma2[0]=1.0f;

    // 计算各层级的缩放因子和平方
    for(int i=1; i<nlevels; i++)
    {
        mvScaleFactor[i]=mvScaleFactor[i-1]*scaleFactor;
        mvLevelSigma2[i]=mvScaleFactor[i]*mvScaleFactor[i];
    }

    //开辟缩放因子和其平方倒数的容器 
    mvInvScaleFactor.resize(nlevels);
    mvInvLevelSigma2.resize(nlevels);

    // 计算各层级的缩放因子和平方的倒数
    for(int i=0; i<nlevels; i++)
    {
        mvInvScaleFactor[i]=1.0f/mvScaleFactor[i];
        mvInvLevelSigma2[i]=1.0f/mvLevelSigma2[i];
    }

    // 开辟图像金字塔层级的容器
    mvImagePyramid.resize(nlevels);
    // 开辟存放各层特征点个数的容器
    mnFeaturesPerLevel.resize(nlevels);
    // 缩放因子的倒数
    float factor = 1.0f / scaleFactor;
    // 第0层分配的特征点数
    float nDesiredFeaturesPerScale = nfeatures*(1 - factor)/(1 - (float)pow((double)factor, (double)nlevels));
    // 总共被分配过的特征点数量,用于后续分配最后一层的特征点
    int sumFeatures = 0;

    // 用第0层的特征点数来依次计算除最后一层以外的每层特征点数
    for( int level = 0; level < nlevels-1; level++ )
    {
        mnFeaturesPerLevel[level] = cvRound(nDesiredFeaturesPerScale); // 四舍五入,返回int类型
        sumFeatures += mnFeaturesPerLevel[level];
        nDesiredFeaturesPerScale *= factor;
    }

    // 因为前面用了四舍五入,将剩余的所有特征点放在最后一层
    mnFeaturesPerLevel[nlevels-1] = std::max(nfeatures - sumFeatures, 0);

    // 定义成员变量为512,因为描述子储存坐标是256*4,描述子成对出现,所以为(256*4)/2
    const int npoints = 512;
    // 将int类型的bit_pattern_31_,强制转换为指针类型
    const Point* pattern0 = (const Point*)bit_pattern_31_;
    // 将pattern0到pattern0 + npoints的元素复制追加到pattern末尾
    // 每段pattern0 + npoints中有一对描述子,所以占2个int类型
    std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));

    //This is for orientation
    // pre-compute the end of a row in a circular patch
    // 本函数难点,这部分代码实际作用是求灰度圆的边界
    // 开辟vmax的容器
    umax.resize(HALF_PATCH_SIZE + 1); // HALF_PATCH_SIZE = 15;

    // 创建循环辅助变量,v,v0,创建int类型vmax
    int v, v0, vmax = cvFloor(HALF_PATCH_SIZE * sqrt(2.f) / 2 + 1); // cvFloor()向上取最小整数值
    int vmin = cvCeil(HALF_PATCH_SIZE * sqrt(2.f) / 2); // 向下取最大整数值
    // hp2等于半径的平方
    const double hp2 = HALF_PATCH_SIZE*HALF_PATCH_SIZE;
    // 保持对称性
    for (v = 0; v <= vmax; ++v)
        umax[v] = cvRound(sqrt(hp2 - v * v));
    // Make sure we are symmetric
    for (v = HALF_PATCH_SIZE, v0 = 0; v >= vmin; --v)
    {
        while (umax[v0] == umax[v0 + 1])
            ++v0;
        umax[v] = v0;
        ++v0;
    }
}

三、函数的传参

1. int  _nfeatures 特征点的数目,类型为int类型
2. float _scaleFactor 缩放因子,类型为float类型 
3. int _nlevels 金字塔的层数,类型为int类型
4. int _iniThFAST 提取角点的阈值,类型为int类型
5. int _minThFAST 降低后的阈值(若无角点,降低阈值后继续提取),类型为int类型

四、变量命名规范

这里说一下变量的命名规范,这个很重要,在看代码时可以快速理解代码:
1. 以小写字母m(member的首字母)开头的变量表示类的成员变量
2. mp开头的变量表示指针(pointer)型类成员变量;
3. mb开头的变量表示布尔(bool)型类成员变量;
4. mv开头的变量表示向量(vector)型类成员变量;
5. mpt开头的变量表示指针(pointer)型类成员变量,并且它是一个线程(thread);
6. ml开头的变量表示列表(list)型类成员变量;
7. mlp开头的变量表示列表(list)型类成员变量,并且它的元素类型是指针(pointer);
8. mlb开头的变量表示列表(list)型类成员变量,并且它的元素类型是布尔型(bool);
其中mv在初期看代码时尤其重要,因为代码中会出现大量的容器,如本文中出现的mvScaleFactor.resize(nlevels)等,看到mv开头,
就要反映过来这是一个容器。

五、本函数难点

	这块内容本人看的时候感觉代码能看懂,但是不知道具体作用是什么,看了很多帖子感觉讲的都不清楚,在看完后续内容再回头梳理时发现其实很简单,
是被那些帖子的描述带偏了。其他代码作了详尽的注释,可以很容易的看懂

在这里插入图片描述

	在本项目中求出的vmax = vmin = 11 ,两个循环一个从15到11,一个从0到11,这两个循环是为了
保证良好的对称性。
	这段代码的功能是求灰度圆的边界,最上面那一行(标注15的地方),有三个像素在圆内(看边界的
交点在14.5以上算作园内),第十四行有6个,后面依次为8,9,10,11,12,13,13,14,14,14,
15,15,15,15.,这个第3,6,8......像素点就是灰度圆的边界。

六、总结

构造函数在Tracking中会new一个ORBextractor(),并且初始化,后续可以使用此函数中的容器:
1. 装每层特征点个数的容器『mnFeaturesPerLevel』
2. 装灰度圆边界的容器『umax[v]』
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值