当前位置: 首页 > 编程日记 > 正文

SLAM笔记(五)光束平差法(Bundle Adjustment)

1.什么是光束平差法

前边的八点法,五点法等可以求出闭式解的前提是已经知道确切的点对。但实际情况中往往存在大量的噪声,点与点不是精确地对应甚至出现一些错误匹配。 
光束平差法由Bundle Adjustment翻译得来,有两层意思: 
对场景中任意三维点P,由从每个视图所对应的的摄像机的光心发射出来并经过图像中P对应的像素后的光线,都将交于P这一点,对于所有三维点,则形成相当多的光束(bundle);实际过程中由于噪声等存在,每条光线几乎不可能汇聚与一点,因此在求解过程中,需要不断对待求信息进行调整(adjustment),来使得最终光线能交于点P。对m帧,每帧含N个特征点的目标函数如下: 
这里写图片描述 
(1) 
其中:表示受白噪声影响的估计二维点坐标,为投影函数,ruguo 如果点j出现在图i上,则,否则。 
这是一个非凸问题。 
式子(1)表示对所有点 
以上便是光束平差法目标函数的原理。由于场景中特征点往往较多,该问题是一个巨大的高维非线性优化问题。接下来,需要对上述式子进行求解,这是光束平差法的核心内容。 
针对具体应用场景,光束平差法有不同收敛方法。目前常用的方法有梯度下降法,牛顿法,高斯牛顿法,Levenber-Marquardt等方法。

2.1 一阶方法——梯度下降法

所谓一阶方法,即对问题的目标函数进行泰勒一阶展开后进行迭代求解的方法。梯度下降法是一阶方法之一。当梯度为负值时,沿着梯度方向就是函数值f变小最快的方向。梯度下降法就是让函数沿着下降最快的方向去找函数值的最小值,就像水流沿着斜率最大的方向流去。对于变量都为标量的函数,形象的描述是始终用一条直线来拟合曲线。梯度下降法迭代式子如下:

(2)

其中,ϵ表示自己设置的迭代步长,可用一维线性搜索动态确定。x表示自变量。

严格意义上,梯度下降法并不决定函数f(x)下降方向,因为它仅仅是一个余向量而非向量,只能通过最终标量的正负而非实际的向量指引函数下降方向。梯度下降法的复杂度是Ο(n),其中n为待解决问题的大小,比如矩阵E的行数。实际过程中,常常使用一维线性搜索方法来寻找合适的步长。

2.2 二阶方法——牛顿法(Newton Method)

牛顿法是二阶优化方法,即会将目标函数展开至泰勒二阶项然后进行优化求解。与梯度法相比,它们利用到了目标函数的二阶导数。形象地讲,如用牛顿法求解自变量为标量的函数时,用二次曲线来拟合最优化点时的函数曲线。

对目标函数E,其二阶泰特展开式为:

其中g为E的雅克比矩阵,H为E的海塞矩阵。

由于优化点的导数为0,即:

上式展开,易知x的迭代式子为:

由于牛顿法下降速度很快。实际中往往加上一个步长因子γϵ(0,1),来控制收敛的速度:

牛顿法是二阶收敛的,收敛速度很快。在实际应用中,向量x往往非常大(每个视图中图像处理后特征点数量可能达到万个以上),海森矩阵H将非常大,求海塞矩阵的逆的运算消耗将非常大,对于牛顿法来说,计算复杂度是O(n3)。此外,由于海塞矩阵不一定可逆。其三,对于大多数一阶优化方法,可以采用诸如图形处理器(Graphics Processing Unit)并行的方式来加速,但对于海塞矩阵求逆来说这显然无法实现。因此实际中往往出现一阶方法比二阶方法更快收敛。

2.3 拟牛顿法——高斯牛顿法(Gauss-Newton Method)

所谓拟牛顿法,就是用其他式子来模拟替代海塞矩阵。假如牛顿法中的海塞矩阵不是正定(positive definitive)的,无法求解;此外,海森矩阵H往往非常大,求海塞矩阵的逆的运算消耗也很大(对于牛顿法来说,计算复杂度是O(n3)),因此,引入用拟牛顿法来用正定矩阵代替海塞矩阵和海塞矩阵的逆。常用的拟牛顿法有高斯牛顿法(Gauss-Newton Method)。

