前言
这部分函数是根据输入的图像矩阵构建图像金字塔,这是 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;