SLAM中的三角测量

2023-05-16

【来源】视觉SLAM十四讲,作者 高翔

三角测量是SLAM中,利用相机运动估计特征点空间位置的过程。

本节旨在解决以下问题:

  1. 三角测量的概念
  2. 三角测量的过程及代码实现;
  3. 三角测量有哪些不确定性
  4. 如何提高三角测量的精度

1. 概念

在SLAM中,利用对极几何约束估计相机运动之后,我们还需要通过三角测量来估计地图点的深度。三角测量(三角化)指的是,通过在两处观测同一个点的夹角,从而确定该点的距离。

SLAM中主要用三角化来估计像素点的距离。

image-20200324165223362

2. 过程

按照对极几何的定义,设$x_1,x_2$为两个特征点的归一化坐标,那么他们满足:
$$
s_1x_1=s_2Rx_2+t.
$$
经过对极几何之后,已得到了运动$R,t$,需要求解两个特征点的深度$s_1$,$s_2$。

两个深度可以分开算。若先算$s_2$,那么对上市两个做成一个$x_1$^,得:

image-20200324170444757

该式子左侧为0,右侧可看成是$s_2$的一个方程,可以根据它直接求$s_2$。有了$s_2$,$s_1$也非常容易求出。预测就可以得到两帧下的深度,即确定了空间坐标。

3. 代码实现;

void triangulation (
	const vector<KeyPoint>& keypoint_1,
	const vector<KeyPoint>& keypoint_2,
	const std::vector< DMatch >& matches,
	const Mat& R, const Mat& t,
	vector<Point3d>& points
);

void triangulation (
	const vector< KeyPoint >& keypoint_1,
	const vector< KeyPoint >& keypoint_2,
	const std::vector< DMatch >& matches,
	const Mat& R, const Mat& t,
	vector< Point3d >& points )
{
	Mat T1 = (Mat_<double> (3,4) <<
	1,0,0,0,
	0,1,0,0,
	0,0,1,0);
	Mat T2 = (Mat_<double> (3,4) <<
	R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2), t.at<double>(0,0),
	R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2), t.at<double>(1,0),
	R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2), t.at<double>(2,0));

    Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );
    vector<Point2d> pts_1, pts_2;
    for ( DMatch m:matches )
    {
        // 将像素坐标转换至相机坐标
        pts_1.push_back ( pixel2cam( keypoint_1[m.queryIdx].pt, K) );
        pts_2.push_back ( pixel2cam( keypoint_2[m.trainIdx].pt, K) );
    }

    Mat pts_4d;
    cv::triangulatePoints( T1, T2, pts_1, pts_2, pts_4d );
    // 转换成非齐次坐标
	for ( int i=0; i<pts_4d.cols; i++ )
	{
        Mat x = pts_4d.col(i);
        x /= x.at<float>(3,0); // 归一化
        Point3d p (x.at<float>(0,0),x.at<float>(1,0),x.at<float>(2,0));
	points.push_back( p );
	}
}

同时,在main函数中增加三角测量部分,并验证重投影关系:

int main (int argc, char∗∗ argv)
{
	// .....
	//􀀀􀀀 三角化
	vector<Point3d> points;
	triangulation( keypoints_1, keypoints_2, matches, R, t, points );
	
    //􀀀􀀀 验证三角化点与特征点的重投影关系
	Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );
    for ( int i=0; i<matches.size(); i++ )
    {
        Point2d pt1_cam = pixel2cam( keypoints_1[ matches[i].queryIdx ].pt, K );
        Point2d pt1_cam_3d (points[i].x/points[i].z, points[i].y/points[i].z );

        cout<<"point in the first camera frame: "<<pt1_cam<<endl;
        cout<<"point projected from 3D "<<pt1_cam_3d<<", d="<<points[i].z<<endl;

        // 第2幅图
        Point2f pt2_cam = pixel2cam( keypoints_2[ matches[i].trainIdx ].pt, K );
        Mat pt2_trans = R∗( Mat_<double>(3,1) << points[i].x, points[i].y, points[i].z ) + t;
        pt2_trans /= pt2_trans.at<double>(2,0);
        cout<<"point in the second camera frame: "<<pt2_cam<<endl;
        cout<<"point reprojected from second frame: "<<pt2_trans.t()<<endl;
        cout<<endl;
    }
