关于Bundle Adjustment的直观理解

关于Bundle Adjustment的直观理解

前言

学习SLAM最大的一个问题就是知识点太多,学完前面又忘记后面,而且脑子总是很混乱,还经常看不懂。今天刚搞懂了Bundle Adjustment的原理,马上过来记录一下,以后忘记还可以回来看看。

本文没有公式的证明,只是通俗的理解Bundle Adjustment到底是什么,这需要读者了解一定的slam基础。
下面就让我们一步步地理解BA吧。

Bundle Adjustment译为光束法平差,或者束调整、捆集调整。我们知道,SLAM大致可以分为前端、后端、回环检测、建图这几个步骤,那BA属于这里面的哪个步骤呢?

()slam讲解)

BA的作用

让我们先来看看Bundle Adjustment的作用,BA不仅可以优化位姿(R和t),还可以优化特征点的空间位置。而我们又可以把BA看成是最小化重投影误差(Reprojection error)问题,同时这也是一个非线性最小二乘问题。说到这里,各位同学都猜到BA属于哪个步骤了吧?没错,就是属于SLAM中的后端,说白了,BA就是一个优化模型,其本质就是最小化重投影误差

投影

首先了解一下,投影是什么意思。这里所说的投影是指空间中的某个点映射到图像中的某个像素的过程。
在这里插入图片描述

特征匹配

学过SLAM的童鞋应该知道,SLAM的关键问题就是求解出机器人的运动估计,也就是位姿(可用旋转矩阵+位移,或者是变换矩阵,或者是李代数的方式表示)。在视觉SLAM中,我们要从两张图中恢复机器人的运动。在恢复运动位姿之前,我们需要对某一时刻的连续两帧进行提取特征点,特征点匹配。 特征点匹配的意思就是说 :a图像中的ua像素对应b图像中的ub像素,他们都表示空间点中的P点。
在这里插入图片描述
注意,这里的图像b是由机器人所携带的摄像头传感器所得到的真实数据,是观测出来的。表示空间点P在b图像的实际投影。

我们这里把ub的坐标设置为(ubx,uby)。

重投影

https://blog.csdn.net/bufengzj/article/details/103336170(重投影)

以单目摄像头为例子,结合多个特征匹配点,使用对极几何(E或F)或者是单应性矩阵H可以求得机器人的运动位姿。我们知道针孔相机模型如下:
在这里插入图片描述
利用针孔相机模型(观测模型),可以通过空间点P的坐标,获得空间点P投影在图像b中的像素坐标,我们称为ub`。

这个ub`像素点坐标是先通过位姿估计,再通过观测模型计算出来的,相当于这个像素坐标是估算出来的。

这个过程也称为重投影

重投影误差

如果完全没有误差,那么两者的坐标是一样的,但这是不可能的,不管是实际测量出来的ub还是通过位姿估算+重投影的出来的ub`,都是有误差的,将实际值和估算值一减,就得到了重投影误差
在这里插入图片描述

最小化重投影误差

由于两张图片有很多对特征匹配点,将所有特征点误差求和,取平方,再乘上1/2,这就构建了一个非线性最小二乘问题了,将里面的位姿、空间点作为优化的对象,最小化重投影误差,即可得到一个优化后的结果,这就是所谓的BA。
在这里插入图片描述

参考文献

《视觉SLAM十四讲》——高翔
https://www.sohu.com/a/195484669_715754
https://www.cnblogs.com/Jessica-jie/p/7739775.html

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Bundle Adjustment 是一种用于同时估计多个相机位置,姿态和三维点云的优化算法。下面是一个用Python编写的简单的Bundle Adjustment玩具程序: ```python import numpy as np import scipy.sparse as sp import scipy.sparse.linalg as splinalg # 生成测试数据 num_cameras = 3 num_points = 5 num_observations = 10 noise_scale = 0.1 # 相机的位置和姿态 camera_positions = np.random.randn(num_cameras, 3) camera_orientations = np.random.randn(num_cameras, 3) # 三维点云 points_3d = np.random.randn(num_points, 3) # 观测到的2D点 observed_points = np.zeros((num_observations, 2)) camera_indices = np.zeros(num_observations, dtype=int) point_indices = np.zeros(num_observations, dtype=int) for i in range(num_observations): camera_idx = np.random.randint(num_cameras) point_idx = np.random.randint(num_points) observed_points[i] = np.random.randn(2) + \ np.dot(camera_orientations[camera_idx], points_3d[point_idx]) + \ camera_positions[camera_idx] observed_points[i] += np.random.randn(2) * noise_scale camera_indices[i] = camera_idx point_indices[i] = point_idx # 构建稀疏矩阵 A = sp.lil_matrix((num_observations * 2, num_cameras * 6 + num_points * 3)) b = np.zeros(num_observations * 2) for i in range(num_observations): camera_idx = camera_indices[i] point_idx = point_indices[i] point_3d = points_3d[point_idx] camera_pos = camera_positions[camera_idx] camera_orient = camera_orientations[camera_idx] # 计算重投影误差 projected_point = np.dot(camera_orient, point_3d) + camera_pos projected_point /= projected_point[2] projected_point = projected_point[:2] error = observed_points[i] - projected_point # 构建雅可比矩阵 J_camera = np.hstack((point_3d, np.zeros(3), np.eye(3))) J_point = np.hstack((np.zeros(2), camera_orient[:2].reshape(2, 1) * point_3d.reshape(1, 3))) J = np.vstack((J_camera, J_point)) A[i * 2: (i+1) * 2, camera_idx * 6: (camera_idx+1) * 6] = J[:, :6] A[i * 2: (i+1) * 2, num_cameras * 6 + point_idx * 3: num_cameras * 6 + (point_idx+1) * 3] = J[:, 6:] b[i * 2: (i+1) * 2] = error # 优化 x0 = np.hstack((camera_positions.ravel(), camera_orientations.ravel(), points_3d.ravel())) res = splinalg.lsmr(A, b, x0=x0) optimized_positions = res[0][:num_cameras * 3].reshape(num_cameras, 3) optimized_orientations = res[0][num_cameras * 3: num_cameras * 6].reshape(num_cameras, 3) optimized_points_3d = res[0][num_cameras * 6:].reshape(num_points, 3) print("Original Camera Positions:\n", camera_positions) print("Original Camera Orientations:\n", camera_orientations) print("Original 3D Points:\n", points_3d) print("Optimized Camera Positions:\n", optimized_positions) print("Optimized Camera Orientations:\n", optimized_orientations) print("Optimized 3D Points:\n", optimized_points_3d) ``` 这个程序生成了一些随机的相机位置、姿态和三维点云,然后随机生成了一些观测到的2D点,并添加了一些高斯噪声。程序使用Bundle Adjustment来估计相机和3D点云的位置,并输出优化后的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值