【SLAM十四讲总结】第二讲
1.三种相机
1.1单目相机
- 照片,本质上是拍照时的场景(Scene),在相机的成像平面上留下的一个投影。 它以二维的形式反映了三维的世界。这个过程丢掉了场景的一个维度:也就是所谓的深度(或距离)。
- 由于单目相机只是三维空间的二维投影,所以,如果我们真想恢复三维结构,必须移动相机的视角。
- 同时估计场景中物体的远近和大小,不妨称之为结构。
- 根据近大远小的原理,以及运动后,近处的物体移动的快,远处的物体移动缓慢,可以得到相对深度,但是无法得到绝对深度。
- 如果把相机的运动和场景大小同时放大两倍,单目所看到的像是一样的。同样的,把这个大小乘以任意倍数,我们都将看到一样的景象(例如屏幕由13寸变成24寸)。这说明了单目 SLAM 估计的轨迹和地图,将与真实的轨迹、地图,相差一个因子,也就是所谓的尺度(Scale) 。由于单目 SLAM 无法仅凭图像确定这个真实尺度,所以又称为尺度不确定性。
- 单目相机的尺度不确定有两个原因,第一个是无法知道物体的实际尺寸大小,第二是无法知道实际的深度,如果任意知道其中的一个,那么就可以获取场景的尺度。
1.2 双目相机
- 如下图,双目相机利用视差(同一个点在两个相机上成像位置的像素差值)进行位姿的估计,需要两个先验信息,一个是基线(两个相机光心的距离),另一个是焦距(光心到成像平面的距离)。
计算公式如下: - 由上式可以看出,两个相机的基线越大,可以探测的深度范围越大。所以自动驾驶的双目相机距离很大,小型机器人的双目基线比较小。
- 远处的物体在成像平面上的视差小,近处的物体在成像平面上的视差大。但是,视差最小是一个像素,所以当基线和焦距固定的时候,可探测的深度z存在理论上的最大值,即fb。
- 优缺点:
首先,以上我们默认已经知道一个空间点在两个成像平面上的投影对应,但是实际情况是我们需要自己找一个成像平面上一点在另一个成像平面上的点的位置。这需要算法去解决。大概采用的是极线约束,不是一张图上所有像素点遍历。
其次,首先需要对双目相机进行标定,得到两个相机的内外参数、单应矩阵。当然,很多双目相机出厂会标定依次,并提供给用户,但是实际使用要求精度较高时,还是会自己重新标定。注意,两个相机的单应矩阵中包含了基线。
第三,深度量程和精度受制于双目的基线和图像的分辨率所限。
第四,计算量的问题,视差的计算涉及大量像素点,消耗资源,需要GPU或者FPGA加速,才能实时输出整张图像的深度信息。 - 双目相机的原理详解
深度相机原理揭秘–双目立体视觉
基本流程:
1、首先需要对双目相机进行标定,得到两个相机的内外参数、单应矩阵。
2、根据标定结果对原始图像校正,校正后的两张图像位于同一平面且互相平行。
3、对校正后的两张图像进行像素点匹配。(极线约束)
4、根据匹配结果计算每个像素的深度,从而获得深度图。
1.3 RGBD相机
- 主要分为结构光和TOF,包括 Kinect/Kinect V2/Kinect Azure、 Xtion live pro、Realsense系列 等。
- Realsense系列一般是结构光,Kinect一般是TOF。
- 主动测量功耗大,深度值准确,量程小,易受光照干扰,无法测量透射材质,主要用于室内。
2 VSLAM框架
- 传感器信息读取。在视觉 SLAM 中主要为相机图像信息的读取和预处理。如果在机器人中,还可能有码盘、惯性传感器等信息的读取和同步。
- 视觉里程计 (Visual Odometry, VO)。视觉里程计任务是估算相邻图像间相机的运动,以及局部地图的样子。 VO 又称为前端(Front End)。
- 后端优化(Optimization)。后端接受不同时刻视觉里程计测量的相机位姿,以及回环检测的信息,对它们进行优化,得到全局一致的轨迹和地图。由于接在 VO 之后,又称为后端(Back End)。
- 回环检测(Loop Closing)。回环检测判断机器人是否曾经到达过先前的位置。如果检测到回环,它会把信息提供给后端进行处理。
- 建图(Mapping)。它根据估计的轨迹,建立与任务要求对应的地图。
- 补充:
- VO是估计相邻两帧图像间的位姿
- 后端优化主要处理SLAM过程中的噪声问题,如何从带有噪声的数据估计系统的状态。从KF到图优化。
- 回环主要解决的是累计误差导致的漂移问题。
其他
- 静态库以.a为后缀,共享库以.so为后缀:
静态库每次调用都会产生一个副本,共享库只有一个副本,更省空间。
CMakeLists中应该怎么写?
生成库:
静态库:add_library( hello libHelloSLAM.cpp )—>生成libhello.a
共享库:add_library( hello_shared SHARED libHelloSLAM.cpp )–>生成libhello_shared.so
使用库:
add_executable( useHello useHello.cpp )
target_link_libraries( useHello hello_shared )