ORB-SLAM2 ---- ORBextractor::ComputePyramid函数

目录

1.ComputePyramid函数作用

2. 代码解释

2.1 整体代码

2.2 几个图像的区别

2.3 拷贝图像的方式

2.3.1 图像扩充边界的方式

2.3.2 为什么要扩充图像边界

2.3.3 拷贝图像代码解释 

2.3.4 要分清构造图像的大小Sz、构造空图像Mat、填补图像resize、扩充图像MakeBorder的区别!!!


1.ComputePyramid函数作用

        根据输入的图片CV::Mat构建图像金字塔图像。

2. 代码解释

2.1 整体代码

void ORBextractor::ComputePyramid(cv::Mat image)
{
	//开始遍历所有的图层,levels是yaml文件里面的
    for (int level = 0; level < nlevels; ++level)
    {
		//获取本层图像的缩放系数,mvInvScaleFactor[level]是从orbextrator得到的
        float scale = mvInvScaleFactor[level];
		//计算本层图像的像素尺寸大小
        Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale));
		//全尺寸图像。包括无效图像区域的大小。将图像进行“补边”,EDGE_THRESHOLD区域外的图像不进行FAST角点检测
        Size wholeSize(sz.width + EDGE_THRESHOLD*2, sz.height + EDGE_THRESHOLD*2);
		// temp是扩展了边界的图像,是一个构造函数,拷贝了wholeSize的图像
        Mat temp(wholeSize, image.type()), masktemp;
        // mvImagePyramid 刚开始时是个...空的vector
		// 将扩充后的图像拷贝给mvImagePyramid容器
        mvImagePyramid[level] = temp(Rect(EDGE_THRESHOLD, EDGE_THRESHOLD, sz.width, sz.height));

        // Compute the resized image
		//计算第0层以上resize后的图像
        if( level != 0 )
        {
			//将上一层金字塔图像根据前文设定sz缩放到当前层级
            resize(mvImagePyramid[level-1],	//输入图像
				   mvImagePyramid[level], 	//输出图像
				   sz, 						//输出图像的尺寸
				   0, 						//水平方向上的缩放系数,留0表示自动计算
				   0,  						//垂直方向上的缩放系数,留0表示自动计算
				   cv::INTER_LINEAR);		//图像缩放的差值算法类型,这里的是线性插值算法


			//把源图像拷贝到目的图像的中央,四面填充指定的像素。图片如果已经拷贝到中间,只填充边界
			//这样做是为了能够正确提取边界的FAST角点
			//EDGE_THRESHOLD指的这个边界的宽度,由于这个边界之外的像素不是原图像素而是算法生成出来的,所以不能够在EDGE_THRESHOLD之外提取特征点			
            copyMakeBorder(mvImagePyramid[level], 					//源图像
						   temp, 									//目标图像(此时其实就已经有大了一圈的尺寸了)
						   EDGE_THRESHOLD, EDGE_THRESHOLD, 			//top & bottom 需要扩展的border大小
						   EDGE_THRESHOLD, EDGE_THRESHOLD,			//left & right 需要扩展的border大小
                           BORDER_REFLECT_101+BORDER_ISOLATED);     //扩充方式,opencv给出的解释:						
        }
        else
        {
			//对于第0层未缩放图像,直接将图像深拷贝到temp的中间,并且对其周围进行边界扩展。此时temp就是对原图扩展后的图像
            copyMakeBorder(image,			//这里是原图像
						   temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD,
                           BORDER_REFLECT_101);            
        }
    }
}

2.2 几个图像的区别

