相机模型与标定(九)--LM算法

本文详细介绍了Levenberg-Marquardt (LM) 算法,一种广泛应用于非线性最小二乘问题的优化方法。LM算法结合了梯度法和牛顿法的优点,通过调整参数λ实现快速收敛。适用于曲线拟合等场景。

LM算法,全称为Levenberg-Marquard,它可用于解决非线性最小二乘问题,多用于曲线拟合等场合。

LM算法的实现并不算难,它的关键是用模型函数 f 对待估参数向量p在其领域内做线性近似,忽略掉二阶以上的导数项,从而转化为线性最小二乘问题,它具有收敛速度快等优点。LM算法属于一种“信赖域法”——所谓的信赖域法,此处稍微解释一下:在最优化算法中,都是要求一个函数的极小值,每一步迭代中,都要求目标函数值是下降的,而信赖域法,顾名思义,就是从初始点开始,先假设一个可以信赖的最大位移s,然后在以当前点为中心,以s为半径的区域内,通过寻找目标函数的一个近似函数(二次的)的最优点,来求解得到真正的位移。在得到了位移之后,再计算目标函数值,如果其使目标函数值的下降满足了一定条件,那么就说明这个位移是可靠的,则继续按此规则迭代计算下去;如果其不能使目标函数值的下降满足一定的条件,则应减小信赖域的范围,再重新求解。

事实上,你从所有可以找到的资料里看到的LM算法的说明,都可以找到类似于“如果目标函数值增大,则调整某系数再继续求解;如果目标函数值减小,则调整某系数再继续求解”的迭代过程,这种过程与上面所说的信赖域法是非常相似的,所以说LM算法是一种信赖域法。

LM算法需要对每一个待估参数求偏导,所以,如果你的拟合函数 f 非常复杂,或者待估参数相当地多,那么可能不适合使用LM算法,而可以选择Powell算法——Powell算法不需要求导。

至于这个求导过程是如何实现的,我还不能给出建议,我使用过的方法是拿到函数的方程,然后手工计算出其偏导数方程,进而在函数中直接使用,这样做是最直接,求导误差也最小的方式。不过,在你不知道函数的形式之前,你当然就不能这样做了——例如,你提供给了用户在界面上输入数学函数式的机会,然后在程序中解析其输入的函数,再做后面的处理。在这种情况下,我猜是需要使用数值求导算法的,但我没有亲自试验过这样做的效率,因为一些优秀的求导算法——例如Ridders算法——在一次求导数值过程中,需要计算的函数值次数也会达到5次以上。这样的话,它当然要比手工求出导函数(只需计算一次,就可以得到导数值)效率要差得多了。不过,我个人估计(没有任何依据的,只是猜的):依赖于LM算法的高效,就算添加了一个数值求导的“拖油瓶”,整个最优化过程下来,它仍然会优于Powell等方法。对这个猜想,我会以实际代码来试验。

文章来源:http://www.codelast.com/

LM求解过程中需要用到求解线性方程组的算法,一般我们使用高斯约当消元法,因为它非常稳定——虽然它不是最快最好的算法。

对于急需自己编程用LM算法解决一些问题的朋友,如果你的数学几乎都忘了,那么你还是多请教一下自己的朋友吧,要不然连函数的偏导数都不记得怎么求了,是写不出代码的。

网上有很多LM算法的示例程序,但是如果你不理解这个算法的过程,要想看懂它们,很难。而且要对自己定义的函数使用LM算法,更加应该明白该算法的原理。

有一篇很不错的文章,解释了如何实现LM算法:http://www.ics.forth.gr/~lourakis/levmar/levmar.pdf

用Google搜索“Levenberg-Marquardt”,会有很多资料可参考。有一些现成的库也可以使用,不过,到你弄明白怎么用的时候,你都能够自己写出完整的代码了。当初我对LM也是很困惑,一直没弄清它的原理,网上的示例我怎么都用不对,后来一怒之下不再看网上的sample code,重新回到理论上,后来终于弄明白了,于是自己写出了完整的LM实现代码。

