DSO windowed optimization 代码

这里不想解释怎么 marginalize,什么是 First-Estimate Jacobian。这里只想看看代码,看看Hessian矩阵是怎么构造出来的。

代码中用于存储窗口优化过程Hessian矩阵使用的导数存储在结构体RawResidualJacobian中。

https://github.com/JakobEngel/dso/blob/master/src/OptimizationBackend/RawResidualJacobian.h#L32

struct RawResidualJacobian
{
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
    // ================== new structure: save independently =============.
    VecNRf resF; // typdef Eigen::Matrix<float,MAX_RES_PER_POINT,1> VecNRf; MAX_RES_PER_POINT == 8

    // the two rows of d[x,y]/d[xi].
    Vec6f Jpdxi[2];         // 2x6

    // the two rows of d[x,y]/d[C].
    VecCf Jpdc[2];          // 2x4

    // the two rows of d[x,y]/d[idepth].
    Vec2f Jpdd;             // 2x1

    // the two columns of d[r]/d[x,y].
    VecNRf JIdx[2];         // 9x2

    // = the two columns of d[r] / d[ab]
    VecNRf JabF[2];         // 9x2

    // = JIdx^T * JIdx (inner product). Only as a shorthand.
    Mat22f JIdx2;               // 2x2
    // = Jab^T * JIdx (inner product). Only as a shorthand.
    Mat22f JabJIdx;         // 2x2
    // = Jab^T * Jab (inner product). Only as a shorthand.
    Mat22f Jab2;            // 2x2

};

以上变量的类型中出现NR,说明该变量是存储了每一个 pattern 点的信息。

现在将这些变量对应的导数一一列出:

  1. VecNRf resF;对应\(r_{21}\),1x8,这里的\(r_{21}\)是对于一个点,八个 pattern residual 组成的向量。
  2. Vec6f Jpdxi[2];对应\(\partial x_2 \over \partial \xi_{21}\),2x6,注意这里的\(x_2\)是像素坐标。(我一般把像素坐标写成\(x\),对应代码中的变量Ku,归一化坐标写成\(x^{\prime}\),对应代码中的变量u。)
  3. VecCf Jpdc[2];对应\(\partial x_2 \over \partial C\),这里的\(C\)指相机内参\(\begin{bmatrix} f_x, f_y, c_x, c_y\end{bmatrix}^T\)。
  4. Vec2f Jpdd;对应\(\partial x_2 \over \partial \rho_1\),2x4,注意是对 host 帧的逆深度求导。
  5. VecNRf JIdx[2];对应\(\partial r_{21} \over \partial x_2\),8x2,这个和 target 帧上的影像梯度相关。
  6. VecNRf JabF[2];对应\({\partial r_{21} \over \partial a_{21}}, {\partial r_{21} \over \partial b_{21}}\),8x1,8x1。
  7. Mat22f JIdx2;对应\({\partial r_{21} \over \partial x_2}^T{\partial r_{21} \over \partial x_2}\),2x8 8x2,2x2。
  8. Mat22f JabJIdx;对应\(\begin{bmatrix}{\partial r_{21} \over \partial a_{21}} & {\partial r_{21} \over \partial b_{21}} \end{bmatrix}^T{\partial r_{21} \over \partial x_2}\),2x8 8x2,2x2。
  9. Mat22f Jab2;对应\(\begin{bmatrix}{\partial r_{21} \over \partial a_{21}} & {\partial r_{21} \over \partial b_{21}} \end{bmatrix}^T\begin{bmatrix}{\partial r_{21} \over \partial a_{21}} & {\partial r_{21} \over \partial b_{21}} \end{bmatrix}\),2x8 2x8,2x2。

在 PointFrameResidual::linearize 中对这些变量进行了计算。

https://github.com/JakobEngel/dso/blob/master/src/FullSystem/Residuals.cpp#L78

在计算时使用了投影过程中的变量,现在将这些变量与公式对应。投影过程标准公式如下:

\[\begin{align} x_2 &= K \rho_2 (R_{21} \rho_1^{-1} K^{-1} x_1 + t_{21}) \notag \\
&= K x^{\prime}_2\notag \end{align}\]

变量的对应关系如下:

KliP = \(K^{-1}x_1\) = \(x_1^{\prime}\)

ptp = \(R_{21}K^{-1}x_1 + \rho_1 t_{21}\) = \(\rho_2^{-1}\rho_1K^{-1}x_2\)

drescale = \(\rho_2 \rho_1^{-1}\)

[u, v, 1]^T = \(K^{-1}x_2\) = \(x_2^{\prime}\)

[Ku, Kv, 1]^T = \(x_2\)

1. Vec2f Jpdd;\(\partial x_2 \over \partial \rho_1\)
d_d_x = drescale * (PRE_tTll_0[0]-PRE_tTll_0[2]*u)*SCALE_IDEPTH*HCalib->fxl();
d_d_y = drescale * (PRE_tTll_0[1]-PRE_tTll_0[2]*v)*SCALE_IDEPTH*HCalib->fyl();

计算\(\partial x_2 \over \partial \rho_1\),这个在博客《直接法光度误差导数推导》中已经讲了如何求解。得到的结果是:

\[\begin{bmatrix} f_x \rho_1^{-1}\rho_2(t_{21}^x - u^{\prime}_2t_{21}^z) \\ f_y \rho_1^{-1}\rho_2(t_{21}^y - v^{\prime}_2t_{21}^z)\end{bmatrix}\]

2.VecCf Jpdc[2];\(\partial x_2 \over \partial C\)
d_C_x[2] = drescale*(PRE_RTll_0(2,0)*u-PRE_RTll_0(0,0));
d_C_x[3] = HCalib->fxl() * drescale*(PRE_RTll_0(2,1)*u-PRE_RTll_0(0,1)) * HCalib->fyli();
d_C_x[0] = KliP[0]*d_C_x[2];
d_C_x[1] = KliP[1]*d_C_x[3];

d_C_y[2] = HCalib->fyl() * drescale*(PRE_RTll_0(2,0)*v-PRE_RTll_0(1,0)) * HCalib->fxli();
d_C_y[3] = drescale*(PRE_RTll_0(2,1)*v-PRE_RTll_0(1,1));
d_C_y[0] = KliP[0]*d_C_y[2];
d_C_y[1] = KliP[1]*d_C_y[3];

d_C_x[0] = (d_C_x[0]+u)*SCALE_F;
d_C_x[1] *= SCALE_F;
d_C_x[2] = (d_C_x[2]+1)*SCALE_C;
d_C_x[3] *= SCALE_C;

d_C_y[0] *= SCALE_F;
d_C_y[1] = (d_C_y[1]+v)*SCALE_F;
d_C_y[2] *= SCALE_C;
d_C_y[3] = (d_C_y[3]+1)*SCALE_C;

我算对相机内参的导数与代码不一致,先写出我的求导过程。

\[{\partial x_2 \over \partial C} = \begin{bmatrix} {\partial u_2 \over \partial f_x} & {\partial u_2 \over \partial f_y} & {\partial u_2 \over \partial c_x} & {\partial u_2 \over \partial c_y} \\ {\partial v_2 \over \partial f_x} & {\partial v_2 \over \partial f_y} & {\partial v_2 \over \partial c_x} & {\partial v_2 \over \partial c_y} \end{bmatrix}\]

\[\begin{align}x_2 &= Kx_2^{\prime} \notag \\begin{bmatrix} u_2 \\ v_2 \\ 1 \end{bmatrix} &= \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1\end{bmatrix} \begin{bmatrix} u_2^{\prime} \\ v_2^{\prime} \\ 1\end{bmatrix} \notag \end{align}\]

\[\begin{align} u_2 &= f_x u_2^{\prime} + c_x \notag \v_2 &= f_y v_2^{\prime} + c_y \notag \end{align}\]

