接上一篇博客《直接法光度误差导数推导》,DSO 代码中 CoarseInitializer::trackFrame 目的是优化两帧(ref frame 和 new frame)之间的相对状态和 ref frame 中所有点的逆深度。

在代码中出现了变量Hsc和变量bsc,其中的"sc"是指 Schur Complement。依据这个事实就能够确定整个优化过程的所有细节。

一下假设 ref frame 上需要优化逆深度的点共有 N 个。

首先构建 Gauss Newton 方程,需要优化的参数共有 N + 8 个。

\[J^TJ \delta x = - J^T r_{21}
\]

其中\(\delta x\)是一个(N+8)x1的向量,\(J\) 是 Nx(N+8) 的矩阵,第 i 行表示\(r_{21}^{(i)}\) 对\(\delta x\)的导数(求导得到的结果就是“横着”的),\(r_{21}\)是 Nx1 的向量。

\[\begin{align}\delta x &= \begin{bmatrix} \delta \rho^{(1)} & \delta \rho^{(2)} & \dots & \delta \rho^{(N)} & \delta \xi_{21}^{(1)} & \delta \xi_{21}^{(2)} & \dots & \delta \xi_{21}^{(6)} & \delta a_{21} & \delta b_{21} \end{bmatrix}^T \notag \\
& = \begin{bmatrix} \delta \rho^T & \delta x_{21}^T \end{bmatrix}^T\notag \end{align}\]

\(x_{21}\) 表示量帧之间的相对状态转换,包括 8 个参数。

\[\begin{align} J &= \begin{bmatrix} \partial r_{21}^{(1)} \over \partial \rho^{(1)} & \partial r_{21}^{(1)} \over \partial \rho^{(2)} & \dots & \partial r_{21}^{(1)} \over \partial \rho^{(N)} & \partial r_{21}^{(1)} \over \partial \xi_{21}^{(1)} & \partial r_{21}^{(1)} \over \partial \xi_{21}^{(2)} & \dots & \partial r_{21}^{(1)} \over \partial \xi_{21}^{(6)} & \partial r_{21}^{(1)} \over \partial a_{21} & \partial r_{21}^{(1)} \over \partial b_{21} \\
\partial r_{21}^{(2)} \over \partial \rho^{(1)} & \partial r_{21}^{(2)} \over \partial \rho^{(2)} & \dots & \partial r_{21}^{(2)} \over \partial \rho^{(N)} & \partial r_{21}^{(2)} \over \partial \xi_{21}^{(1)} & \partial r_{21}^{(2)} \over \partial \xi_{21}^{(2)} & \dots & \partial r_{21}^{(2)} \over \partial \xi_{21}^{(6)} & \partial r_{21}^{(2)} \over \partial a_{21} & \partial r_{21}^{(2)} \over \partial b_{21} \\
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\
\partial r_{21}^{(N)} \over \partial \rho^{(1)} & \partial r_{21}^{(N)} \over \partial \rho^{(2)} & \dots & \partial r_{21}^{(N)} \over \partial \rho^{(N)} & \partial r_{21}^{(N)} \over \partial \xi_{21}^{(1)} & \partial r_{21}^{(N)} \over \partial \xi_{21}^{(2)} & \dots & \partial r_{21}^{(N)} \over \partial \xi_{21}^{(6)} & \partial r_{21}^{(N)} \over \partial a_{21} & \partial r_{21}^{(N)} \over \partial b_{21} \end{bmatrix} \notag \\
& = \begin{bmatrix} J_\rho & J_{x_{21}} \end{bmatrix}\notag \end{align}\]

Gauss Newton 方程可以进一步写成

\[\begin{bmatrix} (J_\rho^TJ_\rho)_{N \times N} & (J_\rho^TJ_{x_{21}})_{N \times 8} \\ (J_{x_{21}}^TJ_\rho)_{8 \times N} & (J_{x_{21}}^TJ_{x_{21}})_{8 \times 8} \end{bmatrix} \begin{bmatrix} \delta \rho \\ \delta x_{21} \end{bmatrix} = - \begin{bmatrix} J_\rho^T r_{21} \\ J_{x_{21}}^T r_{21}\end{bmatrix}
\]

\[\begin{bmatrix} H_{\rho\rho} & H_{\rho x_{21}} \\ H_{\rho x_{21}}^T & H_{x_{21}x_{21}} \end{bmatrix} \begin{bmatrix} \delta \rho \\ \delta x_{21} \end{bmatrix} = - \begin{bmatrix} J_\rho^T r_{21} \\ J_{x_{21}}^T r_{21}\end{bmatrix}
\]

Schur Complement 消除 \(\delta \rho\):

\[\begin{bmatrix} H_{\rho\rho} & H_{\rho x_{21}} \\ 0 & H_{x_{21}x_{21}} - H_{\rho x_{21}}^TH_{\rho\rho}^{-1}H_{\rho x_{21}} \end{bmatrix} \begin{bmatrix} \delta \rho \\ \delta x_{21} \end{bmatrix} = - \begin{bmatrix} J_\rho^T r_{21} \\ J_{x_{21}}^T r_{21} - H_{\rho x_{21}}^TH_{\rho\rho}^{-1} J_\rho^T r_{21} \end{bmatrix}
\]

