美文网首页
SVO:FrameHandler

SVO:FrameHandler

作者: 爱毯子的小狮子 | 来源:发表于2020-07-28 15:39 被阅读0次

    FrameHandlerMono是主类,总领一切。继承自FrameHandlerBase。拥有的field不多,有:
    cam_相机模型,reprojector_重投影,new_frme_当前帧,last_frame_上一帧,depth_filter_深度滤波器等

    初始化即设置了cam_reprojector_depth_filter_。并且调用initialize(),开启深度滤波器线程(见上一篇)。

    之后需要调用start(),此为继承的函数,仅设置flag:set_start_

    再调用addImage(),在循环中逐帧添加,即开启了全部的运行。

    void FrameHandlerMono::addImage(const cv::Mat& img, const double timestamp)
    函数体很简单,
    startFrameProcessingCommon(timestamp),查看set_start_是否立起,若是,则resetAll()(在里面将set_start_置为0),并将stage_设置为STAGE_FIRST_FRAME;查看stage_的状态是否是暂停,是就返回False,
    然后用新图片重新设置new_frame_
    接着是下图的4个分支,
    最后交接last_frame_,并调用finishFrameProcessingCommon(last_frame_->id_, res, last_frame_->nObs()),主要是一些总结(设置状态field)和记录、输出工作。

    4个分支

    FrameHandlerMono::UpdateResult FrameHandlerMono::processFirstFrame()

    stage_在第一帧设置成功后改变了

    首先使用klt_homography_init_.addFirstFrame() 初始化第一帧,如果因为找到的特征点太少了而返回失败,那么就重新reset。值得一提的是,目前特征点存储在klt_homography_init_自己的相应的ref和cur变量里面,和FrameHandlerMono没有关系。而提取特征点用的都是第三方类FastDetector,先存在局部变量里面,后拷贝,这样应该是利于变更detector算法。
    当上一步成功后,调用setKeyframe()。仅仅如图

    只有两行

    其中,setKeyPoints()所做之事就是设置Frame里面的key_pts_,这是由5个特征点组成的向量,分别代表图像里最四个角和最中间的特征点。通过遍历Frame里的所有特征点找到。【这里有很大的疑问,可能我错了,也可能代码错了:a)既然特征点只保存在klt_homography_init_的field里,那么怎么能遍历Frame的特征点呢? b)设置这5个点的代码也不对,存在很大错误,大于号小于号搞错了,后两个if里的比较也错了】

    FrameHandlerBase::UpdateResult FrameHandlerMono::processSecondFrame()
    比处理第一帧要复杂得多,仍是调用klt_homography_init_.addSecondFrame(new_frame_)
        a)trackKlt():调用opencv方法计算前两帧的KLT光流,该方法是计算第一帧的特征点在第二帧上的跟踪。然后保存每个光流的大小,叫disparities_,其数量和大小若太小则失败;
        b)computeHomography():用二维像素点,焦距等计算单应矩阵【不明白为什么二维点要用单位球投影得到,明明之前已经得到特征点了,并且单位球就是由特征点算出来的】。然后从单应矩阵计算transform,具体求解过程没有详细看,他是使用decomposition的方法而不是线性方程组法。并且由于我们的特征值不一定在同一平面所以要用RANSAC找出inlier。计算单应矩阵的方法是opencv提供的。inliers最后还计算了其三维坐标点。
        c)由于scale是不可求的,就认为规定一个,让计算除的三维坐标点rescale一下,同事translation也要rescale。
        d)将inlier对应的3D点验证合法性,然后加入一、二帧。
    同第一帧一样设置为关键帧setKeyframe()
    调用depth_filter_->addKeyframe(new_frame_, depth_mean, 0.5*depth_min),参数为第二帧,其平均深度,其最小深度:

    addKeyframe(new_frame_, depth_mean, 0.5*depth_min)

    这就是之前深度滤波器的循环为什么要线程同步的原因了,这里有notify_one()。这里如果滤波器线程没开启就自己初始化种子,如果开启就通知滤波器线程让它做后续工作。
    最后将关键帧加入map_stage_改为STAGE_DEFAULT_FRAME

    FrameHandlerBase::UpdateResult FrameHandlerMono::processFrame()
    基本就是那三步。

    相关文章

      网友评论

          本文标题:SVO:FrameHandler

          本文链接:https://www.haomeiwen.com/subject/qcawlktx.html