课程Github地址:https://github.com/wrk666/VSLAM-Course/tree/master
仍然是前端的内容,估计位姿,不过不是特征点法,而是另外的方法。
之前的前端工作流程:
其中前3步是一定要做的,但是特征的提取(主要是描述子费时)和匹配又是非常耗时,所以考虑用更快的方法来拿到点与点之间的对应关系。
1图提取出了特征点,对2图不进行提取,找1图中的点在2图中的哪里(Track)。
给定一个强假设:t和t+dt时刻同一像素的亮度不变(但实际中不太可能成立,光线,材质,曝光等都会影响像素的亮度)
未知数多,方程少:欠定
未知数少,方程多:超定
光流法也可以进行物体跟踪,相机不动,对一辆车在远处时采集一个特征点,不断跟踪这个特征点,就能够估计出车的运动轨迹,实现物体跟踪。早期是这样做的,但是后期出现了Deep Learning都用DL了。
对于之前的灰度不变假设,可以用一些手段处理,如去均值,归一化等。
对于梯度,可以在原始图像或者目标图像中计算,比如在 I 1 I_1 I1中是角点,在 I 2 I_2 I2中就不是角点了。(如何在目标图像中计算?不知道在哪啊,作业中会做,有参考文献)
光流法没有用到相机的3D投影模型,仅仅是2D-2D的方法。
没有考虑相机的旋转和缩放。
直接法是估计相机本身的旋转和平移,而不是每个点的旋转和平移。
直接建立最小二乘问题:
已知 I 1 I_1 I1中的特征点 p 1 p_1 p1,构建光度误差,对齐进行最小化。
待估计的是相机的运动情况,这里取相机运动的李代数 ζ \zeta ζ,这里关键的就是如何求雅可比,
实际上这里是通过优化相机的位姿,来寻找与 p 1 p_1 p1更相似的 p 2 p_2 p2,但这里优化的不是重投影误差,而是光度误差(两个像素的亮度误差)。
3. 这个问题通过直接法可以来解决,因为直接法使用的是整个相机的运动,而不是通过某几对点之间的匹配来确定的。这导致直接法在选点的时候选择有梯度的点即可,不需要每次都提角点或者有重复的点,也没有光流的那种假设。(有人设计特征:线的,圆的等,但是需要考虑的情况很多)
直接法可以处理渐变的图像(有梯度),只要保持采光一致。
直接法的缺点:和光流法一样,很依赖于pose估计的准确性(这不就是来估计吗?不太理解)
Opencv Optical Flow有一个module的介绍,可以去看
OpenCV没有直接法,使用g2o解(g2o)本身就是一个解最小二乘问题的一个库。
说是可以使用雅可比也可以不使用(不太理解)
也可以用ceres或者自己手写高斯牛顿法求解,也可以套多层的金字塔。
可以用多点的像素误差(类似于光流的5*5窗口)
这里例程出了点问题,使用的slambook ch8的代码poseEstimationDirect
这个函数出问题,看了一些博客应该是指针的错误,看到g2o时再说。对照之前3d2d的代码改了改前几句:
#include //G-N 使用相应的求解方法需要引库
#include //LM
bool poseEstimationDirect ( const vector< Measurement >& measurements, cv::Mat* gray, Eigen::Matrix3f& K, Eigen::Isometry3d& Tcw )
{
// 初始化g2o
typedef g2o::BlockSolver<g2o::BlockSolverTraits<6,1>> DirectBlock; // 求解的向量是6*1的
typedef g2o::LinearSolverDense<DirectBlock::PoseMatrixType> LinearSolverType; //线性求解器类型
//梯度下降方法
// auto solver = new g2o::OptimizationAlgorithmGaussNewton( g2o::make_unique(g2o::make_unique()));
auto solver = new g2o::OptimizationAlgorithmLevenberg ( g2o::make_unique<DirectBlock>(g2o::make_unique<LinearSolverType>()));
CMAkeLists.txt:
当时我改了link的库,出了个岔子,这里用的是库里面的节点VertexSE3Expmap
,需要linkg2o_types_sba
这个库,我给删了,整半天,老是这个报错
undefined reference to `g2o::VertexSE3Expmap::VertexSE3Expmap()‘
最终的CMakeLists.txt
cmake_minimum_required( VERSION 2.8 )
project( directMethod )
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS "-std=c++11")
# 添加cmake模块路径
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
find_package( OpenCV 3 REQUIRED)
find_package( G2O REQUIRED)
find_package(Sophus REQUIRED)
include_directories(
${OpenCV_INCLUDE_DIRS}
${G2O_INCLUDE_DIRS}
"/usr/include/eigen3/"
${Sophus_INCLUDE_DIRS}
)
set( G2O_LIBS g2o_core g2o_types_sba g2o_solver_csparse g2o_stuff g2o_csparse_extension)
add_executable( direct_sparse direct_sparse.cpp )
target_link_libraries( direct_sparse
${OpenCV_LIBS}
${G2O_LIBS}
g2o_core g2o_stuff
)
add_executable( direct_semidense direct_semidense.cpp )
target_link_libraries( direct_semidense ${OpenCV_LIBS} ${G2O_LIBS} )