CoarseInitializer::trackFrame 是调用了 CoarseIntializer::calcResAndGS 计算 Gauss Newton 相关的数值。

在函数 CoarseIntializer::calcResAndGS 中变量acc9与公式中的\(H_{x_{21}x_{21}}, J_{x_{21}}^T r_{21}\)相关,acc9SC与公式中的\(H_{\rho x_{21}}^TH_{\rho\rho}^{-1}H_{\rho x_{21}}, H_{\rho x_{21}}^TH_{\rho\rho}^{-1} J_\rho^T r_{21}\)相关。

acc9.H是9x9的矩阵:

\[\begin{bmatrix} J_{x_{21}}^TJ_{x_{21}} & J_{x_{21}}^Tr_{21} \\ J_{x_{21}} r_{21} & r_{21}r_{21} \end{bmatrix}
\]

acc9的累加在两个循环内部,循环是遍历 patternNum。

第一个循环 for(int i=0;i+3<patternNum;i+=4) 内部是 acc9.updateSSE

acc9.updateSSE 使用了 Intel 的 Streaming SIMD Extensions (SSE),一次操作取 4 个 float,完成 4 个不同数据、相同命令的 float 运算。这种一次 4 个数据的操作,说明了循环的 i 增量是 4。算法现在使用的 patternNum 是 8(8%4==0),所以当前循环可以完成所有 pattern 点的操作。如果 patternNum%4 != 0,剩下的余数就可以用第二个循环 for(int i=((patternNum>>2)<<2); i < patternNum; i++)((patternNum>>2)<<2)把最后两个 bit 设置为 0,得到了小于 patternNum 的最大的 4 的倍数,这个循环每次进行 1 个float运算,把最后未循环到的 pattern 点补足。

为了理解acc9SC需要将前面的两个舒尔补矩阵进行变换:

\[\begin{align}H_{\rho x_{21}}^TH_{\rho\rho}^{-1}H_{\rho x_{21}} &= (J_\rho^TJ_{x_{21}})^T (J_\rho^TJ_\rho)^{-1}J_\rho^TJ_{x_{21}}\notag \\
&= {1 \over J_\rho J_\rho^T} J_{x_{21}}^TJ_\rho (J_\rho^TJ_\rho)^{-1} J_\rho^T J_\rho J_\rho^T J_{x_{21}} \notag \\
&= {1 \over J_\rho J_\rho^T} J_{x_{21}}^TJ_\rho J_\rho^T J_{x_{21}} \notag \end{align}\]

\[\begin{align} H_{\rho x_{21}}^TH_{\rho\rho}^{-1} J_\rho^T r_{21} &= (J_\rho^TJ_{x_{21}})^T (J_\rho^TJ_\rho)^{-1}J_\rho^Tr_{21} \notag \\
&= {1 \over J_\rho J_\rho^T} J_{x_{21}}^TJ_\rho J_\rho ^Tr_{21} \notag \end{align}\]

JbBuffer_new在 idx pattern 循环内,分别对每点的8个 pattern 的\(J_{x_{21}}^TJ_\rho, J_\rho^Tr_{21}, J_\rho J_\rho^T\)进行累加。最后在 idx 点循环完成之后,使用JbBuffer_new中的数据对acc9SC进行处理,累加得到最终的结果。在处理的过程中代码

JbBuffer_new[i][9] = 1 / (1 + JbBuffer_new[i][9]);

对应着\({1 \over J_\rho J_\rho^T}\),分母里多了一个1,猜测是为了防止JbBuffer_new[i][9]太小造成系统不稳定。

回到函数 CoarseInitializer::trackFrame 中,在得到相关的矩阵之后,变量H, Hsc相减解算\(x_{21}\),对Hsc加了一个权值1/(1+lambda),并且在接受更新时降低lambda提高了Hsc的权重。这个权重相当于是\(d\)对于\(x_{21}\)的权重。

对\(x_{21}\)的更新很容易看到,对\(d\)的更新在 CoarseInitializer::doStep 中。

float b = JbBuffer[i][8] + JbBuffer[i].head<8>().dot(inc);
float step = -b * JbBuffer[i][9] / (1 + lambda);

在得到\(\delta x_{21}\)之后可以代回求\(\delta \rho\):

\[ H_{\rho\rho}\delta \rho + H_{\rho x_{21}}\delta x_{21} = -J_\rho^Tr_{21} \\
\delta \rho = -H_{\rho\rho}^{-1}(J_\rho^Tr_{21} + H_{\rho x_{21}}\delta x_{21})\]

对于每一个点,代码中inc对应\(\delta x_{21}\),JbBuffer[i].head<8>()对应\(H_{\rho x_{21}}\)的第 8*i 行到第 8*i+7 行,JbBuffer[i][8]对应\(J_\rho^Tr_{21}\)的第 8*i 行到第8*i+7 行,JbBuffer[i][9]对应\(H_{\rho\rho}^{-1}\)的\((i, i)\)位置上的 Scalar。

