VINS-Mono+Fusion源码解析系列(十三):纯视觉SFM

1. 视觉SFM理论

 假设滑窗中一共有11帧,首先需要选取一个枢纽帧,利用枢纽帧和最后一帧通过对极约束求出这两帧之间的相对位姿。对枢纽帧的要求是:一方面要求枢纽帧离最后一帧尽可能远,因为离最后一帧比较近时,二者之间的平移比较小,使得三角化精度较差,甚至会无法进行对极约束(平移为零的情况)。另一方面,要求枢纽帧与最后一帧之间不能距离太远,否则会使得二者之间关联的特征点比较少,导致求解出的位姿可信度不高,并且无法三角化出尽可能多的点。因此,在保证匹配点足够多的情况下,枢纽帧离最后一帧应该尽可能远,如下图中选取第4帧作为枢纽帧。

​ 将枢纽帧设为参考帧,其位姿设置:旋转为单位阵 I I I,平移为0。通过对极几何求出枢纽阵(4)和最后一帧(10)之间的相对位姿R和t(尺度未知)。由于第4帧的位姿为 ( I , 0 ) (I,0) (I,0),那么第10帧的位姿就是二者之间的相对位姿 ( R , t ) (R,t) (R,t)。然后,在已知位姿之后,通过三角化求出这两帧之间的共视点(带尺度的)。由于光流追踪的性质,求出的第4帧与第10帧之间的共视点也会被中间的第5—9帧所看到,那么在已知这些共视点(3D)和第4帧的关键点(2D)之后,通过PnP的方法(3D-2D)求解出第5帧的位姿。按照同样的方法,通过三角化获取更多的共视点,通过PnP求出枢纽帧(4)和最后一帧(10)之间的每一帧(5—9)的位姿。

​ 枢纽帧(4)与第一帧(0)之间的位姿和共视点求取按照同样的方法,先根据对极几何求出第0帧和第4帧的相对位姿,由于第4帧的位姿为 ( I , 0 ) (I,0) (I,0),那么求出的相对位姿就是第0帧的位姿。然后通过三角化求出第0帧与第4帧之间的共视点,根据光流追踪的性质,这些点都会被第1—3帧所看到。然后通过PnP的方法求出第1帧的位姿,以此类推,通过三角化获取更多的共视点,通过PnP求出第2、3帧的位姿。

​ 通过对滑窗进行上述操作,可求出滑窗中每一帧的位姿和所看到的3D共视点。
视觉SFM

2. 获取枢纽帧并计算相对位姿relativePose

(1)大致流程

  • 遍历滑窗中的每一帧,通过f_manager获取遍历到的当前帧与最后一帧之间的匹配对
  • 通过f_manager直接获取这一匹配对的共视点个数,在共视点个数超过20个的前提下,执行如下操作:
    • 获取每个共视点在各自帧中的像素坐标,根据像素坐标计算出其视差,进而计算出所有共视点的平均视差
    • 结合虚拟相机焦距(460像素/mm),满足平均视差超过30个像素(这样保证枢纽帧与最后一帧具有足够的距离)的当前帧作为枢纽帧
    • 然后,通过对极约束,调用solveRelativeRT计算出枢纽帧与滑窗中最后一帧之间的相对位姿

(2)代码实现

/**
 * @brief 寻找滑窗内一个帧作为枢纽帧,要求和最后一帧既有足够的共视也要有足够的视差
 *        并求出枢纽帧与滑窗中最后一帧之间的相对位姿
 *
 * @param[in] relative_R 
 * @param[in] relative_T 
 * @param[in] l 
 * @return true 
 * @return false 
 */

bool Estimator::relativePose(Matrix3d &relative_R, Vector3d &relative_T, int &l)
{
   
    // 优先从最前面开始遍历,确定哪一帧能够选定为枢纽帧
    for (int i = 0; i < WINDOW_SIZE; i++)
    {
   
        vector<pair<Vector3d, Vector3d>> corres;
        // corres表示第i帧与最后一帧WINDOW_SIZE同时观测到的3D点在各自归一化坐标系下的投影点
        corres = f_manager.getCorresponding(i, WINDOW_SIZE); 
        // 要求共视的特征点足够多
        if (corres.size() > 20)  // 若第i帧与最后一帧的共视点个数 大于 20
        {
   
            double sum_parallax = 0;
            double average_parallax;
            for (int j = 0; j < int(corres.size()); j++)
            {
    
                // 第j个共视点在当前第i帧中的像素坐标(u, v)
                Vector2d pts_0(corres[j].first(0), corres[j].first(1));   
                // 第j个共视点在最后一帧中的像素坐标(u, v)
                Vector2d pts_1(corres[j].second(0), corres[j].second(1));  
                double parallax = (pts_0 - pts_1).norm();   // 计算二者之间的视差
                sum_parallax = sum_parallax + parallax;     // 求所有共视点的视差和

            }
            // 计算两帧之间共视点的平均视差
            average_parallax = 1.0 * sum_parallax / int(corres.size());
/*
   要求平均视差在虚拟相机的焦距(460像素/mm)中 大于 30,就认为当前帧i与最后一帧之间具有足够的视差
   不同相机的视差判断阈值就不一样,这里使用虚拟相机焦距,使得视差阈值统一为30个像素
   然后,利用对极约束,通过本质矩阵恢复枢纽帧和最后一帧之间的相对位姿 R t ————  solveRelativeRT
*/
            if(average_parallax * 460 > 30 && 
               				m_estimator.solveRelativeRT(corres, relative_R, relative_T))
            {
   
              // 枢纽帧: 既与最后一帧有足够的视差,又能够使用对极约束成功计算出与最后一帧之间的相对位姿
                l = i; 
                return true;
            }
        }
    }
    return false;
}

