ORB-SLAM2源码逐行解析系列(五):ORB-SLAM2中的ORB特征点后处理

1. 去畸变UndistortKeyPoints

/**
 * @brief 用内参对特征点去畸变,结果保存在mvKeysUn中
 * 
 */
void Frame::UndistortKeyPoints()
{
/*
    Step 1 判断是否有必要进行去畸变
	变量mDistCoef中存储了opencv指定格式的去畸变参数,格式为:(k1,k2,p1,p2,k3)
    第一个畸变参数k1是最重要的,一般不为0,为0的话,说明畸变参数都是0
    mvKeys是矫正前的特征点    mvKeysUn是矫正后的特征点
*/
    if(mDistCoef.at<float>(0)==0.0)
    {
        mvKeysUn=mvKeys;
        return;
    }
    
    // Step 2 根据opencv的去畸变函数格式,将待去畸变的特征点以cv::Mat的形式进行存储
    cv::Mat mat(N,2,CV_32F);
    for(int i=0; i<N; i++)
    {
		// 然后将这个特征点(需要去畸变的)的横纵坐标分别保存
        mat.at<float>(i,0)=mvKeys[i].pt.x;
        mat.at<float>(i,1)=mvKeys[i].pt.y;
    }
    
    // Step 3 调用opencv的cv::undistortPoints进行去畸变
    mat=mat.reshape(2);
    cv::undistortPoints(	
		mat,				// 输入的特征点坐标
		mat,				// 输出的校正后的特征点坐标,覆盖原矩阵
		mK,					// 相机的内参数矩阵
		mDistCoef,			// 相机畸变参数矩阵
		cv::Mat(),			// 一个空矩阵,对应为函数原型中的R
		mK); 				// 新内参矩阵,对应为函数原型中的P,将原内参矩阵覆盖掉
	
	// 调整回只有一个通道,回归我们正常的处理方式
    mat=mat.reshape(1);
    
    // Step 4 将去畸变后的点存储到mvKeysUn中
    mvKeysUn.resize(N);
    for(int i=0; i<N; i++)
    {
        cv::KeyPoint kp = mvKeys[i];
		// 读取校正后的坐标并覆盖老坐标(只对特征点的坐标进行矫正出处理,其他属性不变)
        kp.pt.x=mat.at<float>(i,0);
        kp.pt.y=mat.at<float>(i,1);
        mvKeysUn[i]=kp;  // 获取校正后的特征点
    }
}

2. 更新图像边界ComputeImageBounds

/**
 * @brief 计算去畸变图像的边界
 * 
 * @param[in] imLeft            需要计算边界的图像
 */
void Frame::ComputeImageBounds(const cv::Mat &imLeft)	
{
    // 如果畸变参数不为0,用OpenCV函数进行畸变矫正
    if(mDistCoef.at<float>(0)!=0.0)
	{
        // 保存矫正前的图像四个边界点坐标: (0,0) (cols,0) (0,rows) (cols,rows)
        cv::Mat mat(4,2,CV_32F);
        mat.at<float>(0,0)=0.0;         //左上
		mat.at<float>(0,1)=0.0;
        mat.at<float>(1,0)=imLeft.cols; //右上
		mat.at<float>(1,1)=0.0;
		mat.at<float>(2,0)=0.0;         //左下
		mat.at<float>(2,1)=imLeft.rows;
        mat.at<float>(3,0)=imLeft.cols; //右下
		mat.at<float>(3,1)=imLeft.rows;

        // Undistort corners
		// 和前面校正特征点一样的操作,将这几个(4个)边界点作为输入进行校正
        // 前面是对提取到的所有特征点进行矫正,这里是对4个边界点(mat)进行矫正
        mat=mat.reshape(2);
        cv::undistortPoints(mat,mat,mK,mDistCoef,cv::Mat(),mK);
        mat=mat.reshape(1);

		// 校正后的四个边界点已经不能够围成一个严格的矩形,因此在这个四边形的外侧加边框作为坐标的边界
        mnMinX = min(mat.at<float>(0,0),mat.at<float>(2,0));  // 左上和左下横坐标最小的
        mnMaxX = max(mat.at<float>(1,0),mat.at<float>(3,0));  // 右上和右下横坐标最大的
        mnMinY = min(mat.at<float>(0,1),mat.at<float>(1,1));  // 左上和右上纵坐标最小的
        mnMaxY = max(mat.at<float>(2,1),mat.at<float>(3,1));  // 左下和右下纵坐标最大的
    }
    else
    {
        // 如果畸变参数为0,就直接获得图像边界
        mnMinX = 0.0f;
        mnMaxX = imLeft.cols;
        mnMinY = 0.0f;
        mnMaxY = imLeft.rows;
    }
}