for (int level = 0; level < nlevels; ++level)
    {
		//获取本层图像的缩放系数,mvInvScaleFactor[level]是从orbextrator得到的
        float scale = mvInvScaleFactor[level];
		//计算本层图像的像素尺寸大小
        Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale));
		//全尺寸图像。包括无效图像区域的大小。将图像进行“补边”,EDGE_THRESHOLD区域外的图像不进行FAST角点检测
        Size wholeSize(sz.width + EDGE_THRESHOLD*2, sz.height + EDGE_THRESHOLD*2);
		// temp是扩展了边界的图像,是一个构造函数,拷贝了wholeSize的图像
        Mat temp(wholeSize, image.type()), masktemp;
        // mvImagePyramid 刚开始时是个...空的vector
		// 把中间区域拷贝给mvImagePyramid容器
        mvImagePyramid[level] = temp(Rect(EDGE_THRESHOLD, EDGE_THRESHOLD, sz.width, sz.height));

        我们从第0层到第八层确定金字塔的尺寸及图像。

    std::vector mvScaleFactor;		    ///<每层图像的缩放因子
    std::vector mvInvScaleFactor;        ///<以及每层缩放因子的倒数
    std::vector mvLevelSigma2;		    ///<存储每层的sigma^2,即上面每层图像相对于底层图像缩放倍数的平方
    std::vector mvInvLevelSigma2;	    /// mvImagePyramid;

        先获取本层的缩放系数,然后构造本层图像像素的尺寸大小sz,这个大小就是传进来的参数图像的大小乘以缩放因子。

        然后构造全尺寸图像尺寸大小,全尺寸图像是将上下左右都镶上边框了,对图像进行补边,如下图所示。

ORB-SLAM2 ---- ORBextractor::ComputePyramid函数_第1张图片

         再构造空图片temp,用全尺寸大小进行初始化,并将格式设置与输入图片一致,最后一行代码的意思是将temp图片扩充边界大小保存到mvImagePyramid容器中,mvImagePyramid容器保存金字塔各层图像。

ORB-SLAM2 ---- ORBextractor::ComputePyramid函数_第2张图片

2.3 拷贝图像的方式

2.3.1 图像扩充边界的方式

ORB-SLAM2 ---- ORBextractor::ComputePyramid函数_第3张图片        在opencv里面提供。

2.3.2 为什么要扩充图像边界

        利用FAST算法在提取特征点时,图像边缘的特征点半径为3的圆无法取到(边界外无像素点),为了解决此问题,我们对图像边界进行填充。

2.3.3 拷贝图像代码解释 

// Compute the resized image
		//计算第0层以上resize后的图像
        if( level != 0 )
        {
			//将上一层金字塔图像根据前文设定sz缩放到当前层级
            resize(mvImagePyramid[level-1],	//输入图像
				   mvImagePyramid[level], 	//输出图像
				   sz, 						//输出图像的尺寸
				   0, 						//水平方向上的缩放系数,留0表示自动计算
				   0,  						//垂直方向上的缩放系数,留0表示自动计算
				   cv::INTER_LINEAR);		//图像缩放的差值算法类型,这里的是线性插值算法


			//把源图像拷贝到目的图像的中央,四面填充指定的像素。图片如果已经拷贝到中间,只填充边界
			//这样做是为了能够正确提取边界的FAST角点
			//EDGE_THRESHOLD指的这个边界的宽度,由于这个边界之外的像素不是原图像素而是算法生成出来的,所以不能够在EDGE_THRESHOLD之外提取特征点			
            copyMakeBorder(mvImagePyramid[level], 					//源图像
						   temp, 									//目标图像(此时其实就已经有大了一圈的尺寸了)
						   EDGE_THRESHOLD, EDGE_THRESHOLD, 			//top & bottom 需要扩展的border大小
						   EDGE_THRESHOLD, EDGE_THRESHOLD,			//left & right 需要扩展的border大小
                           BORDER_REFLECT_101+BORDER_ISOLATED);     //扩充方式,opencv给出的解释:						
        }
        else
        {
			//对于第0层未缩放图像,直接将图像深拷贝到temp的中间,并且对其周围进行边界扩展。此时temp就是对原图扩展后的图像
            copyMakeBorder(image,			//这里是原图像
						   temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD,
                           BORDER_REFLECT_101);            
        }
    }

        如果图像是非0层的,将上一层的图像作为输入缩放到本层并存储到mvImagePyramid容器作为本函数的输出,图像大小为本层计算出来的sz(不包含边界的),copyMakeBorder函数把源图像拷贝到目的图像的中央,四面填充指定的像素。图片如果已经拷贝到中间,只填充边界。

        如果图像是0层的,只填充边界。

2.3.4 要分清构造图像的大小Sz、构造空图像Mat、填补图像resize、扩充图像MakeBorder的区别!!!

你可能感兴趣的:(orb-slam2,c++,图像处理,计算机视觉)