【Ceres】Ceres学习笔记2 BA相关

本文介绍了Bundle Adjustment问题的优化过程,使用Ceres库进行非线性最小二乘求解。首先,详细阐述了如何从数据集中读取相机参数、3D点坐标和观测的2D点信息。接着,解析了SnavelyReprojectionError结构,用于计算重投影误差。最后,展示了如何构建Ceres问题并调用求解器进行优化。整个过程涵盖了数据处理、误差模型和数值求解的关键步骤。

7. Bundle Adjustment

​ 给定一组测量的图像特征位置和对应关系,Bundle Adjustment 的目标是找到最小化重投影误差的 3D 点位置和相机参数。 该优化问题通常被表述为非线性最小二乘问题,其中误差是观察到的特征位置与相机图像平面上相应 3D 点的投影之间的差异的平方范数。 Ceres 为解决 Bundle Adjustment 问题提供了广泛的支持。

​ BAL 问题中的每个残差都取决于一个三维点和一个九参数相机。 定义相机的九个参数是:三个用于作为罗德里格斯轴角矢量的旋转,三个用于平移,一个用于焦距,两个用于径向畸变。 此相机型号的详细信息可以在 Bundler 主页BAL 主页中找到。

1)读取数据

​ 拿到一个数据集,首先要了解其含义,即每个数据所代表的意义。然后根据其不同的意义分类,思考如何通过代码的方式如何读入数据。

​ 第二次记录:

​ 已经了解到,数据集分为三部分,1 header 相关的个数数据 2 某个相机观察到的3D点以及对应的2D观察点的数据 3 相机参数(9个)以及3D点的坐标

(1)读入第一部分的个数

​ 1 相机个数:int num_cameras_;

​ 2 所观测的现实世界的位置,即3D点数量:int num_points_;

​ 3 观测的2D点的数量:int num_observations_;

​ 以上可以通过通过数据集的第一行得到。

int num_observations() const {
   
    return num_observations_; }
FscanfOrDie(fptr, "%d", &num_cameras_);
FscanfOrDie(fptr, "%d", &num_points_);
FscanfOrDie(fptr, "%d", &num_observations_);

(2)每个相机观察到的3D点的索引以及其对应的2D点的两个坐标(第二部分)

​ 思考:只能按行读取数据,一次读取一行中的一个数据,其中一个隐含的条件是第二部分的行数与观测到的2D坐标点的个数相同,所以比较有用的便是 num_observations_ ,其描述了循环读取数据的次数。

​ 每一行中第一个数据表示第几个相机,第二个数据表示观测到的第几个3D点,那么由于 “第几个”,所以定义索引:

    int* point_index_;
    int* camera_index_;

​ 第几个观察到的2D点:double* observations_;

    point_index_ = new int[num_observations_];
    camera_index_ = new int[num_observations_];
    observations_ = new double[2 * num_observations_];
point_index_ = new int[num_observations_];
camera_index_ = new int[num_observations_];
observations_ = new double[2 * num_observations_];
num_parameters_ = 9 * num_cameras_ + 3 * num_points_;
parameters_ = new double[num_parameters_];
for (int i = 0; i < num_observations_; ++i) {
   
   
	FscanfOrDie(fptr, "%d", camera_index_ + i);
    FscanfOrDie(fptr, "%d", point_index_ + i);
    for (int j = 0; j < 2; ++j) {
   
   
    	FscanfOrDie(fptr, "%lf", observations_ + 2 * i + j);
    }
}

(3)每个相机的参数以及3D点的坐标(第三部分)

​ 如何读入这部分的数据?
​ 1 首先确定这一部分总共有多少数据:int num_parameters_;

num_parameters_ = 9 * num_cameras_ + 3 * num_points_;

​ 2 通过 “第几个“确定位置

double* parameters_;

​ 3 首先将读取到的参数看作整体,然后再分配:

for (int i = 0; i < num_parameters_; ++i) {
   
   
	FscanfOrDie(fptr, "%lf", parameters_ + i);
	}
double* mutable_cameras() {
   
    return parameters_; }                   //相机参数首地址
double* mutable_points() {
   
    return parameters_ + 9 * num_cameras_; } //3D点的首地址
double* mutable_camera_for_observation(int i) {
   
                        //返回第i个相机
	return mutable_cameras(<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值