\[\begin{align} {\partial u_2 \over \partial f_x} &= u_2^{\prime} + f_x {\partial u_2^{\prime} \over \partial f_x} \notag &
{\partial u_2 \over \partial f_y} &= f_x {\partial u_2^{\prime} \over \partial f_y} \notag \\
{\partial u_2 \over \partial c_x} &= f_x {\partial u_2^{\prime} \over \partial c_x} + 1 \notag &
{\partial u_2 \over \partial c_y} &= f_x {\partial u_2^{\prime} \over \partial c_y} \notag \end{align}\]

\[\begin{align} {\partial v_2 \over \partial f_x} &= f_y {\partial v_2^{\prime} \over \partial f_x} \notag &
{\partial v_2 \over \partial f_y} &= v_2^{\prime} + f_y {\partial v_2^{\prime} \over \partial f_y} \notag \\
{\partial v_2 \over \partial c_x} &= f_y {\partial v_2^{\prime} \over \partial c_x} \notag &
{\partial v_2 \over \partial c_y} &= f_y {\partial v_2^{\prime} \over \partial c_y} + 1 \notag \end{align}\]

先求\({\partial x_2^{\prime} \over \partial C}\),再使用链式法则求\({\partial x_2 \over \partial C}\)。

\[\begin{align} x_2^{\prime} &= \rho_2 \rho_1^{-1}(R_{21}K^{-1}x_1+\rho_1t_{21}) \notag \\
&= \rho_2 \rho_1^{-1} R_{21}K^{-1}x_1 + \dots \notag \&= \rho_2 \rho_1^{-1} \begin{bmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33}\end{bmatrix} \begin{bmatrix} f_x^{-1} & 0 & -f_x^{-1}c_x \\ 0 & f_y^{-1} & -f_y^{-1}c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} u_1 \\ v_1 \\ 1 \end{bmatrix} + \dots \notag \&= \rho_2 \rho_1^{-1} \begin{bmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33}\end{bmatrix} \begin{bmatrix} f_x^{-1}(u_1 - c_x) \\ f_y^{-1}(v_1 - c_y) \\ 1 \end{bmatrix} + \dots \notag \end{align}\]

\[\begin{align} u_2^{\prime} &= \rho_2 \rho_1^{-1}(r_{11}f_x^{-1}(u_1 - c_x) + r_{12}f_y^{-1}(v_1-c_y) + r_{13}) + \dots \notag \v_2^{\prime} &= \rho_2 \rho_1^{-1}(r_{21}f_x^{-1}(u_1 - c_x) + r_{22}f_y^{-1}(v_1-c_y) + r_{23}) + \dots \notag \end{align}\]

\[\begin{align} {\partial u_2^{\prime} \over \partial f_x} &= \rho_2 \rho_1^{-1} (-r_{11})f_x^{-2}(u_1 - c_x) \notag &
{\partial u_2^{\prime} \over \partial f_y} &= \rho_2 \rho_1^{-1}(-r_{12})f_y^{-2}(v_1 - c_y) \notag \\
{\partial u_2^{\prime} \over \partial c_x} &= \rho_2 \rho_1^{-1}(-r_{11})f_x^{-1} \notag &
{\partial u_2^{\prime} \over \partial c_y} &= \rho_2 \rho_1^{-1}(-r_{12}) f_y^{-1} \notag \end{align}\]

\[\begin{align} {\partial v_2^{\prime} \over \partial f_x} &= \rho_2 \rho_1^{-1} (-r_{21})f_x^{-2}(u_1 - c_x) \notag &
{\partial v_2^{\prime} \over \partial f_y} &= \rho_2 \rho_1^{-1}(-r_{22})f_y^{-2}(v_1 - c_y) \notag \\
{\partial v_2^{\prime} \over \partial c_x} &= \rho_2 \rho_1^{-1}(-r_{21})f_x^{-1} \notag &
{\partial v_2^{\prime} \over \partial c_y} &= \rho_2 \rho_1^{-1}(-r_{22}) f_y^{-1} \notag \end{align}\]

链式:

\[\begin{align} {\partial u_2 \over \partial f_x} &= u_2^{\prime} + f_x {\partial u_2^{\prime} \over \partial f_x} \notag \\ &= u_2^{\prime} + \rho_2 \rho_1^{-1} (-r_{11})f_x^{-1}(u_1 - c_x) \notag \{\partial u_2 \over \partial f_y} &= f_x {\partial u_2^{\prime} \over \partial f_y} \notag \\ &= f_x f_y^{-1} \rho_2 \rho_1^{-1}(-r_{12})f_y^{-1}(v_1 - c_y) \notag \{\partial u_2 \over \partial c_x} &= f_x {\partial u_2^{\prime} \over \partial c_x} + 1 \notag \\ &= \rho_2 \rho_1^{-1}(-r_{11}) + 1\notag \{\partial u_2 \over \partial c_y} &= f_x {\partial u_2^{\prime} \over \partial c_y} \notag \\ &= f_x f_y^{-1} \rho_2 \rho_1^{-1}(-r_{12}) \notag
\end{align}\]

\[\begin{align} {\partial v_2 \over \partial f_x} &= f_y {\partial v_2^{\prime} \over \partial f_x} \notag \\ &= f_y f_x^{-1} \rho_2 \rho_1^{-1} (-r_{21})f_x^{-1}(u_1 - c_x) \notag \{\partial v_2 \over \partial f_y} &= v_2^{\prime} + f_y {\partial v_2^{\prime} \over \partial f_y} \notag \\ &= v_2^{\prime} + \rho_2 \rho_1^{-1}(-r_{22})f_y^{-1}(v_1 - c_y) \notag \{\partial v_2 \over \partial c_x} &= f_y {\partial v_2^{\prime} \over \partial c_x} \notag \\ &= f_y f_x^{-1} \rho_2 \rho_1^{-1}(-r_{21}) \notag \{\partial v_2 \over \partial c_y} &= f_y {\partial v_2^{\prime} \over \partial c_y} + 1 \notag \\ &= \rho_2 \rho_1^{-1}(-r_{22}) + 1 \notag \end{align}\]

代码认为的导数(去除 scale 参数的影响):

\[\begin{align} {\partial u_2 \over \partial f_x} &= u_2^{\prime} + \rho_2 \rho_1^{-1} (r_{31}u_2^{\prime}-r_{11})f_x^{-1}(u_1 - c_x) \notag \{\partial u_2 \over \partial f_y} &= f_x f_y^{-1} \rho_2 \rho_1^{-1}(r_{32} u_2^{\prime}-r_{12})f_y^{-1}(v_1 - c_y) \notag \{\partial u_2 \over \partial c_x} &= \rho_2 \rho_1^{-1}(r_{31} u_2^{\prime}-r_{11}) + 1 \notag \\
{\partial u_2 \over \partial c_y} &= f_x f_y^{-1} \rho_2 \rho_1^{-1}(r_{32} u_2^{\prime}-r_{12}) \notag \end{align}\]

\[\begin{align} {\partial v_2 \over \partial f_x} &= f_y f_x^{-1} \rho_2 \rho_1^{-1} (r_{31} v_2^{\prime}-r_{21})f_x^{-1}(u_1 - c_x) \notag \{\partial v_2 \over \partial f_y} &= v_2^{\prime} + \rho_2 \rho_1^{-1}(r_{32} v_2^{\prime}-r_{22})f_y^{-1}(v_1 - c_y) \notag \{\partial v_2 \over \partial c_x} &= f_y f_x^{-1} \rho_2 \rho_1^{-1}(r_{31} v_2^{\prime}-r_{21}) \notag \{\partial v_2 \over \partial c_y} &= \rho_2 \rho_1^{-1}(r_{32} v_2^{\prime}-r_{22}) + 1 \notag \end{align}\]

我认为的导数对应的代码如下:

d_C_x[2] = drescale*(-PRE_RTll_0(0,0));
d_C_x[3] = HCalib->fxl() * drescale*(-PRE_RTll_0(0,1)) * HCalib->fyli();
d_C_x[0] = KliP[0]*d_C_x[2];
d_C_x[1] = KliP[1]*d_C_x[3];