(3)对极约束求解相对位姿

大致流程

  • 首先,在共视特征点匹配对个数不少于15的前提下,获取输入的两关键帧的共视特征点匹配对
  • 根据两关键帧上的匹配像素点,调用opencv函数cv::findFundamentalMat计算本质矩阵E
  • 调用opencv函数cv::recoverPose,根据本质矩阵恢复出位姿R和t,并返回内点个数(用于衡量匹配点中满足求解出的R和t的点的个数)
  • 求解出的位姿是cv::Mat格式的R21和t21,先将其转换成eigen格式,然后通过下面推导出的公式,将其转换成R12和t12。并且,只有当内点个数超过12时,求解出的R12和t12才有效。

​ 假设第一帧的位姿为单位矩阵,要求第二帧位姿,则相对位姿 R 21 R_{21} R21 t 21 t_{21} t21就是第二帧的位姿。二者之间的转换关系推导如下:
P 1 = R 12 ⋅ P 2 + t 12            P 2 = R 21 ⋅ P 1 + t 21 ⇒ R 12 T ⋅ P 1 = P 2 + R 12 T ⋅ t 12       P 2 = R 12 T ⋅ P 1 − R 12 T ⋅ t 12 ⇒ R 21 = R 12 T       t 21 = − R 12 T ⋅ t 12 ⇒ R 12 = R 21 T       t 12 = − R 21 T ⋅ t 21 P_1 = R_{12} \cdot P_2 + t_{12} \ \ \ \ \ \ \ \ \ \ P_2 = R_{21} \cdot P_1 + t_{21} \\ \Rightarrow \\ R_{12}^T \cdot P_1 = P_2 + R_{12}^T \cdot t_{12} \ \ \ \ \ P_2 = R_{12}^T \cdot P_1 - R_{12}^T\cdot t_{12} \\ \Rightarrow \\ R_{21} = R_{12}^T\ \ \ \ \ t_{21} = -R_{12}^T \cdot t_{12} \\ \Rightarrow \\ R_{12} = R_{21}^T\ \ \ \ \ t_{12} = -R_{21}^T \cdot t_{21} P1=R12P2+t12          P2=R21P1+t21R12TP1=P2+R12Tt12     P2=R12TP1R12Tt12R21=R12T     t21=R12Tt12R12=R21T     t12=R21Tt21
代码实现

/**
 * @brief 根据两帧匹配对求解R和带尺度的t
 * 
 * @param[in] corres        两帧的匹配对
 * @param[out] Rotation     求解出的相对旋转
 * @param[out] Translation  求解出的相对平移
 * @return true 
 * @return false 
 */

bool MotionEstimator::solveRelativeRT(const vector<pair<Vector3d, Vector3d>> &corres, Matrix3d &Rotation, Vector3d &Translation)
{
   
    if (corres.size() >= 15)  // 两帧的匹配点对至少要有15个
    {
   
        vector<cv::Point2f> ll, rr;  // 获取匹配点对的坐标
        for (int i 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
地形数据测量是许多地貌研究应用程序的基本方面,尤其是那些包括地形监测和地形变化研究的应用程序。然而,大多数测量技术需要相对昂贵的技术或专门的用户监督。 MotionSfM)摄影测量技术的结构通过允许使用消费级数码相机和高度自动化的数据处理(可以免费使用)减少了这两个限制。因此,SfM摄影测量法提供了快速,自动化和低成本获取3D数据的可能性,这不可避免地引起了地貌界的极大兴趣。在此贡献中,介绍了SfM摄影测量的基本概念,同时也承认了其传统。举几个例子来说明SfM在地貌研究中的应用潜力。特别是,SfM摄影测量为地貌学家提供了一种工具,用于在一定范围内对3-D形式进行高分辨率表征,并用于变化检测。 SfM数据处理的高度自动化既创造了机遇,也带来了威胁,特别是因为用户控制倾向于将重点放在最终产品的可视化上,而不是固有的数据质量上。因此,这项贡献旨在指导潜在的新用户成功地将SfM应用于一系列地貌研究。 关键词:运动结构,近距离摄影测量,智能手机技术,测量系统,表面形态echnology reduces both these constraints by allowing the use of consumer grade digital cameras and highly automated data processing, which can be free to use. SfM photogrammetry therefore offers the possibility of fast, automated and low-cost acquisition of 3-D data, which has inevitably created great interest amongst the geomorphological community. In this contribution, the basic concepts of SfM photogrammetry are presented, whilst recognising its heritage. A few examples are employed to illustrate the potential of SfM applications for geomorphological research. In particular, SfM photogrammetry offers to geomorphologists a tool for high-resolution characterisation of 3-D forms at a range of scales and for change detection purposes. The high level of automation of SfM data processing creates both opportunities and threats, particularly because user control tends to focus upon visualisation of the final product rather than upon inherent data quality. Accordingly, this contribution seeks to guide potential new users in successfully applying SfM for a range of geomorphic studies.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值