// ...
}

我们打印了每个空间点在两个相机坐标系下的投影坐标与像素坐标——相当于P 的投影位置与看到的特征点位置。由于误差的存在,它们会有一些微小的差异。以下是某一特征点的信息:

point in the first camera frame: [0.0844072, 0.0734976]
point projected from 3D [0.0843702, 0.0743606], d=14.9895
point in the second camera frame: [0.0431343, 0.0459876]
point reprojected from second frame: [0.04312769812378599, 0.04515455276163744, 1]

可以看到,误差的量级大约在小数点后第3 位。可以看到,三角化特征点的距离大约为15。

但由于尺度不确定性,我们并不知道这里的15 究竟是多少米。

4. 不确定性因素

  1. 由于噪声的存在,我们估得的运动R; t 不一定精确使(1)式为零,所以更常见的做法是求最小二乘解而不是零解。
  2. 三角测量是由平移得到的,有平移才会有对极几何中的三角形,才谈得上三角测量。因此,纯旋转是无法使用三角测量的,因为对极约束将永远满足。在平移存在的情况下,我们还要关心三角测量的不确定性,这会引出一个三角测量的矛盾
  3. 当平移很小时,像素上的不确定性将导致较大的深度不确定性。即若特征点运动一个像素x,使得视线角变化了一个角度,那么将测量到深度值有d 的变化。从几何关系可以看出,当t 较大时,d 将明显变小,这说明平移较大时,在同样的相机分辨率下,三角化测量将更精确。对该过程的定量分析可以使用正弦定理得到,不过这里先考虑定性分析。

5. 如何提高精度

要提高三角化的精度,主要有两种方法:

  1. 提高特征点的提取精度,也就是提高图像分辨率——但这会导致图像变大,增加计算成本。
  2. 使平移量增大。但是,这会导致图像的外观发生明显的变化,比如箱子原先被挡住的侧面显示出来,又比如反射光发生变化,等等。外观变化会使得特征提取与匹配变得困难。

总而言之,增大平移,会导致匹配失效;而平移太小,则三角化精度不够——这就是三角化的矛盾。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SLAM中的三角测量 的相关文章