需要说明的是,这是非线性无约束的问题,如果待估参数是有约束的(例如参数在某一范围内变动),要想用在LM算法中,那就是约束最优化问题了,这是一个big topic,以我目前的知识储备,尚不能解释好,请大家另寻资料吧。

最后,不得不说的就是,LM算法并非许多人刚接触时想像的那般难,当你了解了过程之后,你就会觉得它很有意思。希望所有在学习它的朋友们都能成功。

原文:

http://www.cnblogs.com/engineerLF/p/5393110.html

一.LM最优化算法   

    最优化是寻找使得目标函数有最大或最小值的的参数向量根据求导数的方法,可分为2大类。(1)若f具有解析函数形式,知道x后求导数速度快。(2)使用数值差分来求导数。根据使用模型不同,分为非约束最优化约束最优化最小二乘最优化Levenberg-Marquardt算法是最优化算法中的一种。

   Levenberg-Marquardt算法是使用最广泛的非线性最小二乘算法(用模型函数 f 对待估参数向量p在其领域内做线性近似,利用泰勒展开,忽略掉二阶以上的导数项,优化目标方程转化为线性最小二乘问题)。它是利用梯度求最大(小)值的算法,形象的说,属于“爬山”法的一种。它同时具有梯度法牛顿法的优点。当λ很小时,步长等于牛顿法步长,当λ很大时,步长约等于梯度下降法的步长。见下图:
    
    算法从山脚开始不断迭代。可以看到,它的寻优速度是比较快的,在山腰部分直接利用梯度大幅度提升(参见后文例子程序中u较小时),快到山顶时经过几次尝试(u较大时),最后达到顶峰(最大值点),算法终止。

   LM算法属于一种“信赖域法”,所谓的信赖域法,就是从初始点开始,先假设一个可以信赖的最大位移σ,然后在以当前点为中心,以σ为半径的区域内,通过寻找目标函数的一个近似函数(二次的)的最优点,来求解得到真正的位移。在得到了位移之后,再计算目标函数值,如果其使目标函数值的下降满足了一定条件,那么就说明这个位移是可靠的,则继续按此规则迭代计算下去;如果其不能使目标函数值的下降满足一定的条件,则应减小信赖域的范围,再重新求解。
   LM算法需要对每一个待估参数求偏导,所以,如果你的拟合函数 f 非常复杂,或者待估参数相当地多,那么可能不适合使用LM算法,而可以选择Powell算法(Powell算法不需要求导。LM收敛速度块。但是参数应该设定一个初值,其次对于多优化解的问题,也不是很适合。

   英文文档lemar介绍比较简洁,还包括伪代码,请点击下载:

   我的总结如下:

      (1)Principle:An iterative tech. to locate the minimum of a multivariate function (sum of squares of non-linear real-valued function).Assuming measure vector x’=f(p) ,target vector x(such as training target in classification problem) ,error vector e=x-x’:

Optimization Object:arg(p) min(||x-f(p)||)

       Linear approximation: in the neighborhood of p, assuming Jis Jacobian Matrix(f(p) to p) ,for a smallσ,so f(p+σ)=f(p)+σJ (Taylor Expansion) ,and

min (||x-f(p+σ)||=min(||e-Jσ||)  =>  JTJσ=JTe  (derivation to σ)

       Introducing the damping term u and setN=( JTJ+uI)=> Nσ= JTe => σ

       For each iteration or updata of p(p:=p+σ),u is adjusted to assure a reduction in the error e(norm-2)

  

       (2)Merits & Defects:LM is a standard tech. fornon-linear least-squares problems:When u is set to a large value, p updates as steepest descent, otherwise updates as Gauss-Newton method.

         p shall be set toarelative reliable initial value (the work of RBM model).

LM算法,全称为Levenberg-Marquard算法,它可用于解决非线性最小二乘问题,多用于曲线拟合等场合。 LM算法的实现并不算难,它的关键是用模型函数 f 对待估参数向量 p 在其邻域内做线性近似,忽略掉二阶以上的导数项,从而转化为线性最小二乘问题,它具有收敛速度快等优点。LM算法属于一种“信赖域法”——所谓的信赖域法,此处稍微解释一下:在最优化算法中,都是要求一个函数的极小值,每一步迭代中,都要求目标函数值是下降的,而信赖域法,顾名思义,就是从初始点开始,先假设一个可以信赖的最大位移 s ,然后在以当前点为中心,以 s 为半径的区域内,通过寻找目标函数的一个近似函数(二次的)的最优点,来求解得到真正的位移。在得到了位移之后,再计算目标函数值,如果其使目标函数值的下降满足了一定条件,那么就说明这个位移是可靠的,则继续按此规则迭代计算下去;如果其不能使目标函数值的下降满足一定的条件,则应减小信赖域的范围,再重新求解。 事实上,你从所有可以找到的资料里看到的LM算法的说明,都可以找到类似于“如果目标函数值增大,则调整某系数再继续求解;如果目标函数值减小,则调整某系数再继续求解”的迭代过程,这种过程上面所说的信赖域法是非常相似的,所以说LM算法是一种信赖域法。
<think>好的,我现在要解释如何使用Levenberg-Marquardt(LM算法优化相机标定参数。首先,我需要回忆一下相机标定的基本概念和LM算法的作用。 相机标定的目的是确定相机的内参(比如焦距、主点坐标、畸变系数)和外参(比如旋转矩阵和平移向量)。通常,这通过拍摄已知的标定板(比如棋盘格)来实现,收集多个角点的图像坐标和对应的世界坐标,然后建立投影模型,通过优化算法最小化重投影误差来求解参数。 Levenberg-Marquardt算法是一种非线性最小二乘优化算法,结合了梯度下降和高斯-牛顿法的优点。在相机标定中,重投影误差通常是非线性的,因此需要LM这样的迭代算法优化参数。 接下来,我需要分步骤说明LM算法相机标定中的应用流程: 1. **建立投影模型**:首先确定相机模型,比如针孔模型加上径向和切向畸变。投影过程将3D世界点转换到2D图像坐标,涉及内参和外参。 2. **目标函数定义**:定义重投影误差作为优化的目标函数。对于每个标定板的角点,计算其投影到图像平面的坐标实测坐标的差值,平方后求和作为总误差。 3. **参数初始化**:提供相机参数的初始估计值。可能需要使用张正友标定法等方法先获取粗略的参数,作为LM算法的起点。 4. **迭代优化**:LM算法在每一步迭代中,根据当前参数计算雅可比矩阵,进而构建线性方程组,调整参数以减少误差。LM通过调节阻尼因子在梯度下降和高斯-牛顿法之间切换,确保稳定收敛。 5. **收敛判断**:当参数变化或误差下降小于阈值时,停止迭代,得到优化后的参数。 在此过程中,需要注意几点:雅可比矩阵的计算可能比较复杂,需使用数值方法或解析求导;初始值的好坏会影响收敛速度和结果;畸变模型的复杂性可能导致局部极小值,需要合理选择模型结构。 可能遇到的问题包括:参数过多导致过拟合,标定板角点数量不足,或者噪声较大的数据影响优化结果。此时需要检查数据质量,增加标定点数量,或者调整LM算法的参数如初始阻尼因子、最大迭代次数等。 总结来说,LM算法通过迭代调整相机参数,最小化重投影误差,是相机标定中常用的优化方法,兼具效率和稳定性。</think>使用Levenberg-Marquardt(LM算法优化相机标定参数的过程可分为以下步骤,其核心是通过非线性最小二乘优化最小化重投影误差: --- ### **1. 相机标定问题建模** - **投影模型**:建立3D世界点$(X_w, Y_w, Z_w)$到2D图像点$(u, v)$的映射关系: $$ \begin{aligned} s\begin{bmatrix}u \\ v \\ 1\end{bmatrix} &= \mathbf{K} \left[ \mathbf{R} \mid \mathbf{t} \right] \begin{bmatrix}X_w \\ Y_w \\ Z_w \\ 1\end{bmatrix} + \text{畸变项} \\ \mathbf{K} &= \begin{bmatrix} f_x & \gamma & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \quad (\text{内参矩阵}) \end{aligned} $$ 其中包含内参$(f_x, f_y, c_x, c_y, \gamma)$、外参$(\mathbf{R}, \mathbf{t})$及畸变参数$(k_1, k_2, p_1, p_2, k_3)$。 - **重投影误差**:对$N$个标定板角点,误差函数为: $$ E = \sum_{i=1}^{N} \left\| \boldsymbol{u}_i^{\text{观测}} - \boldsymbol{u}_i^{\text{投影}} \right\|^2 $$ --- ### **2. LM算法优化流程** - **步骤1:参数初始化** 使用张正友标定法等粗略估计初始参数$\boldsymbol{\theta}_0$(包含内参、外参和畸变参数)。 - **步骤2:计算雅可比矩阵** 计算误差函数对每个参数的偏导数,构建雅可比矩阵$\mathbf{J}$,维度为$2N \times m$($m$为参数总数)。 - **步骤3:构建增量方程** LM算法迭代公式: $$ (\mathbf{J}^T\mathbf{J} + \lambda \mathbf{I}) \Delta \boldsymbol{\theta} = \mathbf{J}^T \mathbf{e} $$ 其中$\lambda$为阻尼因子,$\mathbf{e}$为误差向量。 - **步骤4:参数更新阻尼调节** - 若误差减小,接受$\Delta \boldsymbol{\theta}$,减小$\lambda$(偏向高斯-牛顿法加速收敛)。 - 若误差增大,增大$\lambda$(偏向梯度下降法稳定搜索)。 - **步骤5:收敛判断** 当满足 $\|\Delta \boldsymbol{\theta}\| < \epsilon_1$ 或 $\Delta E < \epsilon_2$ 时终止迭代。 --- ### **3. 关键实现细节** - **雅可比矩阵计算** 使用解析法(链式法则求导)或数值差分法。例如,对焦距$f_x$的偏导: $$ \frac{\partial u}{\partial f_x} = \frac{X_c}{Z_c} \quad (\text{其中} X_c = \mathbf{R}X_w + t_x) $$ - **畸变模型处理** 包含径向畸变$(k_1, k_2, k_3)$和切向畸变$(p_1, p_2)$: $$ \begin{aligned} x_{\text{distorted}} &= x(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1 xy + p_2(r^2 + 2x^2) \\ y_{\text{distorted}} &= y(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1(r^2 + 2y^2) + 2p_2 xy \end{aligned} $$ - **鲁棒性增强** 可引入M估计(如Huber损失)抑制离群点影响。 --- ### **4. 实际应用中的注意事项** - **数据质量**:标定板需覆盖图像不同区域,角度多样,避免退化配置。 - **参数耦合**:内参(如$f_x, f_y$)和外参可能存在耦合,需足够的数据点解耦。 - **过拟合控制**:畸变参数过多时,可通过交叉验证选择合适模型阶数。 --- ### **示例代码框架(Python伪代码)** ```python import numpy as np from scipy.optimize import least_squares def project_points(world_points, K, dist_coeffs, rvecs, tvecs): # 将世界坐标投影到图像平面(含畸变) # 返回投影坐标和雅可比矩阵 def compute_residuals(params, world_points, observed_points): # 解析参数:params = [fx, fy, cx, cy, k1, k2, p1, p2, ..., rvecs, tvecs] # 计算重投影误差 # 初始参数猜测 params_init = [fx_guess, fy_guess, cx_guess, cy_guess, 0, 0, 0, 0, ...] # LM优化 result = least_squares( fun=compute_residuals, x0=params_init, method='lm', args=(world_points, observed_points) ) optimized_params = result.x ``` --- ### **总结** LM算法通过自适应调整阻尼因子,在相机标定中平衡收敛速度稳定性,有效优化非线性参数。其成功依赖于准确的初始值、合理的畸变模型设计以及高质量的标定数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值