地图匹配:基于隐马尔科夫模型(HMM)的地图匹配(Map-Matching)算法
做了哪些项目,多传感器融合了解吗?
跑过哪些开源算法,是否做过对比,各有什么优劣?
对于光照明暗变化、动态场景,视觉SLAM如何去解决?
动态SLAM的思路?与基础矩阵分割相比有什么区别?什么是三角剖分?与深度学习方法相比的优势?
最基本的霍夫变换是从黑白图像中检测直线(线段)
自由度:
首先,单应性矩阵也是一个3x3的矩阵。
其次,其具有尺度等价性。
最后得到,基础矩阵的自由度为8,4对点求解,RANSAC选去点算
秩:因为单应性矩阵是可逆矩阵,所以他的秩为3。
自由度:
首先,基础矩阵也是一个3x3的矩阵。
其次,其仍然受对极约束的影响,具有尺度等价性。
再其次,基础矩阵的行列式为0。(因为他的秩为2,见下面。)
最后得到,基础矩阵的自由度为7.
秩:
首先,相机内参矩阵秩为3,旋转矩阵秩为3。
其次,平移反对称矩阵秩为2。
自由度:
首先,旋转和平移一共6个自由度。
其次,由于对极约束的原因,本质矩阵是具有尺度等价性的,所以自由度减1。
所以,本质矩阵的自由度为5。
PS:旋转矩阵虽然9个参数,但不是任意数都可以,得满足矩阵为单位(去掉3个自由度)正交(去掉2个自由度)阵,行列式为正1(去掉1个自由度)的性质,所以,这些约束导致自由度减少,虽然是9个数但是表达3个自由度。
秩:
**首先,旋转矩阵秩为3,是可逆矩阵。
其次,平移的反对称矩阵秩为2。
* Step 1:(未创建)得到用于初始化的第一帧,初始化需要两帧
* Step 2:(已创建)如果当前帧特征点数大于100,则得到用于单目初始化的第二帧
* Step 3:在mInitialFrame与mCurrentFrame中找匹配的特征点对
* Step 4:如果初始化的两帧之间的匹配点太少,重新初始化
* Step 5:通过H模型或F模型进行单目初始化,得到两帧间相对运动、初始MapPoints
* Step 6:删除那些无法进行三角化的匹配点
* Step 7:将三角化得到的3D点包装成MapPoints
/** 给定投影矩阵P1,P2和图像上的匹配特征点点kp1,kp2,从而计算三维点坐标
* @brief
*
* @param[in] kp1 特征点, in reference frame
* @param[in] kp2 特征点, in current frame
* @param[in] P1 投影矩阵P1
* @param[in] P2 投影矩阵P2
* @param[in & out] x3D 计算的三维点
*/
void Initializer::Triangulate(
const cv::KeyPoint &kp1, //特征点, in reference frame
const cv::KeyPoint &kp2, //特征点, in current frame
const cv::Mat &P1, //投影矩阵P1
const cv::Mat &P2, //投影矩阵P2
cv::Mat &x3D) //三维点
{
// 原理
// Trianularization: 已知匹配特征点对{x x'} 和 各自相机矩阵{P P'}, 估计三维点 X
// x' = P'X x = PX
// 它们都属于 x = aPX模型
// |X|
// |x| |p1 p2 p3 p4 ||Y| |x| |--p0--||.|
// |y| = a |p5 p6 p7 p8 ||Z| ===>|y| = a|--p1--||X|
// |z| |p9 p10 p11 p12||1| |z| |--p2--||.|
// 采用DLT的方法:x叉乘PX = 0
// |yp2 - p1| |0|
// |p0 - xp2| X = |0|
// |xp1 - yp0| |0|
// 两个点:
// |yp2 - p1 | |0|
// |p0 - xp2 | X = |0| ===> AX = 0
// |y'p2' - p1' | |0|
// |p0' - x'p2'| |0|
// 变成程序中的形式:
// |xp2 - p0 | |0|
// |yp2 - p1 | X = |0| ===> AX = 0
// |x'p2'- p0'| |0|
// |y'p2'- p1'| |0|
// 然后就组成了一个四元一次正定方程组,SVD求解,右奇异矩阵的最后一行就是最终的解.
//这个就是上面注释中的矩阵A
cv::Mat A(4,4,CV_32F);
//构造参数矩阵A
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;
//对系数矩阵A进行奇异值分解
cv::SVD::compute(A,w,u,vt,cv::SVD::MODIFY_A| cv::SVD::FULL_UV);
//根据前面的结论,奇异值分解右矩阵的最后一行其实就是解,原理类似于前面的求最小二乘解,四个未知数四个方程正好正定
//别忘了我们更习惯用列向量来表示一个点的空间坐标
x3D = vt.row(3).t();
//为了符合其次坐标的形式,使最后一维为1
x3D = x3D.rowRange(0,3)/x3D.at<float>(3);
}
Schur 消元 (Schur trick) 、舒尔补。在 SLAM 研究中亦称为 Marginalization(边缘化)
(1) 为什么SLAM需要滑动窗口算法?
·随着VSLAM系统不断往新环境探索,就会有新的相机姿态以及看到新的环境特征,最小二乘残差就会越来越多,信息矩阵越来越大,计算量将不断增加。
·为了保持优化变量的个数在一定范围内,需要使用滑动窗口算法动态增加或移除优化变量。
(2) 滑动窗口算法大致流程
增加新的变量进入最小二乘系统优化
如果变量数目达到了一定的维度,则移除老的变量。
SLAM系统不断循环前面两步
4个,3个求解,1个验证
R的自由度为3,知道R11 R12 R21就能求出剩下的Rxx,平移向量的3个未知数,一共6个未知数。
只有一个点的自由度是多少?两个点呢?
二维码恢复相对位置,六个自由度,哪个自由度上对噪声比较敏感?
怎么用EKF融合多传感器信息?
单目视觉如何测量深度?
相机内参K的单位。
roslaunch可以用来启动定义在launch文件中的多个节点,通常的命名方案是以.launch作为启动文件的后缀,启动文件是xml文件,一般把启动文件存储在取名为launch的目录中,用法
$ roslaunch [package] [filename.launch]
rosrun是运行一个单独节点的命令,如果要运行多个节点,则需要使用多次rosrun命令
特征点匹配中,如何避免误匹配?
后端BA中,如何存在outlier一般怎么解决?
如果给你一个不连续函数,如何求导?
代码,手写KD-Tree
BA[1](光束平差法,捆集约束)的本质是一个图优化模型,其主要目的是构建最小化重投影误差模型或光度误差模型,用于优化相机位姿和地图点。一般选择LM(Levenberg-Marquardt)算法并在此基础上利用BA模型的稀疏性进行计算;可以直接计算(可以使用g2o或者Ceres等优化库进行计算)。
Bundle Adjustment : 从视觉重建中提炼出最优的3D模型和相机参数(内参和外参),好似每一个特征点都会反射几束光线,当把相机位姿和特征点位置做出最优的调整后,这些光线都收束到相机光心。也就是根据相机的投影模型构造构造代价函数,利用非线性优化(比如高斯牛顿或列文伯格马夸而尔特)来求最优解,利用雅克比矩阵的稀疏性解增量方程,得到相机位姿和特征点3D位置的最优解。
基本流程
Perspective-n-Points, 是求解3D到2D点对运动的方法。
通常用于特征点法,在已经有三角化以后的3D地图点(拥有世界坐标)和当前图像帧像素点的匹配对时(例如ORBSLAM里是通过计算描述子匹配3D地图点和像素点),通过重投影地图点到当前帧以获取重投影误差获取当前帧的位姿的过程,称为PNP。