d_C_y[2] = HCalib->fyl() * drescale*(-PRE_RTll_0(1,0)) * HCalib->fxli();
d_C_y[3] = drescale*(-PRE_RTll_0(1,1));
d_C_y[0] = KliP[0]*d_C_y[2];
d_C_y[1] = KliP[1]*d_C_y[3];

d_C_x[0] = (d_C_x[0]+u)*SCALE_F;
d_C_x[1] *= SCALE_F;
d_C_x[2] = (d_C_x[2]+1)*SCALE_C;
d_C_x[3] *= SCALE_C;

d_C_y[0] *= SCALE_F;
d_C_y[1] = (d_C_y[1]+v)*SCALE_F;
d_C_y[2] *= SCALE_C;
d_C_y[3] = (d_C_y[3]+1)*SCALE_C;
3. Vec6f Jpdxi[2];\(\partial x_2 \over \partial \xi_{21}\)
d_xi_x[0] = new_idepth*HCalib->fxl();
d_xi_x[1] = 0;
d_xi_x[2] = -new_idepth*u*HCalib->fxl();
d_xi_x[3] = -u*v*HCalib->fxl();
d_xi_x[4] = (1+u*u)*HCalib->fxl();
d_xi_x[5] = -v*HCalib->fxl();

d_xi_y[0] = 0;
d_xi_y[1] = new_idepth*HCalib->fyl();
d_xi_y[2] = -new_idepth*v*HCalib->fyl();
d_xi_y[3] = -(1+v*v)*HCalib->fyl();
d_xi_y[4] = u*v*HCalib->fyl();
d_xi_y[5] = u*HCalib->fyl();

计算\(\partial x_2 \over \partial \xi_{21}\),这个在博客《直接法光度误差导数推导》中已经讲了如何求解。得到的结果是:

\[{\partial x_2 \over \partial \xi_{21}} = \begin{bmatrix} f_x \rho_2 & 0 & -f_x \rho_2 u^{\prime}_2 & -f_xu^{\prime}_2 v^{\prime}_2 & f_x(1 + u^{\prime 2}_2) & -f_x v^{\prime}_2 \\ 0 & f_y\rho_2 & -f_y \rho_2 v^{\prime}_2 & -f_y(1 + v^{\prime 2}_2) & f_y u^{\prime}_2 v^{\prime}_2 & f_y u^{\prime}_2 \\ 0 & 0 & 0 & 0 & 0 & 0\end{bmatrix}\]

4. VecNRf JIdx[2];对应\(\partial r_{21} \over \partial x_2\)
J->JIdx[0][idx] = hitColor[1];
J->JIdx[1][idx] = hitColor[2];

计算\(\partial r_{21} \over \partial x_2\),这个在博客《直接法光度误差导数推导》中已经讲了如何求解。得到的结果是:

\[{\partial r_{21} \over \partial x_{2}} = w_h {\partial I_2[x_2] \over \partial x_{2}} = w_h \begin{bmatrix} g_x, g_y\end{bmatrix}\]

注意代码中这个变量是8维。

原文地址:https://www.cnblogs.com/JingeTU/p/8306727.html

时间: 2024-10-31 19:36:35

DSO windowed optimization 代码的相关文章

DSO windowed optimization 代码 (2)

