ORB-SLAM2源码笔记(2)——特征点提取ORBextractor

从ORB-SLAM2代码详解02: 特征点提取器ORBextractor_ncepu_Chen的博客-CSDN博客_orbextractor 由流程图可知,不无论是单目相机,还是双目相机和RGBD相机,都需要先提取特征点,这是进入跟踪流程的第一步。

ORBextractor类

ORBextractor()构造函数

ORBextractor通过构建图像金字塔将输入图片逐级缩放进行存储计算,金字塔层级越高,图片分辨率越低,ORB特征点越大。图像金字塔是对尺度的一种描述,例如,当我们在上一个图像金字塔的上层与下一个图像金字塔的下层匹配到特征点时,说明相机后退了(金字塔层数越大,图片越模糊,距离越远)

构造函数步骤:

1. 初始化图像金字塔相关变量

2. 初始化用于计算描述子的pattern变量,pattern是用于计算描述子的256对坐标

3. 计算一个半径为16的圆的近似坐标

构建图像金字塔ComputePyramid() 

逐层计算图像金字塔,对于每层图像进行以下两步:

  1. 图片缩放到mvInvScaleFactor对应尺寸.
  2. 在图像外补一圈厚度为19padding(提取FAST特征点需要特征点周围半径为3的圆域,计算ORB描述子需要特征点周围半径为16的圆域).

  • 深灰色为缩放后的原始图像.
  • 包含绿色边界在内的矩形用于提取FAST特征点.
  • 包含浅灰色边界在内的整个矩形用于计算ORB描述

void ORBextractor::ComputePyramid(cv::Mat image) {
    for (int level = 0; level < nlevels; ++level) {
        // 计算缩放+补padding后该层图像的尺寸
        float scale = mvInvScaleFactor[level];
        Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale));
        Size wholeSize(sz.width + EDGE_THRESHOLD * 2, sz.height + EDGE_THRESHOLD * 2);
        Mat temp(wholeSize, image.type());
        
		// 缩放图像并复制到对应图层并补边
        mvImagePyramid[level] = temp(Rect(EDGE_THRESHOLD, EDGE_THRESHOLD, sz.width, sz.height));
        if( level != 0 ) {
            resize(mvImagePyramid[level-1], mvImagePyramid[level], sz, 0, 0, cv::INTER_LINEAR);
            copyMakeBorder(mvImagePyramid[level], temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, 
                           BORDER_REFLECT_101+BORDER_ISOLATED);            
        } else {
            copyMakeBorder(image, temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, 
                           BORDER_REFLECT_101);            
        }
    }
}

提取特征点并进行筛选ComputeKeyPointsOctTree ()

金字塔层数越高,对应图像的分辨率越低,能提取到的特征数就越少。为了均匀分摊特征点数目,按面积比例进行划分。

参考:https://zhuanlan.zhihu.com/p/61738607

为了力求特征点均匀分布在图像的所有部分,使用了两个技巧:

1. 分块搜索,如果某个块特征点响应值比较小,降低分数再搜索

2. 将所有特征点进行四叉树筛选,若某区域内特征点数目过于密集,则只取其中响应值最大的那个。

 

 每个块的大小是30×30,且相邻两块之间会有6个像素的重叠,这是因为提取FAST特征点需要计算周围半径3内的像素点信息,实际产生特征点的区域会比搜索区域小3个像素。

四叉树筛选特征点

计算特征点的方向computeOrientation()

使用特征点周围半径19的圆的重心方向作为特征点的方向,每一个特征点都对应一个主方向。这样做的目的是在计算描述子时,将特征点周围像素旋转到主方向上计算,方便进行特征匹配。

猜你喜欢

转载自blog.csdn.net/luoyihao123456/article/details/125163363