假设最小二乘问题目标函数如下:

其中ri(x)是对应观测值与预测值之间的残差。

仿照2.3可以得到牛顿法中的迭代式子(10)。不过其中梯度矩阵g:

海塞矩阵H:

如果对于一个近线性的优化问题,则上式第二项更趋近于0,因此舍弃第二项,上式为:

则:

也即有:

由于采用 ,计算量大大减少

应当特别指出,上式成立的条件是。在结构与运动过程中,由于一般认为到场景位置点的距离比较远的,因此短暂的移动过程中,可以认为从摄像机到场景位置点的距离是近似不变的。在距离不变,也就是一个维度固定的前提下,投影函数π是线性的。因此该近似符合应用场景,是很好的近似。

2.4 Levenberg-Marquardt方法

另外一种思路是将牛顿法和梯度法融合在一起。数学上是阻尼最小二乘法的思路,即近似只有在区间内才可靠。对于

此处μ是信赖区间半径,D为对∆进行转换的矩阵(在Levenberg的方法中,他将D设置为单位矩阵)。

即加上一个单位矩阵I的倍数和使之成为:

这种方法时保证改进后的海塞矩阵可逆且正定。从效果上,是用λ在牛顿法与梯度法之间做出权衡。当λ很小时,上式几乎等同与牛顿法式子,当λ很大时,上式等同于梯度下降法的式子。

后来,Levenberg(1944)对此方法进行了改进。他将H替换成高斯牛顿法中的拟合矩阵:

其中: (15)

但容易出现的问题是,当 很小的时候,λI可能很大。这样会极大地偏向梯度法,降低收敛速度。因此为了提高收敛速度,Marquardt 提出了一种新的自适应方法:它的迭代式子中:

因此当很小时,该方法也不会特别偏向梯度法。

在L-M方法中,采用了近似程度描述ρ

即ρ=实际下降/近似下降。当ρ太大,则减少近似范围(增大λ),当p太大,则增加近似范围(减少λ)。

因此最常使用的光束平差法模型, L-M算法计算步骤如下:

a)给定初始值; 
b)对第k次迭代,求解 
c)计算ρ 
d)若ρ>0.75(经验值),则μ=2μ(经验值,实际可视作变化迭代步长); 
若ρ<0.25(经验值),则μ=0.5μ(经验值); 
e)如果ρ大于某阈值,则该次近似是可行的,回到b)继续迭代;否则算法已经收敛,迭代结束。

2.5与高斯牛顿法相比LM算法的优缺点

高斯牛顿法的缺点是:

  • 可能是奇异的病态的,无法保证求解的增量的稳定性;
  • 步长可能很大从而导致无法满足高斯牛顿的一阶能大致拟合的假设 
    优点:
  • 下降速度比LM快

LM是信赖区域优化法的代表,而加上步长的高斯牛顿法是线搜索方法的代表。

3 关于光束平差法的其他问题

(1)初始值

光束平差法需要比较好的初始值才能比较快地收敛,所以光束平差法一般作为重建流水线的最后一个步骤,在此之前,需要使用多视图几何中传统的八点法,五点法等传统多视图几何算法先算出R,T等信息。

(2)步长控制

引入步长控制,既可以是避免收敛时步长太大而在最优点附近震荡,也可以加快收敛速度。加入迭代步长的原因,是因为 牛顿法中 下降方向 可能和真实下降方向不一致* 。*比如可能会出现几个最优点相邻比较近的情况,那么优化过程将在几个谷底之间跳来跳去迟迟不收敛。为了避免这种情况,增加收敛速率,加入一个迭代步长γ,来使迭代朝着真实下降方向走。如果在鞍点,在沿着海塞矩阵为负的方向迭代。实际应用中,可以采用每一次迭代后,再对γ进行一维搜索的方法来寻找合适步长。也可以采用L-M的方法,通过改变信任区间的方式,来进行步长控制。 
4.常用优化库: 
常用BA库: 
sba: A Generic Sparse Bundle Adjustment C/C++

Apero/MicMac, a free open source photogrammetric software. Cecill-B licence.

Package Based on the Levenberg–Marquardt Algorithm (C, MATLAB). GPL.

cvsba: An OpenCV wrapper for sba library (C++). GPL.