这里写一点代码与公式的对应关系,解决 Schur Complement 更新逆深度的细节问题. \[\begin{align} \begin{bmatrix} H_{\rho\rho} & H_{\rho X} \\ H_{X\rho} & H_{XX} \end{bmatrix} \begin{bmatrix} \delta \rho \\ \delta X \end{bmatrix} &= - \begin{bmatrix} J_{\rho}^T r \\ J_X^T r \e

DSO 中的Windowed Optimization

该博客内容发表在泡泡机器人公众号上,请尊重泡泡机器人公众号的版权声明 DSO中除了完善直接法估计位姿的误差模型外(加入了仿射亮度变换,光度标定,depth优化),另一个核心就是像okvis一样使用sliding window来优化位姿,Engel也专门用了一节来介绍它.sliding window 就像c++中的队列,队首进来一个新人,队尾出去一个老人,它更像王朝中武将的新老交替,老将解甲归田,新人受window大王的重用,然而安抚老将不得当,会使得SLAM王朝土崩瓦解.对于初次接触slidin

DSO Marginalization

每当有新的关键帧产生时,都会在 FullSystem::makeKeyFrame() 函数的这里调用函数 EnergyFunctional::insertFrame() 为窗口优化添加新的关键帧,在这里将HM和bM resize,为新帧创造空间,新帧对应的位置在末尾. 有新的帧加入,就有旧的帧离开.从窗口中剔除旧的关键帧就是边缘化(marginalization)过程.边缘化过程有两步,一步是点的边缘化,一步是帧的边缘化. 整个流程在 FullSystem::makeKeyFrame() 当中,

Paper Reading: Stereo DSO

开篇第一篇就写一个paper reading吧,用markdown+vim写东西切换中英文挺麻烦的,有些就偷懒都用英文写了. Stereo DSO: Large-Scale Direct Sparse Visual Odometry with Stereo Cameras Abstract Optimization objectives: intrinsic/extrinsic parameters of all keyframes all selected pixels' depth Inte

CSDN日报20170323——《你首先是一个人,然后你才是程序员》

[程序人生]你首先是一个人,然后你才是程序员 作者:左潇龙 程序员这个职业在外面,一直被过于神化,又或者过于丑化.但其实程序员这个职业,与大多数职业一样,并没有什么特别的地方. 唯一不同的是,厨师是靠自己的厨艺吃饭,而程序员是靠自己的技术吃饭,仅此而已罢了. 作为一个厨师,如果想名扬天下,做出一番事业,光靠提高自己的厨艺肯定不行,毕竟做饭好吃的人多了去了,你又算老几? 同样的,程序员也是一样,技术牛逼的人多了去了,你又能在世界上排第几?你又能在中国排第几?你又能在你的城市排第几? 说这个,并不是

DX11学习一-初始化D3D

初始化D3D我们需要以下几步步 一.创建driver type,feature level driver type分为3种类-hardware,warp以及reference,代表GPU,CPU模拟和软件模拟,性能依次下降 feature level代表dx的等级,从11到10依次下调 按driver type以及feature level,从高到低遍历,找到合适的跳出. //Specifying the driver type and feature levels D3D_DRIVER_TYP

OD: GS Bypasing via SEH

通过 SEH 绕过 GS 保护 GS 机制没对 SEH 提供保护,所以可心通过攻击异常来绕过 GS. 实验环境为: VMware : Windows 2000 sp4, 此版本无 SafeSEH 的影响 Visual Studio 2005 Project Properties : Release, Disable Optimization 代码如下: 1 #include <string.h> 2 char shellcode[]= 3 "\xFC\x68\x6A\x0A\x38\

vins-mono的边缘化分析

##marg 基础   摘自贺一家的博客 在我们这个工科领域,它来源于概率论中的边际分布(marginal distribution).如从联合分布p(x,y)去掉y得到p(x),也就是说从一系列随机变量的分布中获得这些变量子集的概率分布.回忆了这个概率论中的概念以后,让我们转到SLAM的Bundle Adjustment上,随着时间的推移,路标特征点(landmark)和相机的位姿pose越来越多,BA的计算量随着变量的增加而增加,即使BA的H矩阵是稀疏的,也吃不消.因此,我们要限制优化变量的

错误和问题解决的成本

问题描写叙述 错误 数据收集 根本原因 版本号   组件:数据修复           在一个实际成本组织中,(平均,先进先出,后进先出) 一个或更 多的下面情况可能发生: 1.导航到物料成本历史表单上的数量信息,与现有量表单的数量不匹配的记录 2. 一些物料前期已计成本的数量与前面的事务处理历史表单的数量不匹配 3. 全部的库存值报表与事务处理值报表不匹配 4. 存货层次成本更新表单的总数量与现有量数量表单不匹配(只在先进先出/后进先出) 5.这些症状的不论什么一个意味着 MMT-CQL不匹配