首页 > 代码库 > ORB-SLAM2学习4 initializer.h

ORB-SLAM2学习4 initializer.h

orb-slam2   Inlitializer.h  头文件的学习

a.预备知识,主要读取了作者的论文。 

  作者在论文中提到,这个头文件定义的东西全是用于单目的,双目和RGBD不需要初始化。地图初始化的目的就是得到两帧的相对运动,R  T,  然后根据 R T 和这两帧匹配好的关键点,三角化出初始的三   维地图。论文里面提到了一共有5步。

  1.在当前帧与参考帧之间提取ORB特征,就行匹配。

  2.开启两个同步线程,同时计算H矩阵和F矩阵,H=homography 用于特征点都是在同平面的情况,F=fundomental 用于特征点不在同一平面的情况。代码中使用8个点就能恢复出想要的H 和F,具体怎么处理   呢?代码中随机的选8个点,(当前帧和参考帧的8个匹配好的点对,一共8对),一共挑选选200次,选出得分最高的H,F。这里得分如何计算?作者论文中详细的提到了计算方法。

                                                                 技术分享

  具体解释:M可取F H。我们以M=F为例,首先看到的是,SF是一个累加。因为选了8个点,所以累加8次。ρF的计算已经给出来了。这里最重要的是d2 的计算, 就是指把第一帧里面的每一个选中的点,重投影到第二帧后得到的重投影误差,平方,和第二帧里面选中的投影到第一帧里面形成的重投影误差,平方。然后Γ 取的是5.99.这里就计算得到了得分。

 

  3.模型选择选H还是F。

                                            

                                                                           技术分享

        RH>0.45选择H,否则选择F

 

      4,恢复出运动和地图的三维结构

   意思就是从H,或者F中分解出R 和 T ,然后根据R T 三角化匹配好的关键点,得到这些关键点的3D坐标。这就是所谓的初始化地图。

        5 .BA

b.各个函数解释。

 

公共函数:

1.     Initializer(const Frame &ReferenceFrame, float sigma = 1.0, int iterations = 200);

 

 构造函数:给出参考帧,和迭代系数。

 

2.     bool Initialize(const Frame &CurrentFrame, const vector<int> &vMatches12,
                    cv::Mat &R21, cv::Mat &t21, vector<cv::Point3f> &vP3D, vector<bool> &vbTriangulated);

        a.@const Frame &CurrentFrame:输入的参考帧。                         b.@const vector<int> &vMatches12:输入的匹配。

        c.  @cv::Mat &R21                          输出的motion                            d @cv::Mat &t21                                  输出的motion 

        e.@vector<cv::Point3f> &vP3D:输出的三维地图也就是初始化的地图。f:@vector<bool> &vbTriangulated) 输出。

 

具体实现: 首先是找到参考帧和当前帧的配对关系。把这个一一对应关系放入mvMatches12.push_back(make_pair(i,vMatches12[i])).中。然后构造一个200行8列的二维数组vector<vector<size_t> > mvSets   。最后就是开启两个个线程计算H,F,得到想要的结果。

 

私有函数:

3 .void FindHomography(vector<bool> &vbMatchesInliers, float &score, cv::Mat &H21);
4 .void FindFundamental(vector<bool> &vbInliers, float &score, cv::Mat &F21);

首先:3个参数全部都是输出。

具体实现:两个函数实现都是一样的。首先就是将第一帧的关键点和第二帧的关键点全部normalize. 循环200次,分别计算出每次循环的得分,找出最高的得分。以及最高得分对应的H(F),vbMatchesInliers(vbInliers)。

 

 

5.cv::Mat ComputeH21(const vector<cv::Point2f> &vP1, const vector<cv::Point2f> &vP2);
6.cv::Mat ComputeF21(const vector<cv::Point2f> &vP1, const vector<cv::Point2f> &vP2);

首先:两个参数都是输入,输出的就是H,F矩阵。

具体的实现:其实就是根据8个点对,由对极约束或者是,H的约束,来获得H F。具体可看高博的十四讲。

 

 

7. float CheckHomography(const cv::Mat &H21, const cv::Mat &H12, vector<bool> &vbMatchesInliers, float sigma);

 8.float CheckFundamental(const cv::Mat &F21, vector<bool> &vbMatchesInliers, float sigma);

首先:输入 H(F),sigama.输出的是在这种H(F)下的得分,和vbMatchesInliers。

具体实现:见a.预备知识里面的2.

 

 

 9.bool ReconstructF(vector<bool> &vbMatchesInliers, cv::Mat &F21, cv::Mat &K,
                      cv::Mat &R21, cv::Mat &t21, vector<cv::Point3f> &vP3D, vector<bool> &vbTriangulated, float minParallax, int minTriangulated);

 10.bool ReconstructH(vector<bool> &vbMatchesInliers, cv::Mat &H21, cv::Mat &K,
                      cv::Mat &R21, cv::Mat &t21, vector<cv::Point3f> &vP3D, vector<bool> &vbTriangulated, float minParallax, int minTriangulated);

