2D-2D相机位姿估计

本文将介绍如何根据相机在不同位置拍摄的两张图片恢复出相机的运动。在多视图几何学中,这被称为对极几何。

一、对极几何

如下图所示,相机在两个不同的位置(蓝色位置和绿色位置)同时观测到了同一个点X。根据上一篇文章《OpenCV提取ORB特征并匹配》,我们可以将X在两个相机平面上的投影x点和x'点的像素坐标匹配起来。此时,x和x'便满足一个约束,称为对极约束。

对极约束的数学推导并不复杂,本文为求简明和实用,对此不做细究。更多内容可以参考文末列出的参考资料。这里只给出直观的解释。

相机在两个位置的光心分别为O点和O'点,连线OO'与两个成像平面的交点分别为e点和e'点。我们把线段xe和x'e'称为极线。下面我们来分析为什么利用两张图片中特征点对的像素坐标可以恢复相机运动和地图点X的深度(X点的深度估计将在下篇文章中介绍)。

假设左侧相机固定,右侧相机位姿待估计。那么OX射线方向确定,同时,OX在右侧相机平面上的投影也随之确定,即直线l'。这一投影关系便称为对极约束。不过,单个对极约束并不能完全确定右侧相机的位置,大家可以想象右侧相机平面如何在保持x'坐标不变的情况下调整自己的姿态。换句话说,对极约束是有多个自由度的,一对匹配点并不能唯一确定两个相机的位姿。那到底需要多少对点呢?数学上可以证明,至少需要5对。而实际应用中通常使用8对以简化计算过程,称为“八点法”。下面就进入实际代码环节,不在理论上过多纠缠了。

二、2D-2D相机位姿估计

从两张2D图像估计相机位姿的流程如下图所示。

其中有一处分叉点,分别适用于不同的情况。左侧“计算基础矩阵或本质矩阵”适用于特征点不共面的情况;右侧“计算单应矩阵”适用于特征点共面的情况(比如墙壁、地面、航拍等场合)。

下面只给出2D-2D相机位姿估计函数的代码,特征点匹配部分的代码在上一篇文章中可以找到。

完整代码的下载地址:https://github.com/jingedawang/FeatureMethod

void pose_estimation_2d2d ( std::vector<KeyPoint> keypoints_1,
                            std::vector<KeyPoint> keypoints_2,
                            std::vector< DMatch > matches,
                            Mat& R, Mat& t )
{
    // 相机内参,TUM Freiburg2
    Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );

    //-- 把匹配点转换为vector<Point2f>的形式
    vector<Point2f> points1;
    vector<Point2f> points2;

    for ( int i = 0; i < ( int ) matches.size(); i++ )
    {
        points1.push_back ( keypoints_1[matches[i].queryIdx].pt );
        points2.push_back ( keypoints_2[matches[i].trainIdx].pt );
    }

    //-- 计算基础矩阵
    Mat fundamental_matrix;
    fundamental_matrix = findFundamentalMat ( points1, points2, CV_FM_8POINT );
    cout<<"fundamental_matrix is "<<endl<< fundamental_matrix<<endl;

    //-- 计算本质矩阵
    Point2d principal_point ( 325.1, 249.7 );   //相机光心, TUM dataset标定值
    double focal_length = 521;          //相机焦距, TUM dataset标定值
    Mat essential_matrix;
    essential_matrix = findEssentialMat ( points1, points2, focal_length, principal_point );
    cout<<"essential_matrix is "<<endl<< essential_matrix<<endl;

    //-- 计算单应矩阵
    Mat homography_matrix;
    homography_matrix = findHomography ( points1, points2, RANSAC, 3 );
    cout<<"homography_matrix is "<<endl<<homography_matrix<<endl;

    //-- 从本质矩阵中恢复旋转和平移信息.
    recoverPose ( essential_matrix, points1, points2, R, t, focal_length, principal_point );
    cout<<"R is "<<endl<<R<<endl;
    cout<<"t is "<<endl<<t<<endl;
    
}

这里需要解释一下,基础矩阵和本质矩阵都是3×3的矩阵,它们之间不过是差了个相机内参,因此使用时效果完全一样。上边的代码使用了本质矩阵来恢复相机运动,而没有用单应矩阵,这是因为示例图片中的特征点并不共面。在实际应用中,如果事先无法知道特征点是否共面,则应当同时计算本质矩阵和单应矩阵,选择重投影误差比较小的那个作为最终的运动估计矩阵,具体操作敬请期待后续系列文章。

三、进一步讨论

2D-2D相机位姿估计是单目SLAM初始化时的关键技术。初始化成功之后,后续的视频帧就可以采用3D-2D匹配来简化计算过程。因此初始化成功与否对SLAM至关重要。

从单目SLAM的角度考虑,2D-2D相机位姿估计存在以下三个敏感的问题:

  1. 尺度不确定性
    用上面的方法估计出的相机平移向量t的值并没有单位,也就是说相机移动的距离只有相对值,没有绝对值。这是单目相机固有的尺度不确定性问题,无法从根本上解决。因此单目SLAM中一般把初始化后的t归一化,即把初始化时移动的距离默认为1,此后的距离都以这个1为单位。

  2. 初始化的纯旋转问题
    单目初始化不能只有旋转,必须要有一定程度的平移,否则由于t趋近于0,导致无从求解R或者误差非常大。

  3. 多于8对点的情况
    如果匹配的点对数多于8(大多数情况都是这样),可以考虑充分利用这些点,而不是只从中选择8对用于计算。推荐的算法是随机采样一致性(Random Sample Consensus,RANSAC),该算法可以有效地避免错误数据对整体结果的影响。在代码中,只需要将findFundamentalMat函数的第三个参数从CV_FM_8POINT换成CV_FM_RANSAC就可以了。

四、参考资料

《视觉SLAM十四讲》第7讲 视觉里程计1 高翔
本质矩阵和基础矩阵的区别是什么? 知乎

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 本文首先介绍如何使用OpenCV中的PnP求解3D-2D位姿变换,再介绍如何使用g2o对前面得出的结果进行集束调整...
    金戈大王阅读 10,402评论 5 6
  • 在上一篇文章中,我们介绍了3D-2D相机位姿估计,采用PnP方法估计单目SLAM的相机位姿。而对于RGBD深度相机...
    金戈大王阅读 6,776评论 0 2
  • 1. 前言 开始做SLAM(机器人同时定位与建图)研究已经近一年了。从一年级开始对这个方向产生兴趣,到现在为止,...
    壹米玖坤阅读 1,136评论 4 8
  • 前面用了好几篇文章介绍特征点法的相机位姿估计,本文则换一种思路,介绍近年来日渐流行的直接法。 一、直接法 与“光流...
    金戈大王阅读 6,186评论 0 1
  • 第一篇米兰·昆德拉写的文章就让我惊叹,这个作家的脑洞还真是别开生面。他的长篇《生命不能承受之轻》是我很喜欢的作品,...
    仙姑的碎碎念阅读 708评论 0 0