欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > ORB-SLAM2源码学习:ORBextractor.cc:ORBextractor::operator()主入口函数

ORB-SLAM2源码学习:ORBextractor.cc:ORBextractor::operator()主入口函数

2025/9/18 17:12:42 来源:https://blog.csdn.net/2301_76831056/article/details/143405207  浏览:    关键词:ORB-SLAM2源码学习:ORBextractor.cc:ORBextractor::operator()主入口函数

前言

主入口函数直接调用了ComputePyramid()、ComputeKeyPointsOctTree()、computeDescriptors()三大核心函数,间接调用了这三大核心函数所调用的函数,可以说是覆盖了所有的函数。

1.函数声明

/*用仿函数(重载括号运算符)方法来计算图像特征点* _image                    输入原始图的图像_mask                     掩膜mask_keypoints                存储特征点关键点的向量_descriptors              存储特征点描述子的矩阵*/
void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>& _keypoints,OutputArray _descriptors)
{ ....
}

2.函数定义

步骤:

1.接收输入图像(_image)(另一个输入图像矩阵暂时用不到)提取图像的矩阵数据并检查是否是单通道。

if(_image.empty())return;//获取图像的大小Mat image = _image.getMat();// 获取图像的矩阵数据。//判断图像的格式是否正确,要求是单通道灰度值assert(image.type() == CV_8UC1 );//每个像素值是一个8位无符号整数,三通道。// assert是一种断言语句,用于在程序中进行条件检查。

2.调用ComputePyramid() 函数生成图像金字塔。

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

  // Pre-compute the scale pyramidComputePyramid(image);

3.调用ComputeKeyPointsOctTree()函数(传统的方法采用ComputeKeyPointsOld(),这里并未采用)来计算关键(Keypoints)点并存储在 allKeypoints 中。

ORB-SLAM2源码学习:ORBextractor.cc :ComputeKeyPointsOctTree计算并分配特征点②

// 存储所有的特征点,注意此处为二维的vector,第一维存储的是金字塔的层数,第二维存储的是那一层金字塔图像里提取的所有特征点vector < vector<KeyPoint> > allKeypoints; //使用四叉树的方式计算每层图像的特征点并进行分配ComputeKeyPointsOctTree(allKeypoints);

4.根据每层的特征点数量计算总特征点数量,并为描述子(Descriptors)分配内存。

5. 遍历金字塔的每一层。

   a.对当前层图像应用高斯模糊GaussianBlur(),得到workingMat。

   b.调用 computeDescriptors() 函数计算当前层的描述子(Descriptors)。

ORB-SLAM2源码学习:ORBextractor.cc:computeOrbDescriptor 计算描述子

   c.根据层级缩放特征点坐标,并将其添加到输出的 _keypoints 向量中。   

//因为遍历是一层一层进行的,但是描述子那个矩阵是存储整个图像金字塔中特征点的描述子,所以在这里设置了Offset变量来保存“寻址”时的偏移量,//辅助进行在总描述子mat中的定位int offset = 0;//开始遍历每一层图像for (int level = 0; level < nlevels; ++level){//获取在allKeypoints中当前层特征点容器的句柄vector<KeyPoint>& keypoints = allKeypoints[level];//本层的特征点数int nkeypointsLevel = (int)keypoints.size();//如果特征点数目为0,跳出本次循环,继续下一层金字塔if(nkeypointsLevel==0)continue;// preprocess the resized image// 深拷贝当前金字塔所在层级的图像Mat workingMat = mvImagePyramid[level].clone();// 注意:提取特征点的时候,使用的是清晰的原图像;这里计算描述子的时候,为了避免图像噪声的影响,使用了高斯模糊GaussianBlur(workingMat, 		//源图像workingMat, 		//输出图像Size(7, 7), 		//高斯滤波器kernel大小,必须为正的奇数2, 				//高斯滤波在x方向的标准差2, 				//高斯滤波在y方向的标准差BORDER_REFLECT_101);//边缘拓展点插值类型// Compute the descriptors 计算描述子// desc存储当前图层的描述子Mat desc = descriptors.rowRange(offset, offset + nkeypointsLevel);computeDescriptors(workingMat, 	//高斯模糊之后的图层图像keypoints, 	//当前图层中的特征点集合desc, 		//存储计算之后的描述子pattern);	//随机采样模板// 更新偏移量的值 offset += nkeypointsLevel;// Scale keypoint coordinates// 对于第0层的图像特征点,他们的坐标就不需要再进行恢复了if (level != 0){// 获取当前图层上的缩放系数float scale = mvScaleFactor[level];// 遍历本层所有的特征点for (vector<KeyPoint>::iterator keypoint = keypoints.begin(),keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)// 特征点本身直接乘缩放倍数就可以了keypoint->pt *= scale;}// And add the keypoints to the output// 将keypoints中内容插入到_keypoints 的末尾// keypoint其实是对allkeypoints中每层图像中特征点的引用,这样allkeypoints中的所有特征点在这里被转存到输出的_keypoints_keypoints.insert(_keypoints.end(), keypoints.begin(), keypoints.end());}

结束语

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词