Bundle Adjustment

最小化投影误差

可以将前面讲的线性问题转变为非线性的最小二乘问题。非线性优化是不同于线性方法的,线性方法一般是先求去相机的位姿,然后再求空间点的坐标。而非线性优化问题则是将位姿和坐标都当作变量,带入优化器优化求解。
将旋转和平移矩阵表示成李代数,假设空间点P=[X,Y,Z],像素点u=[u,v],可以得到入下的关系:
在这里插入图片描述
构建最小二乘:
在这里插入图片描述
该问题的误差为像素坐标与3D点按照当前估计的位姿进行投影得到的位置相比较得到的误差,称为 重投影误差。
在求解最小二乘的第一步时,需要知道误差项的导数:
在这里插入图片描述
将空间点向像素坐标系投影,先将空间点转变到相机坐标系下:
在这里插入图片描述
然后与相机内参,将相机坐标系的内的点投影到像素坐标系:
在这里插入图片描述

误差项e是u-su,可以知道u的坐标点(u1,v1)为像素坐标为常数。
而su是未知数,是包含李代数的空间坐标表达式。
优化位姿的误差项求导:
这里的求导为左乘扰动,第一项的导数为:
第二项的导数为:
两项的相乘们就是误差项的导数,这样就可以得到一个雅可比矩阵:

在求解位姿的优化后,还需要对空间点P进行优化,可以计算e关于P的导数:
于是可以得到:
而P’对P的导数可以表示成下式:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值