• ORB-SLAM2学习1 convert.h Frame.h


    写在前面: 

      orb_slam是自己学习的第一个完整的开源slam系统,将自己的粗略理解写成博客,有理解不到位和出错的地方还望各位大神前辈指出。文中涉及的公式理论,主要是参考了ORB_SLAM论文和高博的视觉SLAM14讲,希望大家共同进步。博客的主要内容是对各个函数代码的理解,网上也有很多优秀的博客可以参考。

    如:

    http://www.cnblogs.com/shang-slam/

    http://www.fengbing.net/

    1.Convert.h

      这一头文件的作用是将g2o类型的数据,cv类型的数据,vector类型的数据进行转换。里面的实现都很简单,不必细说。

    2.Frame.h

      这个头文件里面包含了Frame类,论文中没有提到的是,这里实现的时候,讲图像划分成很多网格,网格里面对应有关键点,加快匹配。 

        1.Frame(const Frame &frame);
    

     复制构造函数.主要注意的事情:将frame中格子里面的东西一个个拷贝到当前帧,设置当前帧的位姿。

       2.Frame(const cv::Mat &imLeft, const cv::Mat &imRight, const double &timeStamp, ORBextractor* extractorLeft, ORBextractor* extractorRight, ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth);
    
       3.Frame(const cv::Mat &imGray, const cv::Mat &imDepth, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth);
    
       4.Frame(const cv::Mat &imGray, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth);

    构造函数:分别表示:双目,RGBD,和单目的构造函数。

    具体实现:首先给这帧图像一个编号mnId,然后确定将在这个图像金字塔的哪层提取特征,得到金字塔的系数。紧接着提取ORB特征,计算不失真的关键点,划分网格,将关键点分配到个个网格里面去用于加速匹配。

      // Extract ORB on the image. 0 for left image and 1 for right image.
      5  void ExtractORB(int flag, const cv::Mat &im);

      说明:提取图像的orb 特征,提取完之后,关键点存在了公共变量mvKeys中,描述子存在了公共变量mDescriptors中。

        // Compute Bag of Words representation.
      6 void ComputeBoW();

    说明:  计算该帧的ORB特征,输出的结果存放在了全局公共变量mBowVec,和mFeatVec中。mFeatVec是啥样子呢?- -> public std::map<NodeId, std::vector<unsigned int> >,也就是说这个特征向量里面是个map ,map 的第一个元素代表的是Node编号,第二个元素代表的是与第一个元素的NodeID对应的所有特征点的集合。意思就是,将特征点聚类起来了。。。。。。每一类我们都能知道有哪些特征点。(存的是第四层 (从叶子节点向上数)的节点里的特征点)

      7 void SetPose(cv::Mat Tcw);  

      设置当前帧的位资。

      8 void UpdatePoseMatrices();

      更新下,公共的R ,T ,O(相机的中心)

        // Returns the camera center.
      9  inline cv::Mat GetCameraCenter(){
            return mOw.clone();
        }
    
        // Returns inverse of rotation
     10 inline cv::Mat GetRotationInverse(){
            return mRwc.clone();
        }

    返回公共全局变量。

     11  bool isInFrustum(MapPoint* pMP, float viewingCosLimit);

    说明:判断地图点是不是在视锥里面,并将合适的地图点存起来,用于跟踪。两个参数都是输入。

    具体实现:第一步:计算这个地图点在世界坐标系下的坐标,然后经过变化,得到该点在相机坐标系下的坐标->得到像素坐标。

    第二步:检验计算观测角。啥叫观测角?观测角,就是两个向量的夹角,第一个向量是相机中心连接这个的点的空间三维点组成的向量,另一个向量是所有能看到这个点的帧的相机中心与空间三维点组成的向量的平均值向量。接下来就是说,如果该点的视差满足要求,这个点就能用于跟踪,然后再设置各种可以用来跟踪的参数。

      12  bool PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY);

    说明:posX, posY是输出的该关键点在格子中的位置。

    具体做法:该点横(纵)坐标减去,格子最小的横(纵)坐标,然后除以每个格子的宽(高)。

      13  vector<size_t> GetFeaturesInArea(const float &x, const float  &y, const float  &r, const int minLevel=-1, const int maxLevel=-1) const;

    说明: x, y, r 是输入,r表示的是离x,y多远处的范围minLevel,maxLevel,限定了一个金字塔范围,就是说每个格子里面的每个关键点,都得在这个金字塔层数范围内才能被选中输出到vector<size_t>里面。

     14 void ComputeStereoMatches();

    说明:这个函数是用于双目的时候,用于匹配左右两边图像的关键点的。结果改变的是两个公有变量 mvDepth 和mvuRight 。左右两边的关键点一旦匹配好了。就会计算出这个点(左边),深度,和与左边点匹配的右边点的ID。

    主 要实现:第一步:在右边图像的金字塔第0层找出行数nRows,然后生成一个二维数组大小是nRows*200,每行可以最多装200个关键点。

    第二步:讲右边图像的所有关键点按一定的标准放到这些行里面,然后匹配。这样做的目的是为了加快匹配。根据匹配好的结果,在右边关键点实际所在的金字塔层,又继续匹配,选出最好的匹配,(这里的实现没怎么看懂....),最后得到mvDepth ,和mvuRight.

      15  void ComputeStereoFromRGBD(const cv::Mat &imDepth);

     说明:就是将地图点与其深度对应起来。

      16  cv::Mat UnprojectStereo(const int &i);

    说明:返回的是,编号为 i的三维点在世界坐标系下的坐标加上相机中心的坐标。

    私有函数:

    1  void UndistortKeyPoints();

    说明:计算该帧关键点的去除畸变后的位置,在构造函数里面调用。结果放在了公有变量 mvKeyUn 中。这个函数主要调用OPENCV函数............

    2  void ComputeImageBounds(const cv::Mat &imLeft);

    说明:计算的是去除畸变后,图像的边界,在构造函数中调用。得到的是 mnMinX,mnMaxX,mnMinY,mnMaxY. 去除畸变之后的图像范围。。。

    具体做法:将图像的行数和列数(去除畸变之前图像最大的边界范围)按一定的顺序放到一个4*2的矩阵里,经过去畸变校准之后得到的东西,就是我们想要的去除畸变后的图像边界。

    3 void AssignFeaturesToGrid();

    说明:就是将这一帧的关键点,放入到我们划分的格子nGrid[i][j]中去。目的是加快匹配速度。在构造函数里面调用。

  • 相关阅读:
    谈谈JavaScript中继承方式
    《前端架构设计》学习笔记一--架构的种子
    正则中1的用法---反向引用
    JavaScript千分符---正则实现
    JavaScript开发中常用的代码规范配置文件
    前端开发流程---我们应该做些什么
    JavaScript中数据类型判断
    冒泡排序以及改进
    Number和toString中的坑
    Fluent Ribbon 第五步 ToolBar
  • 原文地址:https://www.cnblogs.com/panda1/p/7001052.html
Copyright © 2020-2023  润新知