ssba: Simple Sparse Bundle Adjustment package based on the Levenberg–Marquardt Algorithm (C++). LGPL.

OpenCV: Computer Vision library in the contrib module. BSD license.

mcba: Multi-Core Bundle Adjustment (CPU/GPU). GPL3.

libdogleg: General-purpose sparse non-linear least squares solver,based on Powell’s dogleg method. LGPL. 
ceres-solver: A Nonlinear Least Squares Minimizer. BSD license. 
g2o: General Graph Optimization (C++) - framework with solvers for sparse graph-based non-linear error functions. LGPL.

DGAP: The program DGAP implement the photogrammetric method of bundle adjustment invented by Helmut Schmid and Duane Brown. GPL. 
工程上常用的是g2o和ceres-solver。此上列表来源不可考,如有侵权请联系我以删除。

相关文章:

【Code forces】63B Settlers' Training

http://codeforces.com/problemset/problem/63/B 给你一串数字&#xff0c;直到所有数字都变为k为止&#xff0c;相同的数为一组&#xff0c;在一次中&#xff0c;所有不同的数都加1 1 2 2 3 → 2 2 3 4 → 2 3 4 4 → 3 4 4 4 → 4 4 4 4 #include <ios…

[elixir! #0007] [译] 理解Elixir中的宏——part.5 重塑AST by Saša Jurić

上一章我们提出了一个基本版的deftraceable宏&#xff0c;能让我们编写可跟踪的函数。宏的最终版本有一些剩余的问题&#xff0c;今天我们将解决其中的一个——参数模式匹配。 今天的练习表明我们必须仔细考虑宏可能接收到的输入。 问题 正如我上一次暗示的那样&#xff0c;当前…

vue-cli3环境变量与分环境打包

第一步 : 了解环境变量概念 我们可以根目录中的下列文件来指定环境变量: .env # 在所有的环境中被载入 .env.local # 在所有的环境中被载入&#xff0c;但会被 git 忽略 .env.[mode] # 只在指定的模式中被载入 .env.[mode].local # 只在指定…

SLAM闭合回环————视觉词典BOW小结

在目前实际的视觉SLAM中&#xff0c;闭环检测多采用DBOW2模型https://github.com/dorian3d/DBoW2&#xff0c;而bag of words 又运用了数据挖掘的K-means聚类算法&#xff0c;笔者只通过bag of words 模型用在图像处理中进行形象讲解&#xff0c;并没有涉及太多对SLAM的闭环检测…

【Codeforces】53D Physical Education (有点像冒泡)

http://codeforces.com/problemset/problem/53/D 从上面所给的序列变成下面所给的序列 交换的时候只能交换相邻的两个数字 输出每一步的交换方法&#xff0c;输出的是该元素在序列中的位置&#xff08;第一个数的位置是1&#xff09; 不要求输出步数最少的那一种方法 当同…

js脚本冷知识

js中有个很恶心的写法。比如这个var adsf(function(){})();这样的写法&#xff0c;主要是原生的&#xff0c;能在dom元素加载完之后实现自动加载这个脚本文件到里面去。可以验证这个&#xff08;function(){.......&#xff09;&#xff08;&#xff09;;在.......里面可以直接…

Python中is同一性运算符和==相等运算符区别

2019独角兽企业重金招聘Python工程师标准>>> 在区分is和这两种运算符区别之前&#xff0c;需要知道Python中对象包含的三个基本要素&#xff0c;分别是&#xff1a;id(身份标识)、type(数据类型)和value(值)。 比较对象的value(值) 是python标准操作符中的比较操作符…

C++实现十大排序算法(冒泡,选择,插入,归并,快速,堆,希尔,桶,计数,基数)排序算法时间复杂度、空间复杂度、稳定性比较(面试经验总结)

排序算法分类 内部排序算法又分为基于比较的排序算法和不基于比较的排序算法&#xff0c;其分类如下&#xff1a; 比较排序&#xff1a; 直接插入排序 希尔排序 &#xff08;插入&#xff09; 冒泡排序 快速排序 (交换) 直接选择排序 堆排序&#xff08;选择&#…

32位处理器是什么意思

问题描述&#xff1a;朋友那个32位处理器&#xff0c;2的32次方算出来的单位是不是应该是4294967296位&#xff08;bit&#xff09;吧&#xff0c;怎么就成字节了呢&#xff1f;单位错了&#xff0c;那个32位是指32位地址总线&#xff0c;而不是32位数据。地址的数量单位是个&a…

【Codeforces】913C Party Lemonade (贪...)。

http://codeforces.com/contest/913/problem/C 这个题和以前见过的有点不一样&#xff0c;可以重复选择&#xff0c;这个有点emmm 首先将a数组优化&#xff0c;举个例子&#xff0c;如果1L20元&#xff0c;2L50元&#xff0c;那么将a[1]赋值为40&#xff0c;而不是50。 之后…

GDB 调试 Mysql 实战(二)GDB 调试打印

背景 在 https://mengkang.net/1328.html 实验中&#xff0c;我们通过optimizer_trace发现group by会使用intermediate_tmp_table&#xff0c;而且里面的的row_length是20&#xff0c;抱着"打破砂锅问到底"的求学精神&#xff0c;所以想通过 gdb 调试源码的方式看这个…

移动端AR的适用分析(二)

移动端AR的适用分析&#xff08;二&#xff09;1. 单目SLAM难点 2. 视觉SLAM难点 3. 可能的解决思路 单目slam的障碍来自于理论和实践两个方面。理论障碍可以看做是固有的&#xff0c;无法通过硬件选型或软件算法来解决的&#xff0c;例如单目初始化和尺度问题。实践问题包括计…

新的理念、 新的解决方案、 新的Azure Stack技术预览

Jeffrey Snover 我们很高兴地宣布︰ Azure Stack Technical Preview 2&#xff08;TP2&#xff09;已发布&#xff01;我们朝着向您的数据中心提供Azure服务能力的目标又更近一步。自发布第一个技术预览版&#xff08;TP1&#xff09;以来&#xff0c;我们访问了很多用户&…

【HDU】1084 What Is Your Grade? (结构体 sort)

http://acm.hdu.edu.cn/showproblem.php?pid1084 题目的关键&#xff1a; 1、Note, only 1 student will get the score 95 when 3 students have solved 4 problems. If you can solve 4 problems, you can also get a high score 95 or 90 (you can get the former(前者)…

FastDFS之Linux下搭建

1.软件环境 CentOS6.5 FastDFS v5.05 libfastcommon- - master.zip&#xff08;是从 FastDFS 和 FastDHT 中提取出来的公共 C 函数库&#xff09; fastdfs- - nginx- - module_v1.16.tar.gz nginx- - 1.6.2.tar.gz fastdfs_client_java._v1.25.tar.gz 2.FastDFS集群规划 描述 …

Linux进程与线程的区别 详细总结(面试经验总结)

首先&#xff0c;简要了解一下进程和线程。对于操作系统而言&#xff0c;进程是核心之核心&#xff0c;整个现代操作系统的根本&#xff0c;就是以进程为单位在执行任务。系统的管理架构也是基于进程层面的。在按下电源键之后&#xff0c;计算机就开始了复杂的启动过程&#xf…

【HDU/POJ/ZOJ】Calling Extraterrestrial Intelligence Again (素数打表模板)

http://poj.org/problem?id1411 POJ http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode1689 ZOJ http://acm.hdu.edu.cn/showproblem.php?pid1239 HDU 都是同一个题&#xff0c;但是可能你在HDU上AC&#xff0c;在POJ和ZOJ上是TLE&#xff08;所以还有待…

[AVR]使用AVR单片机驱动舵机

最近参加了三系举办的小车比赛(好像叫什么"驭远杯")。领导要求我驱动3-4个舵机。研究了几日&#xff0c;总算折腾出一个方案..、 1.舵机驱动的基本原理 &#xff08;可以参考http://blog.sina.com.cn/s/blog_8240cbef01018hu1.html&#xff09; "控制信号由接收…

高阶函数的使用

问题 字节跳动面试时问题&#xff1a;原函数例如fetchData是一个异步函数&#xff0c;尝试从服务器端获取一些信息并返回一个Promise。写一个新的函数可以自动重试一定次数&#xff0c;并且在使用上和原函数没有区别。 思路 这个问题其实不是很难&#xff0c;不过可能是太菜了紧…

内存溢出和内存泄漏的定义,产生原因以及解决方法(面试经验总结)

一、定义&#xff08;概念与区别&#xff09; 内存溢出 out of memory&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现out of memory&#xff1b;比如申请 了一个integer,但给它存了long才能存下的数&#xff0c;那就是内存溢出。 …

【Codeforces】716B Complete the Word (26个字母)

http://codeforces.com/contest/716/problem/B 给你一个字符串该字符串中是否存在长度为26且这26个字母没有重复 一个满足上述条件但是部分区域是问号的话&#xff0c;需要用剩下的字母覆盖掉问号&#xff0c;其余部分的问号可以随便赋值 没有的话输出-1 暴力即可。 #incl…

MySQL ERROR 1878 解决办法

MySQL ERROR 1878报错解决办法错误重现Part1:大表修改字段mysql> ALTER TABLE erp-> ADD COLUMN eas_status tinyint(3) unsigned NOT NULL DEFAULT 0 AFTER totalprice;ERROR 1878 (HY000): Temporary file write failure.mysql> \q这里可以看到&#xff0c;添加字…

共享程序集和强命名程序集(3):强命名程序集的一些作用

强命名程序集能防篡改 用私钥对程序集进行签名&#xff0c;并将公钥和签名嵌入程序集&#xff0c;CLR就可以炎症程序集未被修改或破坏。程序集安装到GAC时&#xff0c;系统对包含清单的那个文件的内容进行哈希处理&#xff0c;将Hash值与PE文件中嵌入的RSA数字签名进行比较。如…

堆和栈的区别(面试经验总结)

C中&#xff0c;内存分为5个区&#xff1a;堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈&#xff1a;是由编译器在需要时自动分配&#xff0c;不需要时自动清除的变量存储区。通常存放局部变量、函数参数等。 堆&#xff1a;是由new分配的内存块&#xff0c;由程序员…

百度Q3财报里的“大生意”

在今日发布的Q3财报中&#xff0c;百度花了不少篇幅来介绍人工智能业务的进展&#xff0c;作为百度的技术核心&#xff0c;近段时间几乎所有百度业务都在与人工智能做深入结合&#xff0c;这预示着移动互联网信息化技术发展已经全面开启人工智能时代&#xff0c;而百度势必要在…

【Codeforces/HDU】76A Plus and xor / 2095 find your present (2)(异或)。

http://codeforces.com/contest/76/problem/D A X Y B X xor Y 异或&#xff08;不进位加法&#xff09;&#xff1a;两个二进制数&#xff0c;对应的位置上&#xff0c;相同为0&#xff0c;不同为1 性质&#xff1a;a^a0&#xff0c;a^0a&#xff0c;满足交换律 所以…

前端项目如何管理

前端项目如何管理 前端项目的管理分为两个维度&#xff1a;项目内的管理与多项目之间的管理。 1. 项目内的管理 在一个项目内&#xff0c;当有多个开发者一起协作开发时&#xff0c;或者功能越来越多、项目越来越庞大时&#xff0c;保证项目井然有序的进行是相当重要的。 一般会…

CMake学习(一)

什么是 CMake 你或许听过好几种 Make 工具&#xff0c;例如 GNU Make &#xff0c;QT 的 qmake &#xff0c;微软的 MS nmake&#xff0c;BSD Make&#xff08;pmake&#xff09;&#xff0c;Makepp&#xff0c;等等。这些 Make 工具遵循着不同的规范和标准&#xff0c;所执行…

【Codeforces】1104C Grid game (变异的俄罗斯方块)

http://codeforces.com/problemset/problem/1104/C 4 X 4 的方格 放置 1*2的矩形&#xff08;用1表示&#xff09;和2*1的矩形&#xff08;用0表示&#xff09; 只要有一行或者一列都填满了&#xff0c;就会自动消除&#xff0c;就可以放心的矩形了&#xff0c;只要不重叠就可…

如何创建.gitignore文件,忽略git不必要提交的文件

1、在需要创建 .gitignore 文件的文件夹, 右键选择Git Bash 进入命令行&#xff0c;进入项目所在目录。 2、输入 touch .gitignore &#xff0c;生成“.gitignore”文件。 3、在”.gitignore” 文件里输入你要忽略的文件夹及其文件就可以了。&#xff08;注意格式&#xff09; …