目录
1 SIFT和SUFT的区别
2 相似变换、仿射变换、射影变换的区别
3 Homography、Essential和Fundamental Matrix的区别
4 视差与深度的关系
5 描述PnP算法
6 闭环检测常用方法
7 给一个二值图,求最大连通域
8 梯度下降法、牛顿法、高斯-牛顿法的区别
9 推导一下卡尔曼滤波、描述下粒子滤波
10 如何求解Ax=b的问题
11 什么是极线约束
12 单目视觉SLAM中尺寸漂移是怎么产生的
13 解释SLAM中的绑架问题
14 描述特征点法和直接法的优缺点
15 EKF和BA的区别
16 边缘检测算子有哪些?
17 简单实现cv::Mat()
18 10个相机同时看到100个路标点,问BA优化的雅克比矩阵多少维
19 介绍经典的视觉SLAM框架
20 介绍下你熟悉的非线性优化库
21 室内SLAM与自动驾驶SLAM有什么区别?
无人驾驶技术与SLAM的契合点在哪里?
有什么理由能够让SLAM成为无人驾驶的关键技术?
22 什么是紧耦合、松耦合?优缺点。
23 地图点的构建方法有哪些
ORB-SLAM3中的求3D点的算法流程(初始化过程):
24 如果对于一个3D点,我们在连续帧之间形成了2D特征点之间的匹配,但是这个匹配中可能存在错误的匹配。请问你如何去构建3D点?
基本矩阵F的自动估计
非线性优化计算位姿
鲁棒核函数
25 RANSAC在选择最佳模型的时候用的判断准则是什么?
26 问题:除了RANSAC之外,还有什么鲁棒估计的方法?
M-估计
最小中值估计
27 问题:3D地图点是怎么存储的?表达方式?
28 BA中,地图点却不能很快的收敛这是为什么呢?
29 问题:LM算法里面那个λ是如何变化的呢?
30 说一下3D空间的位姿如何去表达?
31 问题:李群和李代数的关系?
32 求导 ?
33. Mat是如何访问元素的?先访问行还是先访问列?
34. 写出单目相机的投影模型,畸变模型。
投影模型如下:
畸变模型如下:
35. 给两组已经匹配好的3D点,计算相对位姿变换,写代码
36. ORB-SLAM初始化的时候为什么要同时计算H矩阵和F矩阵?
37. 如何标定IMU与相机之间的外参数?
38. 给你xx误差的GPS,给你xx误差的惯导你怎么得到一个cm级别的地图?
39 计算H矩阵和F矩阵的时候有什么技巧呢?
40. 给一张图片,知道相机与地面之间的相对关系,计算出图的俯视图。
41. 什么是ORB特征? ORB特征的旋转不变性是如何做的? BRIEF算子是怎么提取的?
42. ORB-SLAM中的特征是如何提取的?如何均匀化的?
43. 26道题:3D VISION、SLAM求职宝典 | SLAM知识篇(D1,重点 )
参考
前言: 面试题有很多,这里汇总了网上主流的、自己可能涉及到的大部分题目及答案。如果都会,那必定是全能型大佬。根据自己的研究方向和简历有主有次的准备,可能是一条不错的道路。
SIFT/SURF为了实现不同图像中相同场景的匹配,主要包括三个步骤:
1、尺度空间的建立;
2、特征点的提取;
3、利用特征点周围邻域的信息生成特征描述子
4、特征点匹配。
参考: 图像识别中SIFT算法与SURF算法的区别
参考:多视图几何总结——等距变换、相似变换、仿射变换和射影变换
Homography Matrix可以将一个二维射影空间的2D点变换该另一个二维射影空间的2D点,如下图所示,在不加任何限制的情况下,仅仅考虑二维射影空间中的变换,一个单应矩阵H可由9个参数确定,减去scale的一个自由度,自由度为8。
Fundamental Matrix对两幅图像中任何一对2D对应点x和x′基础矩阵F都满足条件:
,秩只有2,因此F的自由度为7。它自由度比本质矩阵多的原因是多了两个内参矩阵。
Essential matrix:本质矩是归一化图像坐标下的基本矩阵的特殊形式,其参数由运动的位姿决定,与相机内参无关,其自由度为6,考虑scale的话自由度为5。
参考多视图几何总结——基础矩阵、本质矩阵和单应矩阵的自由度分析
参考:三维重建笔记_相机标定(相机矩阵求解)基本概念汇总
在相机完成校正后,则有 z=fb/d,其中d表示视差,b表示基线,f是焦距,z是深度。这个公式其实很好记,在深度和焦距 f 确定的情况下,基线越大,视差也会越大。
已知空间点世界坐标系3D坐标和其对应像素投影2D坐标,求当前相机坐标系,相对于世界坐标系的变换(R,t)。公式如下
目前一共有两种解法,直接线性变换方法(一对点能够构造两个线性约束,因此12个自由度一共需要6对匹配点),另外一种就是非线性优化的方法,假设空间坐标点准确,根据最小重投影误差优化相机位姿。
目前有两个主要场景场景,其一是求解相机相对于某2维图像/3维物体的位姿;其二就是SLAM算法中估计相机位姿时通常需要PnP给出相机初始位姿。
在场景1中,我们通常输入的是物体在世界坐标系下的3D点以及这些3D点在图像上投影的2D点,因此求得的是相机坐标系相对于世界坐标系(Twc)的位姿
在场景2中,通常输入的是上一帧中的3D点(在上一帧的相机坐标系下表示的点)和这些3D点在当前帧中的投影得到的2D点,所以它求得的是当前帧相对于上一帧的位姿变换
参考:三维重建笔记_相机标定(相机矩阵求解)基本概念汇总
ORB SLAM中采用的是词袋模型进行闭环检测筛选出候选帧,再通过求解判断最合适的关键帧
LSD SLAM中的闭环检测主要是根据视差、关键帧连接关系,找出候选帧,然后对每个候选帧和测试的关键帧之间进行双向Sim3跟踪,如果求解出的两个李代数满足马氏距离在一定范围内,则认为是闭环成功
这个之后单独写一篇博客来研究这个好了,二值图的连通域应该是用基于图论的深度优先或者广度优先的方法,后来还接触过基于图的分割方法,采用的是并查集的数据结构,之后再作细致对比研究。
在BA优化、PnP、直接法里面都有接触到非线性优化问题,上面几种方法都是针对对非线性优化问题提出的方法,将非线性最优化问题作如下展开,就可以获得梯度下降法和牛顿法
梯度下降法是一个一阶最优化算法,通常也称为最速下降法。 要使用梯度下降法找到一个函数的局部极小值,必须向函数上当前点对应梯度(或者是近似梯度)的反方向的规定步长距离点进行迭代搜索。因此指保留一阶梯度信息。缺点是过于贪心,容易走出锯齿路线。
牛顿法是一个二阶最优化算法,基本思想是利用迭代点处的一阶导数(梯度)和二阶导数(Hessen矩阵)对目标函数进行二次函数近似。因此保留二阶梯度信息。缺点是需要计算H矩阵,计算量太大。
而把非线性问题,先进行一阶展开,然后再作平方处理就可以得到高斯-牛顿法和列文博格方法
高斯-牛顿法对上式展开并对Δx进行求导即可得高斯牛顿方程,其实其就是使用
对牛顿法的H矩阵进行替换,但是
有可能为奇异矩阵或变态,Δx也会造成结果不稳定,因此稳定性差
列文博格法就是在高斯-牛顿法的基础上对Δx添加一个信赖区域,保证其只在展开点附近有效,即其优化问题变为带有不等式约束的优化问题,利用Lagrange乘子求解
用自己的描述下,仅供参考:
卡尔曼滤波:
卡尔曼滤波就是通过运动方程获得均值和方差的预测值,然后结合观测方程和预测的方差求得卡尔曼增益,然后在用卡尔曼增益更行均值和方差的预测值而获得估计值。
卡尔曼滤波推导的思路是(其中一种)先假定有这么一个修正公式
构真实值和估计值之间的协方差矩阵,然后通过对对角线元素求和获得方差表达式,我们的修正公式是需要使得方差最小,因此把方差表达式对
求导就可以获得卡尔曼增益的表达式,然后从先验到预测值的方差公式可以通过求预测值和真实值的协方差矩阵获得。
粒子滤波:
粒子滤波最常用的是SIR,其算法是用运动方程获得粒子的状态采样,然后用观测方程进行权值更新,通过新的粒子加权平均就获得新的估计状态,最后非常重要的一步就是重采用。
粒子滤波的推导中概念有很多,最重要的推导过程是重要性采样过程,其思路就是我原本的采样分布是不知道的,我如何从一个已知的分布中采样,通过加权的方式使得从已知的分布中采样的粒子分布和原本未知的分布中采样的粒子分布结果一致,从而引入SIS粒子滤波,再进一步加入重采样后就引入了SIR粒子滤波。
具体的可以参看我的另外两个总结博客
概率机器人总结——粒子滤波先实践再推导
概率机器人总结——(扩展)卡尔曼滤波先实践再推导
参看我的另外一个总结博客多视图几何总结——基础矩阵、本质矩阵和单应矩阵的求解过程
所谓极线约束就是说同一个点在两幅图像上的映射,已知左图映射点p1,那么右图映射点p2一定在相对于p1的极线上,这样可以减少待匹配的点数量。如下图:
用单目估计出来的位移,与真实世界相差一个比例,叫做尺度。这个比例在单目初始化时通过三角化确定,但单纯靠视觉无法确定这个比例到底有多大。由于SLAM过程中噪声的影响,这个比例还不是固定不变的。修正方式是通过回环检测计算Sim3进行修正。
绑架问题就是重定位,是指机器人在缺少之前位置信息的情况下,如何去确定当前位姿。例如当机器人被安置在一个已经构建好地图的环境中,但是并不知道它在地图中的相对位置,或者在移动过程中,由于传感器的暂时性功能故障或相机的快速移动,都导致机器人先前的位置信息的丢失,在这种情况下如何重新确定自己的位置。
初始化绑架可以阐述为一种通常状况初始化问题,可使用蒙特卡洛估计器,即粒子滤波方法,重新分散粒子到三维位形空间里面,被里程信息和随机扰动不断更新,初始化粒子聚集到/收敛到可解释观察结果的区域。追踪丢失状态绑架,即在绑架发生之前,系统已经保存当前状态,则可以使用除视觉传感器之外的其他的传感器作为候补测量设备。
特征点法
优点:1. 没有直接法的强假设,更加精确;2. 相较与直接法,可以在更快的运动下工作,鲁棒性好
缺点:1. 特征提取和特征匹配过程耗时长;2. 特征点少的场景中无法使用;3.只能构建稀疏地图
直接法:
优点:1.省去了特征提取和特征匹配的时间,速度较快;2. 可以用在特征缺失的场合;3. 可以构建半稠密/稠密地图
缺点:1. 易受光照和模糊影响;2.运动必须慢;3.非凸性,易陷入局部极小解
因为误差对相机姿态的偏导数的维度是2×6,对路标点的偏导数是2×3,又10个相机可以同时看到100个路标点,所以一共有10×100×2行,100×3+10×6个块。
视觉SLAM总结——ORB SLAM2中关键知识点总结
视觉SLAM总结——SVO中关键知识点总结
视觉SLAM总结——LSD SLAM中关键知识点总结
非线性优化库一般有ceres和g2o两种,我比较熟悉的是g2o,看下g2o的结构图
它表示了g2o中的类结构。 首先根据前面的代码经验可以发现,我们最终使用的optimizer是一个SparseOptimizer对象,因此我们要维护的就是它(对它进行各种操作)。 一个SparseOptimizer是一个可优化图(OptimizableGraph),也是一个超图(HyperGraph)。而图中有很多顶点(Vertex)和边(Edge)。顶点继承于BaseVertex,边继承于BaseUnaryEdge、BaseBinaryEdge或BaseMultiEdge。它们都是抽象的基类,实际有用的顶点和边都是它们的派生类。我们用SparseOptimizer.addVertex和SparseOptimizer.addEdge向一个图中添加顶点和边,最后调用SparseOptimizer.optimize完成优化。
在优化之前还需要制定求解器和迭代算法。一个SparseOptimizer拥有一个OptimizationAlgorithm,它继承自Gauss-Newton, Levernberg-Marquardt, Powell’s dogleg三者之一。同时,这个OptimizationAlgorithm拥有一个Solver,它含有两个部分。一个是 SparseBlockMatrix,用于计算稀疏的雅可比和海塞矩阵;一个是线性方程求解器,可从PCG、CSparse、Choldmod三选一,用于求解迭代过程中最关键的一步:
因此理清了g2o的结构,也就知道了其使用流程。在之前已经说过了,这里就再重复一遍:
(1)选择一个线性方程求解器,PCG、CSparse、Choldmod三选一,来自g2o/solvers文件夹
(2)选择一个BlockSolver,用于求解雅克比和海塞矩阵,来自g2o/core文件夹
(3)选择一个迭代算法,GN、LM、DogLeg三选一,来自g2o/core文件夹
参考G2O图优化基础和SLAM的Bundle Adjustment(光束法平差)
这里我补充下:
注意到上面的结构图中,节点Basevertex
(1)边是EdgeSE3ProjectXYZ,它其实就是继承自BaseBinaryEdge<2, Vector2d, VertexSBAPointXYZ, VertexSE3Expmap>,其模板类型里第一个参数是观测值维度,这里的观测值是其实就是我们的像素误差u,v u,vu,v,第二个参数就是我们观测值的类型,第三个第四个就是我们边两头节点的类型;
(2)相机节点VertexSE3Expmap,它其实就是继承自BaseVertex<6, SE3Quat>,其模板类第一个参数就是其维度,SE3是六维的这没毛病,第二个就是节点的类型,SE3Quat就是g2o自定义的SE3的类,类里面写了各种SE3的计算法则;
(3)空间点节点VertexSBAPointXYZ,它其实就是继承自BaseVertex<3, Vector3d>,其模板类第一个参数是说明咱空间点的维度是三维,第二个参数说明这个点的类型是Vector3d;
(4)求解器是BlockSolver_6_3,它其实就是BlockSolver< BlockSolverTraits<6, 3> >,6,3分别指代的就是边两边的维度了。
我记得我刚开始学习SLAM的时候自己想办法写后端的时候很纳闷这个图是怎么构建起来的,在ORB或者SVO里面,所有的地图点和关键帧都是以类的形式存在的,例如在ORB中是先将关键帧的节点添加起来,然后添加空间点,然后遍历空间点中记录的与哪些关键帧有关系,然后相应ID的关键帧的节点和空间点的节点连接起来,然后就把图建立起来了,我觉得不写类好像没有什么其他更好的办法了。
这是个开放题,参考无人驾驶技术与SLAM的契合点在哪里,有什么理由能够让SLAM成为无人驾驶的关键技术?
答: 都属于SLAM的问题范围。但应用场景不同,技术上的侧重点也不同。
SLAM传统上还是面向室内等缺少GPS信号的应用,例如室内移动机器人导航,而在无人驾驶汽车上,它的意义和作用是什么,已经有高精度的地图和城市GPS信号了,那就是说SLAM只是为了感知么?
最初,SLAM的提出就是为了解决未知环境下移动机器人的定位和建图的问题。所以,笼统的说,SLAM对于无人驾驶的意义就是如何帮助车辆感知周围环境,更好的完成导航、避障、路径规划等高级任务。
现在已经有高精度的地图,暂且不去考虑这个地图的形式、存储规模和如何用它的问题。首先,这个构建好的地图真的能帮助无人驾驶完成避障或者路径规划等的类似任务吗?至少环境是动态的,道路哪里有一辆车,什么时候会出现一个行人,这些都是不确定的。所以从实时感知周围环境这个角度来讲,提前构建好的地图是不能解决这个问题的。
另外,GPS的定位方式是被动的、依赖信号源的,这一点使得其在一些特殊场景下是不可靠的,比如城市环境中GPS信号被遮挡,野外环境信号很弱,还有无人作战车辆作战中信号被干扰以及被监测等。
所以像视觉SLAM这种主动的并且无源的工作方式在上述场景中是有优势的。从硬件角度讲,目前主流的视觉SLAM方案,在构建低成本,小型化,易于搭载的硬件平台方面也是有优势的。
1.我个人不是很赞同这个逻辑。SLAM作为一个很庞杂的系统,其本身也有很多关键环节和实际应用中会遇到的难题,作为一种应用场景越来越广泛的技术(如自动机器人,无人机,无人驾驶,AR),它可能永远不会成为无人驾驶的关键技术,与其思考这个问题,不如关注SLAM本身,即围绕定位和建图这两个基本任务,来想想
接下来在想想SLAM能帮助无人驾驶做些什么?只有技术越来越完善和成熟,才能被应用到更多的实际场景中。
2.我想SLAM真正能发挥作用的区域是last mile或者一些高精度地图覆盖不到的非结构化环境。
这里默认指的是VIO中的松紧耦合,这里参考深蓝学院的公开课里面介绍:
紧耦合是把图像的特征加到特征向量中去,这样做优点是可以免去中间状态的累计误差,提高精度,缺点是系统状态向量的维数会非常高,需要很高的计算量;
松耦合是把VO处理后获得的变换矩阵和IMU进行融合,这样做优点是计算量小但是会带来累计误差。
下面是对经典的VIO框架进行一个分类
(1)在ORB SLAM2中是根据三角化的方法确定地图点的,利用匹配好的图像点对, 构建AX=b的方程,然后利用SVD分解取最小奇异值对应的特征向量作为地图点坐标,参考多视图几何总结——三角形法
(2)在SVO中是利用深度滤波器进行种子点深度更新,当种子点深度收敛后就加入地图构建地图点。
(在LSD中好像没有维护地图点,不断维护的是关键帧上的深度图)
输入: 一对图像的多组2D点对;
输出: 这两帧图像的相对运动(相对位姿: R,t)及D对应的3D点坐标
void TwoViewReconstruction::Triangulate(const cv::KeyPoint &kp1, const cv::KeyPoint &kp2, const cv::Mat &P1, const cv::Mat &P2, cv::Mat &x3D)
{
cv::Mat A(4,4,CV_32F);
A.row(0) = kp1.pt.x*P1.row(2)-P1.row(0);
A.row(1) = kp1.pt.y*P1.row(2)-P1.row(1);
A.row(2) = kp2.pt.x*P2.row(2)-P2.row(0);
A.row(3) = kp2.pt.y*P2.row(2)-P2.row(1);
cv::Mat u,w,vt;
cv::SVD::compute(A,w,u,vt,cv::SVD::MODIFY_A| cv::SVD::FULL_UV);
x3D = vt.row(3).t();
x3D = x3D.rowRange(0,3)/x3D.at(3);
}
毋庸置疑首先想到的是用RANSAC方法进行连续帧之间的位姿估计,然后用内点三角化恢复地图点,具体一点说使用RANSAC估计基础矩阵的算法步骤如下:
(参考 计算机视觉中的数学方法 吴福朝 17.1.3节)
RANSAC 方法可以从有误匹配的点对应集中估计基本矩阵,这使得从两幅图像自动估计基本矩阵成为可能。基本矩阵自动估计的步骤如下:
为了自动估计基本矩阵,首先需要从两幅图像自动建立一个“点对应集”,可以容忍这个点对应集包含有大量的误匹配,因为在 RANSAC 估计方法中,理论上只要存在 8 个“好”的点对应就可以估计出基本矩阵。
如果是利用非线性优化的方法获得位姿的话,可以在非线性优化代价函数中加入鲁棒核函数来减少无匹配所带来的误差,例如《视觉SLAM十四讲》里面提到的Huber核
在《机器人的状态估计》一书总将这种方法称为M估计,核函数还包裹Cauchy核
Geman-MeClure核
等等。
总结:基本都是二次曲线或对数曲线的形式,加上取对数,加上分母项,加上权重项,加上分段的断点,来抑制过滤掉outlier.
除了 Huber 核之外,还有 Cauchy 核, Tukey 核等等(如上),读者可以看看 g2o 和 Ceres 都提供了哪些核函数。
最大一致集;
选择一致集时:简单地说一般是选用具有最小残差和的模型作为最佳模型。
解答:在《机器人的状态估计》一书中还介绍了M估计(广义的最大似然估计)和协方差估计,所谓M估计指的是加入鲁棒代价函数最大似然估计,
而协方差估计指的是同时估计状态和协方差的方法,也称自适应估计。
(参考 计算机视觉中的数学方法 吴福朝 第17章)
解答:以ORB SLAM2为例,3D地图点是以类的形式存储的,在类里面除了
class MapPoint
{
// ...
protected:
// Position in absolute coordinates
cv::Mat mWorldPos;
// Keyframes observing the point and associated index in keyframe
std::map > mObservations;
// For save relation without pointer, this is necessary for save/load function
std::map mBackupObservationsId1;
std::map mBackupObservationsId2;
// Mean viewing direction
cv::Mat mNormalVector;
// Best descriptor to fast matching
cv::Mat mDescriptor;
// Reference KeyFrame
KeyFrame* mpRefKF;
long unsigned int mBackupRefKFId;
// Tracking counters
int mnVisible;
int mnFound;
// Bad flag (we do not currently erase MapPoint from memory)
bool mbBad;
MapPoint* mpReplaced;
// For save relation without pointer, this is necessary for save/load function
long long int mBackupReplacedId;
// Scale invariance distances
float mfMinDistance;
float mfMaxDistance;
Map* mpMap;
std::mutex mMutexPos;
std::mutex mMutexFeatures;
std::mutex mMutexMap;
};
问题:给你m相机n个点的bundle adjustment。当我们在仿真的时候,在迭代的时候,相机的位姿会很快的接近真值。而地图点却不能很快的收敛这是为什么呢?
解答:约束相机位姿的方程远多于约束地图点的方程。
解答:这里我想从头开始理一遍,参考《视觉SLAM十四讲》首先LM算法优势在哪里,GN法采用雅克比矩阵的形式来代替难求的海森矩阵H,但是是半正定的,可能出现奇异矩阵或者病态的情况,而且Δx太大的时候也会导致这种二阶泰勒展开的近似不够准确,为解决第二个问题,提出了给Δx添加一个信赖区域方法,也就是LM法,其采用下式判断近似差异的大小,进而确定信赖区域范围:
其中分子是代价函数的实际下降值,分母是近似下降值。如果ρ越接近1说明近似越准确,ρ过小说明实际下降较小,需要缩小信赖区域范围,如果ρ过大说明实际下降较大,需要扩大信赖区域范围。其步骤如下:
解答:李群或者李代数。
解答:如上图所示(摘自《视觉SLAM十四讲》),从李群到李代数是对数映射,形式上是先取对数,然后取∨,从李代数到李群是指数映射,形式上先取∧,再取指数,下面具体说:
三维旋转:李群就是三维旋转矩阵,李代数是三维轴角(长度代表旋转大小,方向代表旋转轴方向),从李群到李代数是分别求轴角的角θ(通过矩阵的迹求反余弦)和向量a(旋转矩阵特征值1对应的特征向量),从李代数到李群就是罗德罗杰斯公式。
三维变换:李群是四元变换矩阵,李代数是六维向量,从李群到李代数同样先求角和向量,然后需要求t,从李代数到李群的话通过上面的公式计算。
Mat访问像素一共有三种方法:使用at()方法、使用ptr()方法、使用迭代器、使用data指针
(1)使用at()方法:at()方法又是一个模板方法,所以在使用的时候需要传入图像像素的类型,例如:
(2)使用ptr()方法: ptr()方法能够返回指定行的地址(因此正常是先访问行的),然后就可以移动指针访其他的像素。例如
这里需要注意的是,有时候在内存中会为了对齐而会对末尾的像素进行填充,而有时候没有填充。可以使用isContinue()来访问图像是否有填充,对于没有填充的图像,即连续的图像来说,遍历的时候就可以只要一层循环就可以了,他会自己换行将图像变成一维的来处理。
(3)使用迭代器:对Mat类型来说,他的迭代器类型可以使用MatIterator_或者Mat_::Iterator类型,具体使用如下
用这两个迭代器便可以指定Mat对象的迭代器,注意需要传入模板参数。对迭代器的初始化与C++中的STL一致。
遍历也和前面指针一样,从图像左上角第一个像素开始遍历三个字节,然后第二个字节,依次遍历,到第一行遍历完后,就会到第二行来遍历。
(4)使用data指针:用Mat存储一幅图像时,若图像在内存中是连续存储的(Mat对象的isContinuous == true),则可以将图像的数据看成是一个一维数组,而data(uchar*)成员就是指向图像数据的第一个字节的,因此可以用data指针访问图像的数据,从而加速Mat图像的访问速度。
一般经过裁剪的Mat图像,都不再连续了,如cv::Mat crop_img = src(rect);crop_img 是不连续的Mat图像,如果想转为连续的,最简单的方法,就是将不连续的crop_img 重新clone()一份给新的Mat就是连续的了,例如
投影模型一般应该都知道写,但是畸变模型就不一定了…参考《视觉SLAM十四讲》
注意啊,这里空间点(相机坐标系下的3D点坐标)是非齐次坐标,而像素变成了齐次坐标,如果空间点也是齐次坐标的话,需要讲变换矩阵写成3×4
的矩阵,最后一列全为0;。
(以下参数含义:平面上的任意一点 p 可以用笛卡尔坐标表示为 [x,y]^T , 也可以把它写成极坐标的形式[r,θ]^T,其中 r 表示点 p 离坐标系原点的距离, θ 表示和水平轴的夹角。径向畸变可看成坐标点沿着长度方向发生了变化 δr, 也就是其距离原点的长度发生了变化。切向畸变可以看成坐标点沿着切线方向发生了变化,也就是水平夹角发生了变化 δθ。)
畸变模型分为径向畸变和切向畸变,径向畸变如下:
组合上面两式,通过五个畸变系数找到空间点在像素平面上的正确位置:
1.将三维空间点P(X,Y,Z)投影到归一化图像平面。设它的归一化坐标为。
2.对归一化平面上的点进行径向畸变和切向畸变纠正
3.将纠正后的点通过内参数矩阵投影到像素平面,得到该点在图像上的正确位置
值得一提的是,存在两种去畸变处理(Undistort,或称畸变校正)做法。我们可以选择先对整张图像进行去畸变,得到去畸变后的图像,然后讨论此图像上的点的空间位置。或者,我们也可以先考虑图像中的某个点,然后按照去畸变方程,讨论它去畸变后的空间位置。二者都是可行的,不过前者在视觉 SLAM 中似乎更加常见一些。
匹配两组已知坐标的3D点当然是采用ICP,参考《视觉SLAM十四讲》,ICP的解法一共有两种:SVD方法和非线性优化方法,下面过一遍SVD方法的推导过程:
参考:给两组已经匹配好的3D点,计算相对位姿变换,写代码
简单地说,因为初始化的时候如果出现纯旋转或者所有特征点在同一个平面上的情况,F矩阵会发生自由度退化,而这个时候H矩阵会有较小误差,因此要同时计算H矩阵和F矩阵,那么这里补充两个问题:
目前我还没有实际标定过,标定方法可以参考贺一家博士的博客Kalibr 标定双目内外参数以及 IMU 外参数,像Intel出的D435i是已经标定号外参数的,另外在VINS-mono中可以对相机的外参数进行估计
//todo
其中我能想到的技巧有两点,第一个是RANSAC操作,第二个是归一化操作,RANSAC操作前面已经解释过了,这里主要来分析下归一化操作,在《多视图几何》中提到了一种归一化八点法,方法是
归一化具体操作如下:
具体操作:又称各项同性缩放(非同性缩放有额外开销,但是效果并未提升),步骤如下
归一化具体操作优势如下:
简单地说利用射影变换,将原本不垂直的线垂直化(用多视图几何上的话说就是消除透视失真),如下图所示 ...
参考:47. 给一张图片,知道相机与地面之间的相对关系,计算出图的俯视图。
ORB特征指的是Oriented FAST and rotated BREIF,包括改进后的FAST角点和BREIF特征子,ORB特征的旋转不变性主要是通过计算半径r范围内像素点的一阶矩,连接质心到特征点的向量作为主方向来对周围像素进行旋转,然后提取BRIEF特征子,BRIEF特征描述子通过计算出来的一个二进制串特征描述符来进行提取的。
ORB描述子的提取流程:
视觉SLAM面试题汇总(2019年秋招题库参考)——第一部分
万字干货!视觉SLAM面试题汇总(19年秋招)第二部分 26~51
3D VISION、SLAM求职宝典 | SLAM知识篇(D1,重点 )