3. 将特征点分配到网格中AssignFeaturesToGrid

/**
 * @brief 将提取的ORB特征点分配到图像网格mGrid中, 后续会用到mGrid这个变量
 */
void Frame::AssignFeaturesToGrid()
{
    // Step 1  给存储特征点的网格数组 Frame::mGrid 预分配空间
	// nReserve表示每个网格中存储的特征点数
    int nReserve = 0.5f*N/(FRAME_GRID_COLS*FRAME_GRID_ROWS);  
    for(unsigned int i=0; i<FRAME_GRID_COLS;i++)
        for (unsigned int j=0; j<FRAME_GRID_ROWS;j++)
            mGrid[i][j].reserve(nReserve);

    // Step 2 遍历每个特征点,将每个特征点在mvKeysUn中的索引值放到对应的网格mGrid中
    for(int i=0;i<N;i++)
    {
		// 获取遍历到的特征点(去畸变后的)
        const cv::KeyPoint &kp = mvKeysUn[i];

		// 存储某个特征点所在网格的网格坐标
        // nGridPosX范围:[0,FRAME_GRID_COLS], nGridPosY范围:[0,FRAME_GRID_ROWS]
        int nGridPosX, nGridPosY;
		// 计算某个特征点所在网格的网格坐标
        // 如果找到特征点所在的网格坐标,记录在nGridPosX,nGridPosY里,返回true,没找到返回false
        if(PosInGrid(kp,nGridPosX,nGridPosY))
			// 如果找到特征点所在网格坐标,将这个特征点的索引添加到对应网格中
            mGrid[nGridPosX][nGridPosY].push_back(i);
    }
}

// PosInGrid的实现
/**
 * @brief 计算某个特征点所在网格的网格坐标,如果找到特征点所在的网格坐标,记录在nGridPosX,nGridPosY里,返回true,没找到返回false
 * 
 * @param[in] kp                    给定的特征点
 * @param[in & out] posX            特征点所在网格坐标的横坐标
 * @param[in & out] posY            特征点所在网格坐标的纵坐标
 * @return true                     如果找到特征点所在的网格坐标,返回true
 * @return false                    没找到返回false
 */
