美文网首页
SVO:深度滤波器

SVO:深度滤波器

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

    定义的一些类:

    Frame:帧
    Feature:特征点,包含二维像素坐标,三维的单位求面上的坐标。二维坐标用金字塔最底层(0层)来表示,但特征不一定是0层提取的,所以要记录该特征所提取的层。
    Point:3D坐标点,先对世界坐标系。

    其中Frame包含一系列Feature,每个Frame的Feature都是独一无二的,即使有些对应同一个3D点。Frame不包含Point,而Feature指向其对应的那个3D点,所有Frame可通过Feature找到Point。Point包含一系列Feature,都是不同帧观察到的该点留下的Feature。

    深度滤波器

    DepthFilter,为主类FrameHandlerMono的构造函数中除了列表初始化外唯一的内容,initialize(),里做的唯一一件事,实例化其域depth_filter_,并运行startThread()

    新建的feature_detector和depth_filter_cb用来初始化depth_filter_的域

    startThread()里有只有唯一内容,就是开启新线程,运行DepthFilter::updateSeedsLoop()

    DepthFilter里有用List管理起来的Seedseeds_

    DepthFilter::updateSeedsLoop()
    这里的逻辑有点复杂。首先这个深度滤波器线程一直在循环,除非有停止的要求。这个循环实质上是对frame_queue_的管理:先将frame_queue_mut_锁定。
    1. 判断当frame_queue_空,且现在没有一个新的关键帧要处理(new_keyframe_set_未置位)时,线程进入等待frame_queue_mut_的状态;
    2. 当frame_queue_不为空,往下走,若有新关键帧要处理,则清楚所有当前队列,处理关键帧;若没有,就处理队列的第一帧;
    3. 当frame_queue_为空,但有新关键帧要处理,仍然往下走,清楚所有当前队列,处理关键帧。
    因此该函数的工作过程应该是这样的:队列里有帧就按顺序处理,处理方法是统一先updateSeeds(frame),即通过将Seed投影到该帧的方式更新它们,然后判断如果该帧是关键帧,再初始化一些SeedinitializeSeeds(frame))。不断循环直到队列空了。而无论何时,只要有新关键帧要处理,立马停止一切Seed的更新,清除队列内容,开始处理那个关键帧,处理方法同上。这种置位new_keyframe_set_的关键帧优先级最高。new_keyframe_set_frame->isKeyframe()是同步的。

    void DepthFilter::initializeSeeds(FramePtr frame)
    检测frame中的新特征点,检测之前要先设置AbstractDetector::grid_occupancy_,新的特征点如果在已经被占据的格子里,那么就跳过而不会添加。检测使用fast角点,依赖fast库,是之前安装的。我们保证每一个格子都有一个,而且是score最高的。在金字塔的每一层都检测一遍fast角点,然后查看格子状态,然后比较score。最终一个格子里的点要么是已有的,要么是该区域内金字塔里得分最高的那个。最后要将格子的状态全部重置为0。
    然后每个新特征点都初始化一个Seed,push进seeds_。push的过程用seeds_mut_锁定。注意在lock前将seeds_updating_halt_置位1,lock结束前的最后置位0。这些线程操作意在使seeds_增加新成员的时候,updateSeeds()过程能够中断,避免发送冲突。值得注意的是虽然在updateSeedsLoop()里面updateSeeds()和本函数是次第执行的,但是深度滤波器外的其他线程也有使用updateSeeds()的地方,所以还是有必要的。

    void DepthFilter::updateSeeds(FramePtr frame)
    全函数都在seeds_mut_的锁定中。遍历seeds_链表里的每一个Seed:果seeds_updating_halt_置位了,直接返回(注意是整个函数就返回了);所属的帧在最新的Seed的3帧开外,直接抹除并跳过;warping不到当前帧,跳过;
    当有一个合法映射后,直接调用matcher_.findEpipolarMatchDirect()找到对应点,如果返回False,那么扩大beta分布的b,增加错误匹配的计数,然后跳过。
    返回true,那么计算tau,几深度方差相关的数。再调用updateSeed(),该函数更新此Seed的filed,然后增加好的匹配的计数。
    最后当好Seed更新完了之后,检查是否为关键帧frame->isKeyframe()(注意这里不做判断,只是读取该帧的field,了解是否置位),若是则画格子,这一步是为了确保点分布均匀。
    最后判断该Seed是否收敛,收敛则初始化一个3D点并移除该点,并加入candidate list,若发散则抹除,没到收敛域则不做什么,该点将继续被update。

    相关文章

      网友评论

          本文标题:SVO:深度滤波器

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