ORB_SLAM3的ORBextractor函数

1、金字塔提取特征点数量的原理

请添加图片描述

2、相关的代码

// 图片降采样缩放系数的倒数
        // 其实factor才是缩小因子
        float factor = 1.0f / scaleFactor;
        // 每个单位缩放系数所希望的特征点个数  第0层 factor^nelevels
        float nDesiredFeaturesPerScale = nfeatures * (1 - factor) / (1 - (float)pow((double)factor, (double)nlevels));

        // 用于在特征点个数分配的,特征点的累计计数清空
        int sumFeatures = 0;
        // 开始逐层计算要分配的特征点个数,顶层图像除外(看循环后面)
        // 分配0-6层
        for (int level = 0; level < nlevels - 1; level++)
        {
            std::cout << "第" << level << "层的特征点数" << nDesiredFeaturesPerScale << std::endl;
            // 分配 cvRound : 返回个参数最接近的整数值
            mnFeaturesPerLevel[level] = cvRound(nDesiredFeaturesPerScale);
            // 累计
            sumFeatures += mnFeaturesPerLevel[level];
            // 乘系数
            nDesiredFeaturesPerScale *= factor;
        }
        // 剩下的全部丢给了第7层
        //  由于前面的特征点个数取整操作,可能会导致剩余一些特征点个数没有被分配,所以这里就将这个余出来的特征点分配到最高的图层中
        mnFeaturesPerLevel[nlevels - 1] = std::max(nfeatures - sumFeatures, 0);

3、计算圆umax原理

请添加图片描述

4、相关代码

// 成员变量pattern的长度,也就是点的个数,这里的512表示512个点(上面的数组中是存储的坐标所以是256*2*2)
        const int npoints = 512;
        // 获取用于计算BRIEF描述子的随机采样点点集头指针
        // 注意到pattern0数据类型为Points*,bit_pattern_31_是int[]型,所以这里需要进行强制类型转换
        const Point *pattern0 = (const Point *)bit_pattern_31_;
        // 使用std::back_inserter的目的是可以快覆盖掉这个容器pattern之前的数据
        // 其实这里的操作就是,将在全局变量区域的、int格式的随机采样点以cv::point格式复制到当前类对象中的成员变量中
        std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));

        // This is for orientation
        // 下面的内容是和特征点的旋转计算有关的
        //  pre-compute the end of a row in a circular patch
        // 预先计算圆形patch中行的结束位置
        //+1中的1表示那个圆的中间行
        // HALF_PATCH_SIZE=15
        umax.resize(HALF_PATCH_SIZE + 1);

        // cvFloor返回不大于参数的最大整数值,cvCeil返回不小于参数的最小整数值,cvRound则是四舍五入
        int v,                                                   // 循环辅助变量
            v0,                                                  // 辅助变量
            vmax = cvFloor(HALF_PATCH_SIZE * sqrt(2.f) / 2 + 1); // 计算圆的最大行号,+1应该是把中间行也给考虑进去了
                                                                 // NOTICE 注意这里的最大行号指的是计算的时候的最大行号,此行的和圆的角点在45°圆心角的一边上,之所以这样选择
                                                                 // 是因为圆周上的对称特性

        // 这里的二分之根2就是对应那个45°圆心角

        int vmin = cvCeil(HALF_PATCH_SIZE * sqrt(2.f) / 2);
        // 半径的平方
        const double hp2 = HALF_PATCH_SIZE * HALF_PATCH_SIZE;

        // 利用圆的方程计算每行像素的u坐标边界(max)
        for (v = 0; v <= vmax; ++v)
            umax[v] = cvRound(sqrt(hp2 - v * v)); // 结果都是大于0的结果,表示x坐标在这一行的边界

        // Make sure we are symmetric
        // 这里其实是使用了对称的方式计算上四分之一的圆周上的umax,目的也是为了保持严格的对称(如果按照常规的想法做,由于cvRound就会很容易出现不对称的情况,
        // 同时这些随机采样的特征点集也不能够满足旋转之后的采样不变性了)
        for (v = HALF_PATCH_SIZE, v0 = 0; v >= vmin; --v)
        {
            while (umax[v0] == umax[v0 + 1])
                ++v0;
            umax[v] = v0;
            ++v0;
        }

参考这篇相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值