bool Frame::PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY)
{
/*
	计算特征点x,y坐标落在哪个网格内,网格坐标为posX,posY
    mfGridElementWidthInv=(FRAME_GRID_COLS)/(mnMaxX-mnMinX);
    mfGridElementHeightInv=(FRAME_GRID_ROWS)/(mnMaxY-mnMinY);
    (kp.pt.x-mnMinX) / (mnMaxX-mnMinX): 表示当前特征点在图像x方向的比例
    (kp.pt.x-mnMinX) / (mnMaxX-mnMinX) * (FRAME_GRID_COLS): 表示当前特征点的x方向属于图像所划分的哪一个网格
*/
    posX = round((kp.pt.x-mnMinX)*mfGridElementWidthInv); 
    // (kp.pt.y-mnMiny) / (mnMaxY-mnMinY): 表示当前特征点在图像y方向的比例
    // (kp.pt.y-mnMiny) / (mnMaxY-mnMinY) * (FRAME_GRID_COLS): 表示当前特征点的y方向属于图像所划分的哪一个网格  
    posY = round((kp.pt.y-mnMinY)*mfGridElementHeightInv);

    // 因为特征点进行了去畸变,而且前面计算是round取整,所以有可能得到的点落在图像网格坐标外面
    // 如果网格坐标posX,posY超出了[0,FRAME_GRID_COLS] 和[0,FRAME_GRID_ROWS],表示该特征点没有对应网格坐标,返回false
    if(posX<0 || posX>=FRAME_GRID_COLS || posY<0 || posY>=FRAME_GRID_ROWS)
        return false;

	// 计算成功返回true
    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ORB-SLAM2是一款基于特征点SLAM算法,可以在实时运行实现稠密地图的构建和定位。ORB-SLAM2的源代码解析v1.2 pdf为ORB-SLAM2算法的源代码进行详细讲解的文档。 这个文档详细介绍了ORB-SLAM2算法的各个模块以及其组成部分,包括图像预处理、特征点提取、视觉里程计、回环检测、地图构建和定位等。对于每个模块,文档都进行了详细的讲解,并展示了一些代码实现和示例。 其ORB特征点的提取是ORB-SLAM2的一个重要特点。文档详细介绍了ORB特征点的提取与描述,并对其进行了性能优化。在视觉里程计,文档详细介绍了基于ORB-SLAM2的相机位姿估计算法,并同时对其进行了实验验证。 此外,orb-slam2源码解析 v1.2 pdf还对ORB-SLAM2的一些扩展进行了介绍,如RGBD-SLAM、半稠密点云地图构建、直接法视觉里程计等等。 总之,ORB-SLAM2是一个非常强大的SLAM算法,通过对orb-slam2源码解析 v1.2 pdf的学习,可以更好地理解其原理和实现,也为进一步研究和应用提供了参考。 ### 回答2: ORB-SLAM2是一种基于单目相机的实时稠密SLAM系统,被广泛应用于机器人、自动驾驶、增强现实等领域。ORB-SLAM2源码解析v1.2 pdf是一份PDF文档,对ORB-SLAM2源代码进行了详细的解析和分析。 该文档分为多个章节,首先介绍了ORB-SLAM2的概述和背景,包括SLAM系统的基本原理和ORB特征点的提取与匹配算法。接着,文档对ORB-SLAM2的系统框架、流程和算法进行了详细介绍,主要包括定位、建图、闭环检测和重定位等核心模块的实现细节。 文档还对ORB-SLAM2的实验结果和性能进行了评估和分析,包括系统的重定位精度、建图质量、算法复杂度和实时性等指标。同时,文档还针对ORB-SLAM2的应用场景进行了讨论和展望,包括基于ORB-SLAM2的三维重建、SLAM与深度学习的融合等前沿研究方向。 总之,ORB-SLAM2源码解析v1.2 pdf是一份非常有价值的文档,对想要深入了解和应用ORB-SLAM2的研究者和开发者有很大的帮助和启发作用。它不仅详细介绍了ORB-SLAM2的理论基础和实现细节,还从实验和应用角度对其性能和前景进行了评估和展望,为相关领域的技术人员提供了重要的参考和指导。 ### 回答3: ORB-SLAM2是一种基于单目或双目相机的实时视觉SLAM系统,可以在无GPS信号的情况下,通过对相机的位置和姿态的估计,构建3D环境地图。 ORB-SLAM2源码解析 v1.2 PDF是一份解析ORB-SLAM2源码的文档,其包含了ORB-SLAM2的基本架构、算法实现以及关键代码的详细解释。通过学习该文档,可以深入了解ORB-SLAM2的原理和实现方法,从而更好地应用该系统进行SLAM操作。 该文档主要包括以下几个部分: 1.ORB-SLAM2的系统结构:介绍ORB-SLAM2的整体结构和各模块之间的关系。 2.特征提取与匹配:详细介绍ORB特征的提取和匹配算法,包括ORB算法原理、特征对齐和描述符生成等。 3.全局BA和回环检测:讲解ORB-SLAM2的全局优化和回环检测方法,其包括BA算法流程、优化目标函数、回环检测的实现等。 4.实时定位:探讨如何实现ORB-SLAM2的实时运动估计和位姿估计,包括相机位姿估计、尺度恢复和点云重建等内容。 除此之外,该文档还对ORB-SLAM2的一些高级技术进行了讲解,如基于深度学习的特征提取、基于语义信息的地图构建等。 总之,该文档是一份非常有价值的ORB-SLAM2源码解析资料,对于深入了解ORB-SLAM2的实现原理、优化方法和应用场景,具有重要的参考意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值