ORB-SLAM2源码学习:ORBextractor.cc:ComputePyramid构建图像金字塔①

时间:2024-11-07 07:35:01

前言

这部分函数是根据输入的图像矩阵构建图像金字塔,这是 ORB(Oriented FAST and Rotated BRIEF)特征提取算法的一部分。在ORB算法中,通过对图像进行多尺度处理,可以在不同尺度上检测和描述特征,从而使得算法具有尺度不变性。

1.函数声明

void ORBextractor::ComputePyramid(cv::Mat image)//输入图像cv::Mat image。

2.函数定义

2.1对图像进行一些预处理

思路: 

1.获取本层的缩放因子的倒数,构造当前图像像素的尺寸大小SZ

2.根据SZ构造全尺寸图像的尺寸大小(相当于对SZ进行对称加边)

3.构造临时矩阵储存全尺寸图像,masktemp暂时不用理会。

4.最后一步相当于在wholeSize中取出矩形域SZ放入当前层的金字塔图像中。

说明:wholeSize定义了一个足够大的临时图像空间,以便在后续调用 copyMakeBorder 时能在图像的每一边增加适当的边缘填充,从而确保后续处理的稳定性。

for (int level = 0; level < nlevels; ++level)//遍历每一层。
    {
        float scale = mvInvScaleFactor[level];//获取本层的缩放因子的倒数,这里应该是0-1之间的小数。
        // 计算当前层的图像像素大小。
        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()), masktemp;
        // 第一个和第二个参数是矩形的左上角的坐标,均为 EDGE_THRESHOLD。这意味着提取的区域将向右和向下偏移 EDGE_THRESHOLD 的值。
        // 第三个和第四个参数分别是矩形的宽度和高度,均为 sz.width 和 sz.height,这表示提取的区域大小与缩小后的图像尺寸相同。
        mvImagePyramid[level] = temp(Rect(EDGE_THRESHOLD, EDGE_THRESHOLD, sz.width, sz.height));
....
    }
2.2 图像之间的关系

3.缩放图像并进行边缘填充

     // Compute the resized image 计算缩放后的图像。
        // 在图像金字塔的不同层级上计算和生成缩小版本的图像。
        if( level != 0 )//不包括第0层。
        {
            //将下层图像根据当前层SZ缩放到当前层
            resize(mvImagePyramid[level-1], mvImagePyramid[level], sz, 0, 0, INTER_LINEAR);

            // copyMakeBorder 函数被用来为每一层的图像添加边框。
            // 即使在后续的处理(如滤波或特征检测)过程中,金字塔图像的边缘部分也会有足够的邻域信息,从而避免边缘效应带来的计算误差。
            copyMakeBorder(mvImagePyramid[level], temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD,
                           BORDER_REFLECT_101+BORDER_ISOLATED);
    		//BORDER_ISOLATED 选项确保边缘区域不会受到外部环境(即边界外的像素)的影响。
    		// 即使在图像的边缘添加了边框,边缘的计算也只会依赖于图像的有效区域,不会被外部像素干扰。
        }
        else
        {
            copyMakeBorder(image, temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD,
                           BORDER_REFLECT_101);
        }

 注:我认为这里存在一些问题,它最后的图像金字塔容器mvImagePyramid并没有保存到图像边界扩充的结果,扩充时保留在了temp中,应该最后要传给mvImagePyramid。

mvImagePyramid[level] = temp;
3.1图像扩充边界的方式