首先:1@ vector<bool> &vbMatchesInliers:输入参数。2@ cv::Mat &F21:输入参数,计算得到的F矩阵   3@ cv::Mat &K:输入参数,代表相机参数。4 @cv::Mat &R21:输出的R。  5 @cv::Mat &t21:输出的t   6 @ vector<cv::Point3f> &vP3D:输出的3D点。7 @ vector<bool> &vbTriangulated:输出。表示点是不是三角化了。8@float minParallax:输入,最小的视差。9@ int minTriangulated 输入。

具体解释:我们知道的从E,H中直接分解出R T 是不唯一的,会分解出4种(8种)情况,这两个函数就是根据一些手段,和先验知识恢复得到正确唯一的R  T。

 

 

 11.void Triangulate(const cv::KeyPoint &kp1, const cv::KeyPoint &kp2, const cv::Mat &P1, const cv::Mat &P2, cv::Mat &x3D);

首先:1 @const cv::KeyPoint &kp1:输入的第一帧关键点。                                    2 @const cv::KeyPoint &kp2:输入与第一帧匹配的第二帧关键点 。

           3 @ const cv::Mat &P1 :第一帧的相机参数K*T。                                          4 @: const cv::Mat &P2 .第二帧的相机参数K*T。  

            5 @:cv::Mat &x3D   输出的三角化的点。

 

 

12.void Normalize(const vector<cv::KeyPoint> &vKeys, vector<cv::Point2f> &vNormalizedPoints, cv::Mat &T);

首先:1 @ const vector<cv::KeyPoint> &vKeys. 输入的关键点。2 @:vector<cv::Point2f> &vNormalizedPoints:输出的点。3 @:cv::Mat &T:输出的T,在  void FindHomography(vector<bool> &vbMatchesInliers, float &score, cv::Mat &H21);void FindFundamental(vector<bool> &vbInliers, float &score, cv::Mat &F21);函数里面用到了。

 

具体实现:首次先算出输入所有关键点的平均值meanX,meanY(关键点x,y的平均值)
                  其次每个关键点的x,y与这个平均值meanX,meanY做差。将所有的差绝对值加起来求平均值
                  得到meanDevX,meanDevY.   讲上面那些差除以meanDevXm,meanDevY,就得到输出的vNormalizedPoints

 

 

 13.int CheckRT(const cv::Mat &R, const cv::Mat &t, const vector<cv::KeyPoint> &vKeys1, const vector<cv::KeyPoint> &vKeys2,
                       const vector<Match> &vMatches12, vector<bool> &vbInliers,
                       const cv::Mat &K, vector<cv::Point3f> &vP3D, float th2, vector<bool> &vbGood, float &parallax);

首先:1 @ const cv::Mat &R,  输入1->2                                                       2 @ const cv::Mat &t :输入 1->2                                   3 @ const vector<cv::KeyPoint> &vKeys1  输入         

           4 @ const vector<cv::KeyPoint> &vKeys2:输入                             5 @ const vector<Match> &vMatches12  :输入           6 @ vector<bool> &vbInliers :输入      

           7 @  const cv::Mat &K :相机参数输入                                              8 @ vector<cv::Point3f> &vP3D 输出                             9 @ float th2  :输入(重投影误差的平方误差) 

          10 @ vector<bool> &vbGood :输出                                                     11 @ float &parallax  :输出视差。

 

具体实现:首先将第一个相机放在原点。构造两个3X4的矩阵。其等于相机参数K 乘以这帧的T。然后得到第二个相机中心在第一个相机坐标系(可以看成世界坐标系)下的坐标。然后进入一个循环,循环每次都要计算视差。啥叫视差?首先计算匹配好的点在世界坐标系下(第一个相机坐标系下)的3D坐标,从第一个相机中心出发连接这个3D点得到一条射线,从第二个相机的中心出发连接这个3 D点得到一条射线,这两条射线之间的夹角就是视差(parallax),检测视差,分别检测两帧下的深度,和重投影误差。返回3D点。因为没对返回视差。

 

 

14.void Initializer::DecomposeE(const cv::Mat &E, cv::Mat &R1, cv::Mat &R2, cv::Mat &t)

 

 首先: 1 @ const cv::Mat &E :输入        2 @ cv::Mat &R1 :输出       3 @ cv::Mat &R2  :输出        4 @ cv::Mat &t  :输出

 

 具体解释:就是分解E

ORB-SLAM2学习4 initializer.h