DSO 优化代码中的 Schur Complement的更多相关文章

  1. 如何优化代码中大量的if/else,switch/case?

    前言 随着项目的迭代,代码中存在的分支判断可能会越来越多,当里面涉及到的逻辑比较复杂或者分支数量实在是多的难以维护的时候,我们就要考虑下,有办法能让这些代码变得更优雅吗? 正文 使用枚举 这里我们简单 ...

  2. 面试官:优化代码中大量的if/else,你有什么方案?

    一个快速迭代的项目,时间久了之后,代码中可能会充斥着大量的if/else,嵌套6.7层,一个函数几百行,简!直!看!死!人! 这个无限循环嵌套,只是总循环的一部分...我已经绕晕在黄桷湾立交 仔细数了 ...

  3. 使用with子句优化代码中重复查询

    /*好处: 1. 性能更好,一份复制(类似SYS_TMP...),多份使用.       2. 结构清晰,预先定义.       3. 代码修改不必修改多处.       请注意观察语句1和语句2执行 ...

  4. 代码中如何优化过多的if..else

    针对代码中,过多的  if ... else ..,如何优化减少if else呢?(非常重要的优化技巧) 缺点:过多的if else 导致阅读不方便,逻辑过于复杂,代码多长. 解决方法:可以采用多个方 ...

  5. sliding window:"Marginalization","Schur complement","First estimate jacobin"

    [1]知行合一2 SLAM中的marginalization 和 Schur complement SLAM的Bundle Adjustment上,随着时间的推移,路标特征点(landmark)和相机 ...

  6. 前端页面卡顿?或是DOM操作惹的祸,需优化代码

    文档对象模型(DOM)是一个独立 于特定语言的应用程序接口.在浏览器中,DOM接口是以JavaScript语言实现的,通过JavaScript来操作浏览器页面中的元素,这使得 DOM成为了JavaSc ...

  7. 优化Web中的性能

    优化Web中的性能 简介 web的优化就是一场阻止http请求最终访问到数据库的战争. 优化的方式就是加缓存,在各个节点加缓存. web请求的流程及节点 熟悉流程及节点,才能定位性能的问题.而且优化的 ...

  8. 一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)

    问题: 问题出处见 C语言初学者代码中的常见错误与瑕疵(5) . 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己 ...

  9. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

随机推荐

  1. 冲刺Two之站立会议4

    在完成了对主界面的设计之后,我们对自己的聊天室界面进行了优化,添加了一些标签和图片按钮等组件让界面更加美观一些.然后还查询了一些关于改进视频和音频质量的资料,准备开展相关工作.

  2. 第二个spring冲刺第3天

    今天天气突然变得很冷,所以我们队的人都有少许的不适.加上天气比较冷,我们都不怎么想做.幸好在队长的提醒下,我们终于继续投入研发的工作中.由于市面上的同类软件的数量不少所以我们下载了一些来看,希望能找到 ...

  3. 第十一周(11.24-12.01)----ptim测试程序运行速度

    我在dos下用ptime指令对分数运算(http://www.cnblogs.com/YangXiaomoo/p/6095583.html)的运行时间进行了测试.测试结果一般都在0.212-0.217 ...

  4. 设置macbook休眠模式

    前言: macbook默认合上盖默认是进入混合休眠模式模式(mode 3),此时电脑还会供电.不想耗电的话关机的话当前的工作状态就丢失了. macbook实际上是可以进入休眠模式的,只是没开放出来,我 ...

  5. dotTrace 每行执行时间和执行次数

    如果代码中出现效率问题,使用dotTrace来跟踪分析代码的效率问题还是很方便的.使用dotTrace不但可以看到每一个方法被调用的次数和总时间,而且可以引入源代码,查看源代码中每一行执行的次数和时间 ...

  6. 关于“代码规范”,“Review”和“Check list”

    关于“代码规范”,“Review”和“Check list”,就我个人理解,这三者相辅相成.代码规范是在编程时就该注意的,为Review减轻负担.而要进行Review,又需要一个Check list作 ...

  7. delphi 登陆窗口的问题 [问题点数:30分,结帖人tianhuo_soft]

    http://bbs.csdn.net/topics/200053917 有两个窗口formLogin是登陆窗口,formMain是主窗口我想让formMain显示出来,并且formLogin窗口关闭 ...

  8. 如何取消mysql的密码?

    有两种方法: 1.mysql命令 SET PASSWORD FOR root@localhost=PASSWORD(''); 2.运行  mysqladmin 命令 mysqladmin -u roo ...

  9. HGOI20180814 (NOIP 模拟Day1)

    100pts=40+60+0 rank 56 若串联那么显然是这样: 若并联那么显然是这样: 串联时C<1,并联时C>1,贪心策略<1时尽可能串联,>1时尽可能并联 考虑这样一 ...

  10. CF1110E Magic Stones(构造题)

    这场CF怎么这么多构造题…… 题目链接:CF原网 洛谷 题目大意:给定两个长度为 $n$ 的序列 $c$ 和 $t$.每次我们可以对 $c_i(2\le i<n)$ 进行一次操作,也就是把 $c ...