ORB-SLAM2源码逐行解析系列(十二):ORB-SLAM2特征匹配之单目初始化中的特征匹配

1. ORBmatcher类的定义

class ORBmatcher
{
   
public:
    /**
     * 构造函数
     * @param nnratio     最优和次优评分的比例
     * @param checkOri    是否检查方向
     */
    ORBmatcher(float nnratio=0.6, bool checkOri=true);
    
    /**
     * @brief 计算地图点和候选投影点的描述子距离
     * @param[in] a     一个描述子
     * @param[in] b     另外一个描述子
     * @return int      描述子的汉明距离
     */
    static int DescriptorDistance(const cv::Mat &a, const cv::Mat &b);
    
    /**
     * @brief 通过投影地图点到当前帧,对Local MapPoint进行跟踪
     * 步骤
     * Step 1 遍历有效的局部地图点
     * Step 2 设定搜索窗口的大小。取决于视角, 若当前视角和平均视角夹角较小时, r取一个较小的值
     * Step 3 通过投影点以及搜索窗口和预测的尺度进行搜索, 找出搜索半径内的候选匹配点索引
     * Step 4 寻找候选匹配点中的最佳和次佳匹配点
     * Step 5 筛选最佳匹配点
     * @param[in] F                         当前帧
     * @param[in] vpMapPoints               局部地图点,来自局部关键帧
     * @param[in] th                        搜索范围
     * @return int                          成功匹配的数目
     */
    int SearchByProjection(Frame &F, const std::vector<MapPoint*> &vpMapPoints, 
                           const float th=3);
    
    /**
     * @brief 将上一帧跟踪的地图点投影到当前帧,并且搜索匹配点。用于跟踪前一帧
     * 步骤
     * Step 1 建立旋转直方图,用于检测旋转一致性
     * Step 2 计算当前帧和前一帧的平移向量
     * Step 3 对于前一帧的每一个地图点,通过相机投影模型,得到投影到当前帧的像素坐标
     * Step 4 根据相机的前后前进方向来判断搜索尺度范围
     * Step 5 遍历候选匹配点,寻找距离最小的最佳匹配点 
     * Step 6 计算匹配点旋转角度差所在的直方图
     * Step 7 进行旋转一致检测,剔除不一致的匹配
     * @param[in] CurrentFrame          当前帧
     * @param[in] LastFrame             上一帧
     * @param[in] th                    搜索范围阈值,默认单目为7,双目15
     * @param[in] bMono                 是否为单目
     * @return int                      成功匹配的数量
     */
    int SearchByProjection(Frame &CurrentFrame, const Frame &LastFrame, 
                           const float th, const bool bMono);

    /**
     * @brief 通过投影的方式将关键帧中的地图点投影到当前帧中,并且进行匹配
     * 
     * @param[in] CurrentFrame      当前帧
     * @param[in] pKF               关键帧
     * @param[in] sAlreadyFound     已经寻找得到的地图点
     * @param[in] th                窗口大小的阈值
     * @param[in] ORBdist           描述子最小距离阈值
     * @return int                  匹配到的点的数目
     */
    int SearchByProjection(Frame &CurrentFrame, KeyFrame* pKF, 
            const std::set<MapPoint*> &sAlreadyFound, const float th, const int ORBdist);
    
    /**
     * @brief 根据Sim3变换,将每个vpPoints投影到pKF上,并根据尺度确定一个搜索区域,
     * @detials 根据该MapPoint的描述子与该区域内的特征点进行匹配,如果匹配误差小于TH_LOW即匹配成功,更新vpMatched
     * @param[in] pKF               要投影到的关键帧
     * @param[in] Scw               相似变换
     * @param[in] vpPoints          空间点
     * @param[in] vpMatched         已经得到的空间点和关键帧上点的匹配关系
     * @param[in] th                搜索窗口的阈值
     * @return int                  匹配的特征点数目
     */
    int SearchByProjection(KeyFrame* pKF, cv::Mat Scw, const std::vector<MapPoint*> 
                           &vpPoints, std::vector<MapPoint*> &vpMatched, int th);
    
    /*
    * @brief 通过词袋,对关键帧的特征点进行跟踪
    * 步骤
    * Step 1:分别取出属于同一node的ORB特征点(只有属于同一node,才有可能是匹配点)
    * Step 2:遍历KF中属于该node的特征点
    * Step 3:遍历F中属于该node的特征点,寻找最佳匹配点
    * Step 4:根据阈值 和 角度投票剔除误匹配
    * Step 5:根据方向剔除误匹配的点
    * @param  pKF               KeyFrame
    * @param  F                 Current Frame
    * @param  vpMapPointMatches F中MapPoints对应的匹配,NULL表示未匹配
    * @return                   成功匹配的数量
    */
    int SearchByBoW(KeyFrame *pKF, Frame &F, std::vector<MapPoint*> &vpMapPointMatches);
    
    /**
     * @brief 单目初始化中用于参考帧和当前帧的特征点匹配
     * 步骤
     * Step 1 构建旋转直方图
     * Step 2 在半径窗口内搜索当前帧F2中所有的候选匹配特征点 
     * Step 3 遍历搜索窗口中的所有潜在的匹配候选点,找到最优的和次优的
     * Step 4 对最优次优结果进行检查,满足阈值、最优/次优比例,删除重复匹配
     * Step 5 计算匹配点旋转角度差所在的直方图
     * Step 6 筛除旋转直方图中“非主流”部分
     * Step 7 将最后通过筛选的匹配好的特征点保存
     * @param[in] F1                        初始化参考帧                  
     * @param[in] F2                        当前帧
     * @param[in & out] vbPrevMatched       本来存储的是参考帧的所有特征点坐标,该函数更新为匹配好
     *										的当前帧的特征点坐标
     * @param[in & out] vnMatches12         保存参考帧F1中特征点是否匹配上,index保存的是F1对应特
     *										征点索引,值保存的是匹配好的F2特征点索引
     * @param[in] windowSize                搜索窗口大小
     * @return int                          返回成功匹配的特征点数目
     */
    int SearchForInitialization(Frame &F1, Frame &F2, std::vector<cv::Point2f> &vbPrevMatched, std::vector<int> &vnMatches12, int windowSize=10);

    /**
     * @brief 利用基础矩阵F12,在两个关键帧之间未匹配的特征点中产生新的3d点
     * @param pKF1          关键帧1
     * @param pKF2          关键帧2
     * @param F12           基础矩阵
     * @param vMatchedPairs 存储匹配特征点对,特征点用其在关键帧中的索引表示,
     *						下标是关键帧1的特征点id,存储的是关键帧2的特征点id
     * @param bOnlyStereo   在双目和rgbd情况下,是否要求特征点在右图存在匹配
     * @return              成功匹配的数量
     */
    int SearchForTriangulation(KeyFrame *pKF1, KeyFrame* pKF2, cv::Mat F12,
              std::vector<pair<size_t, size_t> > 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值