使用Levenberg Marquardt算法进行的Homography计算

时间:2012-12-27 06:22:45

标签: c++ image statistics computer-vision homography

OpenCV中的findHomography()函数找到两个平面之间的透视变换。使用Levenberg-Marquardt方法进一步细化计算单应矩阵(仅在鲁棒方法的情况下使用内点)以减少重新投影误差更多。任何人都可以向Levenberg Marquardt算法提供任何C / C ++代码链接,这是最小化误差函数所必需的,因为它将帮助我理解算法背后的数学。 (网络中的任何地方,只上传了库或特定代码,但没有上传算法的详细代码)。

2 个答案:

答案 0 :(得分:3)

我知道它不是C / C ++,但Matlab文件交换上的文件可能有源代码可以帮助你:

http://www.mathworks.com/matlabcentral/fileexchange/16063

如果您了解C / C ++,您可能对理解Matlab没有任何问题,特别是如果您正在查看源代码以便进一步理解。

答案 1 :(得分:3)

openCV代码已打开,因此请检查模块。 openCV的cheatsheet有Levenberg Marquardt公式,见第3页第1栏。您可以使用grep搜索该cheatsheet公式或仅使用方法名称:

grep -rnw . -e "Levenberg"

例如,您可以在modules / legacy文件夹中发现许多levmar * .c文件。在使用RANSAC求解线性方程组之后使用LMA的原因是因为前面的线性方程优化了错误的度量 - 在Homography参数中的代数误差。更好的度量是以点坐标表示的残差平方和。在此度量标准中,解决方案是非线性的,必须迭代地找到。线性解决方案用于初始化非线性算法,并增加其收敛到全局最小值的机会。

然而,查看代码并不总是理解复杂概念的最简单方法。这是一个'进化''排列优化算法,希望可以帮助您理解:

  1. 优化始终可以作为成本或残差的最小化
  2. 如果函数凸(碗形)它只有一个全局最小值,可以通过向下滑动找到它。由于渐变点向上,我们用减号:

    param [t + 1] = param [t] -k * cost' ,其中t-iteration,k-step和'代表梯度或衍生物w.r.t.参数

  3. 到目前为止一直很好,但在某些情况下(想象一个看起来像滑雪板管的成本函数)沿着渐变会让你从山谷的一边到另一边过冲和曲折,而只是慢慢走向下(到全球最小)。解决方案 - 使用更好的函数逼近(泰勒扩展到二阶导数)来得到这个

    param [t + 1] =参数[t] - (k /费用'')*费用' ,其中''是二阶导数

  4. 直观快速的函数意味着大的二阶导数,因此我们通过减少步数(将其除以大数量)来减慢收敛,反之亦然。
    4.对于通常表示残差平方或某些距离之和的二次误差,我们可以得出二阶导数的近似值作为一阶导数的乘积(称为Jacobians,显示为J,通常是矩阵);二阶导数或Hessian = J T J,所以优化看起来像

    param [t + 1] = param [t] - (J T J) -1 * cost' - 被调用高斯 - 牛顿

    在这里,为了简单起见,我们放弃了k;比较这个和以前的公式,我们差不多了!另请注意,在维基百科和其他网站中,您可能会看到使用残差yi-f(x,param)而不是k,但您现在也可以忽略它。只有在您对最后一种配方感到满意时才更进一步 莱文伯格来了,他说 - 这很棒,但可能不稳定。我们对这些二阶导数假设太多了,抛弃它们并使事物看起来像以前一样衍生出来会很好。为此,我们添加一个可以使优化看起来像

    的转储因子

    param [t + 1] = param [t] - (J T J + lambda * I) -1 * cost' ,其中我是单位矩阵,lambda是标量

    请注意,当lambda很大时,您可以丢弃J T J并保留标准梯度下降。当收敛速度减慢时,他们会这样做,另外他们使用小lambda,这使得算法看起来更像Gauss-Newton。请注意,J = d_z / d_param,cost'= d_f / d_param和f = z T * z

    Marquardt说道,但是我很喜欢我们的渐变下降速度更快 - 对于小对角线(J T J)我喜欢更大的步伐,因此我们选择了最终的公式通过小的对角线元素,当梯度缓慢时导致更快的收敛:

    param [t + 1] = param [t] - (J T J + lambda *对角线(J T J)) - 1 *费用'

    以下是使用下坡滑雪类比的快速总结,其中我们显示参数更改参数[t + 1] -param [t]的表达式:
    1.渐变J指向,但你想滑雪,所以反对渐变-kJ;
    2.如果在雪管中蜿蜒曲折。与二阶导数(H)相反的步骤;你希望你能直接走得更快:-H -1 J
    3.用一阶导数的乘积逼近二阶导数 - (J T J) -1 J;
    4.如果它过多则倾倒它并返回到一阶导数 - (J T J + lambda I) -1 J;
    5.不想被困在平坦的斜坡上?将你的步骤与近似Hessian的对角线成反比: - (J T J + lambda
    diag(J T J)) -1 J

    由于我的直觉在一段时间之后就放弃了,所以这些都有效,这是一个很大的谜。也许现在是时候从哲学上看这个并运用奥卡姆剃刀的原则 - 我们假设我们越好越好但是假设太少我们可能不会走得太远。我们所做的就是预测(假设)在本地查看它的函数的全局行为(成像在一起一周后结婚)。使用Hessian就像在其众多参数方面有更多的假设,而不是具有一些参数(假设)的更保守的雅可比。最后,我们可能想要保守或风险灵活,以及Levenberg-Marquardt方法试图实现的目标。