Ceres 中的线性求解器类型(linear_solver_type)

Ceres Solver中的线性求解器类型(linear_solver_type)有多个选项,包括:

DENSE_QR:使用稠密QR分解方法求解线性方程组。适用于内存足够的小规模问题,求解速度较快。

DENSE_SCHUR:使用Schur补方法进行求解。适用于大规模问题,但内存消耗较大。

SPARSE_NORMAL_CHOLESKY:使用稀疏Cholesky分解方法求解正规方程。适用于具有稀疏结构的问题,例如SLAM问题,但求解速度较慢。

SPARSE_SCHUR:使用Schur补方法进行求解,其中Hessian矩阵的块对角线部分使用稀疏Cholesky分解方法,而其他部分使用稠密QR分解方法。适用于具有稀疏结构的大规模问题。

CGNR:共轭梯度法(Conjugate Gradient Normal Residual)。适用于具有稀疏结构的问题,但求解速度较慢。

DENSE_NORMAL_CHOLESKY:使用稠密Cholesky分解方法求解正规方程。适用于内存足够的小规模问题。

不同的线性求解器适用于不同类型的问题和数据结构,应根据问题的特点选择合适的线性求解器。如果不确定使用哪种线性求解器,可以尝试多个线性求解器并比较其性能。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ceres Solver 是一个用于非线性最小二乘问题的开源C++库。要使用 Ceres Solver 求解二维变换矩阵,需要定义一个误差函数,并用 Ceres Solver 最小化这个误差函数。 假设我们有一组原始点 $(x_i, y_i)$ 和目标点 $(u_i, v_i)$,要求一个二维变换矩阵 $H$,使得原始点通过 $H$ 变换后的坐标 $(x'_i, y'_i)$ 尽可能接近目标点 $(u_i, v_i)$。可以定义一个误差函数为: $$ E(H) = \sum_{i=1}^n \left\| \begin{bmatrix} u_i \\ v_i \\ 1 \end{bmatrix} - H \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix} \right\|^2 $$ 其 $\left\| \cdot \right\|$ 表示向量的欧几里得范数。接下来,使用 Ceres Solver 最小化这个误差函数。Ceres Solver 需要提供一个初始的变换矩阵 $H_0$,可以使用单位矩阵作为初始值。 下面是一个使用 Ceres Solver 求解二维变换矩阵的例子: ```c++ #include <ceres/ceres.h> #include <ceres/rotation.h> struct TransformCostFunctor { TransformCostFunctor(double u, double v, double x, double y) : u(u), v(v), x(x), y(y) {} template <typename T> bool operator()(const T* const h, T* residual) const { T x_transformed = h[0] * T(x) + h[1] * T(y) + h[2]; T y_transformed = h[3] * T(x) + h[4] * T(y) + h[5]; T w_transformed = h[6] * T(x) + h[7] * T(y) + h[8]; // 将齐次坐标转换为非齐次坐标 x_transformed /= w_transformed; y_transformed /= w_transformed; // 计算残差 residual[0] = T(u) - x_transformed; residual[1] = T(v) - y_transformed; return true; } const double u, v, x, y; }; int main() { std::vector<double> x = { 1, 2, 3, 4 }; std::vector<double> y = { 1, 3, 4, 2 }; std::vector<double> u = { 2, 4, 6, 8 }; std::vector<double> v = { 2, 6, 8, 4 }; double h[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; // 初始变换矩阵 ceres::Problem problem; for (int i = 0; i < x.size(); i++) { ceres::CostFunction* cost_function = new ceres::AutoDiffCostFunction<TransformCostFunctor, 2, 9>( new TransformCostFunctor(u[i], v[i], x[i], y[i])); problem.AddResidualBlock(cost_function, nullptr, h); } ceres::Solver::Options options; options.max_num_iterations = 1000; options.linear_solver_type = ceres::DENSE_QR; options.minimizer_progress_to_stdout = true; ceres::Solver::Summary summary; ceres::Solve(options, &problem, &summary); std::cout << summary.FullReport() << std::endl; std::cout << "Final transformation matrix: " << std::endl; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { std::cout << h[i * 3 + j] << " "; } std::cout << std::endl; } return 0; } ``` 在上面的代码,我们定义了一个 `TransformCostFunctor` 类,用来计算每个点的误差。这个类重载了 `()` 运算符,接受一个变换矩阵 $H$ 和一个原始点 $(x_i, y_i)$,并计算变换后的坐标 $(x'_i, y'_i)$。然后,将变换后的坐标 $(x'_i, y'_i)$ 和目标点 $(u_i, v_i)$ 的差作为残差返回。 在 `main()` 函数,我们首先定义了原始点和目标点的坐标。然后,定义了一个初始变换矩阵 `h`。接下来,使用 Ceres Solver 将每个点的误差加入到问题,并设置求解的参数。最后调用 `ceres::Solve()` 函数求解变换矩阵,并输出求解结果。 注意,这个例子使用的是自动微分(AutoDiff),因此需要在 `ceres::AutoDiffCostFunction` 指定 `TransformCostFunctor` 类的模板参数。如果你想使用其他的求导方法,可以使用 `ceres::NumericDiffCostFunction` 或自己实现 `ceres::CostFunction` 类。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值