随机推荐

  • TX2上布置vins_fusion_gpu指南

    1 参考链接 如果初次安装 xff0c 新的TX2环境 xff0c 请参考文档 https github com arjunskumar vins fusion gpu tx2 nano 2 问题记录 1 xff0c 自己的环境情况 我的环
  • Ubuntu下安装cmake

    Ubuntu下安装cmake 今天因为项目的原因需要将cmake升级一下 xff0c 原来我是按照链接没有卸载旧版本 xff0c 直接升级 但是出现一些问题 xff0c 然后我全部卸载后 xff0c 重新安装 以下就是我的安装步骤 第一步
  • AUTH:basic认证和digest认证

    Http authentication BASIC In the context of an HTTP transaction basic access authentication is a method for a web browse
  • Quick Audience组织和工作空间功能解读

    简介 xff1a Quick Audience完成了权限系统全面升级 xff0c 可以解决集团企业不同品牌 不同运营组织 xff0c 不同消费者运营的诉求 xff0c 精细化保障企业数据访问安全 xff0c 提升管控的灵活度 更多关于数智化
  • Socket编程基础总结,全网最全

    IP地址 xff1a 可以在网络环境中 xff0c 唯一标识一台主机 端口号 xff1a 可以定位网络的一台主机上 xff0c 唯一标识一个进程 ip地址 43 端口号 xff1a 可以在网络环境中 xff0c 唯一标识一个进程 在TCP
  • 嵌入式开发--RS-485通讯的问题

    嵌入式开发 RS 485通讯的问题 RS 485说明接口芯片硬件连接CubeMX设置代码编写引脚定义使能串口中断函数发送数据接收数据 有一个问题 xff0c 多收了一个数数据线上的波形问题分析问题解决 RS 485说明 RS 485一般简称
  • UNIX网络编程卷1(第三版)字节排序函数测试

    内存中存储多字节有两种方法 xff0c 即小端字节序和大端字节序 xff0c Ubuntu10 04 是小端字节序 xff0c 网际协议所用的字节序为大端字节序 内存地址增长方向 低序字节 gt 高序字节 小端字节序 高序字节 gt 低序字
  • android非常好的在线视频播放器源码(包含在线音频播放源码)

    一 在线音频播放器 lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34 gt lt LinearLayout xmlns android 61 34 http schemas androi
  • 深入理解任务堆栈

    先来看这一个小函数 xff0c 猜猜他的运行结果 VC6环境 xff1f include lt stdio h gt void b int data 10 printf 34 helloworld r n 34 data 11 61 5 i
  • Protel99seMEX3

    Protel99se的鼠标增强软件 xff0c 可以实现用鼠标放大与缩小电路图 xff0c 十分方便 xff01 文件 xff1a n459 com file 25127180 478161061 以下内容无关 xff1a 分割线 说起Al
  • 基于C++的http服务端开发

    1 同时支持get post接口请求 2 支持文件流下载接口 完整源代码下载地址 xff1a https download csdn net download GUMU12345 81103130 sample cc Copyright c
  • Psychtoolbox SYNCHRONIZATION FAILURE问题

    参考 xff1a http psychtoolbox org docs SyncTrouble 写这篇文章的原因是自己遇见了这个问题 xff0c 并且换了两台电脑都不行 xff0c 有点烦了 xff0c 决心把它弄清楚是怎么回事 因为我的主
  • vscode写python切换虚拟环境,解释器没有不变的问题

    在用vscode写python代码 xff0c 可以使用anaconda进行虚拟环境的管理 而在vscode中使用Ctrl 43 Shift 43 P的方式调出终端 搜索即可搜索到相关设置 xff0c vscode中的python插件会自动
  • MVVM WPF 绑定颜色

    lt Button Margin 61 34 2 34 Width 61 34 10 34 gt lt Button Background gt lt SolidColorBrush Color 61 34 Binding Path 61
  • Android Handler

    Handler 和 Looper关系 Handler是对我们需要线程执行的一类任务的处理管理类 xff0c 而Looper是android线程所拥有的循环心跳行为的管理类 xff0c 例如主线程就是在一开始就执行了Looper loop x
  • linux 编程 ———网络编程(Socket 编程)客户端与服务端实现源码

    文档声明 xff1a 以下资料均属于本人在学习过程中产出的学习笔记 xff0c 如果错误或者遗漏之处 xff0c 请多多指正 并且该文档在后期会随着学习的深入不断补充完善 感谢各位的参考查看 笔记资料仅供学习交流使用 xff0c 转载请标明
  • 使用vs生成C++动态链接库dll文件----使用C++和C#混合编程

    https blog csdn net qq 30139555 article details 103621955
  • 视觉SLAM作业(四) 相机模型与非线性优化

    视觉SLAM作业 xff08 四 xff09 相机模型与非线性优化 一 图像去畸变 现实生活中的图像总存在畸变 原则上来说 xff0c 针孔透视相机应该将三维世界中的直线投影成直线 xff0c 但是当我们使用广角和鱼眼镜头时 xff0c 由
  • 在TUMVI数据集上测试VINS-Fusion算法

    VINS Fusion算法是一个非常优秀的视觉惯性里程计 但原版VINS Fusion并没有提供与TUM数据集相应的配置文件 因此需要自己进行写yaml文件 修改配置文件 tum mono yaml span class token dir
  • SLAM中的三角测量

    来源 视觉SLAM十四讲 xff0c 作者 高翔 三角测量是SLAM中 xff0c 利用相机运动估计特征点空间位置的过程 本节旨在解决以下问题 xff1a 三角测量的概念三角测量的过程及代码实现 xff1b 三角测量有哪些不确定性如何提高三