问题标签 [ceres-solver]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
212 浏览

c++ - Ceres-Solver:残差函子使用的可变变量是好习惯吗?还有什么其他选择?

据我了解, 的接口Ceres要求将每个残差定义为一个函子,其中operator()是一个const 成员函数。这是我感兴趣的一个例子:

现在,我在一个特殊情况下需要“帮助”矩阵m_M,我想在里面使用它operator()。有几个选项,例如,我可以将其声明为mutable Eigen::MatrixXd m_M;或将其更改为std::shared_ptr<Eigen::MatrixXd> m_pM;*mP从内部更新operator()(或者类似地,我可以使用引用)。作为另一种选择,我可以将此矩阵的数据作为原始 C 指针传递给,并在 优化operator()中修复它们。Ceres

我更愿意尽可能避免使用原始指针,而且我倾向于认为 usingmutable是最好的解决方案。一般来说,这是好的还是坏的做法,特别是,使用它是否安全Ceres?我还有什么其他选择?

0 投票
2 回答
2209 浏览

c++ - 传递 double 的参数但得到 Jet使用 ceres 求解器时

在使用添加残差块时,我是 Ceres Solver 的新学习者

其中参数是双[6];

但是当我输出 x[0] 时,我得到了这个:

在我将 x 的类型更改为 double 之后

我收到了这个错误:

我的代码有什么问题?非常感谢!

0 投票
0 回答
53 浏览

android - Crystax 建造谷神星时遇到的错误

当我使用 Crystax ndk 构建 Ceres-Solver 时,我更改了

因为 gnustl_static 与 android 上的 OpenCV 兼容,所以我有 libceres.a,我将它复制到项目 jni 文件夹并将以下行添加到 Applications.mk

然后我使用 Crystax ndk 运行 ndk-build(我将 Crystax 文件夹添加到系统路径)

使用 Ceres 的 test.cpp 的一部分如下:

然后事情就出错了(发出的错误信息越多):

哪里错了?

是我的 ndk 配置错误还是 Crystax 有错误?

0 投票
0 回答
1624 浏览

c++ - 使用 CMake 配置 ceres-solver 并找不到 SuiteSparse 配置标头

我正在尝试使用 CMake 配置 Ceres 以在我的 Windows 机器上构建。我在我的机器上构建了 Suitesparse v4.4.4,并指向了所有适当的目录和库。所以我相信我在配置中正确包含了 SuiteSparse - 但是当我在 CMake 中配置时,我不断收到一个奇怪的错误:

未找到 SUITESPARSE_CONFIG 标头(可选的 SuiteSparse 组件)。

找到 SUITESPARSE_CONFIG 库:C:/Program Files/Common Files/MSVC/SUITESPARSE/suitesparse-metis-for-windows-1.3.0/build_VS2015/install/lib64/suitesparseconfig.lib

未找到 UFCONFIG 标头(可选的 SuiteSparse 组件)。

-- 未能找到 SuiteSparse - 未能找到:SuiteSparse_config 标头和库(应存在于所有 SuiteSparse >= v4 安装中)或 UFconfig 标头(应存在于所有 SuiteSparse < v4 安装中)。

找到 METIS 库:C:/Program Files/Common Files/MSVC/SUITESPARSE/suitesparse-metis-for-windows-1.3.0/build_VS2015/install/lib64/metis.lib

找到 SuiteSparse:TRUE(找到版本“4.4.4”)

-- 找到 SuiteSparse 4.4.4,使用 SuiteSparse 构建。

由于某种原因,它说它找不到 SuiteSparse_CONFIG 标头。但是有一个名为 SuiteSparse_Config.h 的文件清楚地位于我的 SuiteSparse 文件中的包含文件夹中(我在 CMake 配置中指向该文件)。例如,我已包含条目 SUITESPARSE_INCLUDE_DIR_HINTS、SUITESPARSE_INCLUDE_DIR 和 SUITESPARSE_CONFIG_HEADER(它们指向我的 PC 上 SuiteSparse_config.h 文件所在的 PATH 和 FILEPATH):

C:/Program Files/Common Files/MSVC/SUITESPARSE/suitesparse-metis-for-windows-1.3.0/build_VS2015/install/include/suitesparse/SuiteSparse_config.h

如上面第一个引用所示,我可以在 CMake 中“生成”ceres-solver 并在 Visual Studio 中打开项目。但是,当我去构建项目时,由于无法找到 SuiteSparse 配置头,它们中的许多都无法构建。

为什么 CMake 一直说找不到 SUITESPARSE_CONFIG 标头?我觉得问题与如何在 CMakeLists.txt 文件之一中识别此配置文件有关(我认为,在 SuiteSparse 源文件夹中)。但是,实际的头文件通常不会在 CMake 源文件中指定。我需要对 CMakeLists.txt 文件进行某种编辑以使其找到并使用 SuiteSparse_config.h 标头(和源)文件吗?

0 投票
1 回答
972 浏览

c++ - 如何为 ceres 中的相同解决方案创建不同的求解器块?

我想用ceres来计算三角坐标。

对于这个问题,我需要解决网格中的网格坐标。每个三角形都有自己的顶点,但可以使用三角形(3 个顶点)和边(4 个顶点)等结构。

示例数据(伪代码):

[v1, v2][v4, v5]最初是相同的,在求解过程中可能会发生变化。

现在我有两个成本函数,一个在三角形上,一个在内边缘上

有两种简单的块结构

  • 两个块,一个带有所有三角形残基,一个带有所有边缘残基。
  • 每个三角形一个块,每个边一个块。

第一个求解x具有所有坐标的向量(2*|V|因为每个顶点都有两个坐标),因为块依赖于所有顶点。在第二种情况下,三角形块应该只依赖于三个顶点,而边缘块应该只依赖于四个顶点。我现在想使用第二个,因为我期望更好的性能和更好的收敛性。

如何设置 ceres 来解决相同的坐标,但只考虑与当前残差相关的顶点子集?

我尝试设置大小为 6 和 8 的问题以及在正确位置的指针x,但 ceres 不允许使用具有不同偏移量的相同结果指针。

接下来我尝试使用SubsetParameterization例如这样

但是 ceres 检查告诉我这两种变体都是错误的。

对于(1)我得到

对于(2)我得到

如何设置 ceres,以便我可以在重叠的块中拆分相同的问题,这只会影响少数结果变量?

0 投票
1 回答
862 浏览

c++ - ceres solver:如何在算子中进行数据类型转换和操作

我正在尝试使用 ceres 求解器来优化点云转换过程。

通过遵循 ceres 求解器教程中的示例,我得到了优化过程的简单工作版本。但是,当我尝试进一步修改运算符中的函数(在 MyCostFunctor 类中)时,结果完全错误(求解器收敛,但给出了错误的结果)。我发现问题是由我试图将参数从模板类型 T 转换为特征矩阵类型的两行代码引起的。

以下是代码:

这两行代码在函数“GetCorrespondingPoint”中被注释掉了。

主函数代码如下:

如果我注释掉这两行,我会得到正确的结果: 数据传输前的结果

但是,当我尝试使用这两行代码将参数转换为 Eigen 格式时(函数中未使用,仅复制和传输),我会得到错误的结果: 数据传输后的结果

谁能帮我弄清楚问题出在哪里,如果我想对参数进行一些操作以获得正确的对应点,我该怎么办?谢谢!

0 投票
1 回答
197 浏览

c++ - 使用 Ceres 优化多维函数

我想使用 Ceres 来优化 n 个参数的函数。如何找到这个函数的梯度尚不清楚,尽管我确实有一个明确的成本。到目前为止,我一直在使用 GSL,但我想我会尝试使用带有自动差异的 Ceres。

我看过玩具示例helloworld_analytic_diff.cc,其中他们使用 AutoDiff 来最小化函数 f(x) = 0.5 (10 - x)^2 并阅读教程,所以我想我会尝试将其扩展到二维函数 f(x,y) = (10-x)^2 +(20- y)^2,在 x, y = 10, 20 处具有全局最小值。但我对此有点卡住:

但是,如果我运行它,它最终会收敛到一些不正确的东西,这取决于最初的猜测:

关于我在这里做错了什么的任何想法?非常感谢!

0 投票
3 回答
6049 浏览

c++ - 为什么 C++ 编译器不做更好的常量折叠?

我正在研究加速大部分 C++ 代码的方法,该代码具有用于计算雅可比的自动导数。这涉及在实际残差中做一些工作,但大部分工作(基于分析的执行时间)是计算雅可比。

这让我很惊讶,因为大多数雅可比是从 0 和 1 向前传播的,所以工作量应该是函数的 2-4 倍,而不是 10-12 倍。为了模拟大量的 jacobian 工作是什么样的,我做了一个超级最小的例子,只有一个点积(而不是真实情况下的 sin、cos、sqrt 等),编译器应该能够优化为单个返回值:

应该是一样的

我很失望地发现,在没有启用快速数学的情况下,GCC 8.2、Clang 6 或 MSVC 19 都无法对充满 0 的矩阵的天真点积进行任何优化。即使使用快速数学(https://godbolt.org/z/GvPXFy),GCC 和 Clang 的优化也很差(仍然涉及乘法和加法),并且 MSVC 根本不做任何优化。

我没有编译器的背景,但这有什么原因吗?我相当肯定,在大部分科学计算中,能够进行更好的常数传播/折叠将使更多优化变得明显,即使常数折叠本身并没有导致加速。

虽然我对解释为什么不在编译器方面这样做很感兴趣,但我也对我可以在实际方面做些什么来使我自己的代码在面对这些类型的模式时变得更快感兴趣。

0 投票
2 回答
1342 浏览

c++ - 使 C++ 自动将 int 转换为 double

当我有一个数字类型时,它定义operator<为 double 但不是 int,与 int 文字的比较不起作用。这是一个问题,作为标准库的一部分,即std::complex包含 int 文字。

使用该类型时,我可以让编译器将 int 文字视为 double 吗?

简化示例:

失败发生在at_Div方法内部std::complex

导致错误:

我认为其中的代码可能std::complex应该_Rightimag < static_cast<_Other>(0)适用于所有数字类型,但我必须使用 stdlib 提供的内容。

由于另一种类型也来自库,我正在寻找一种将隐式转换添加到我的代码的方法。


对于实际代码:我正在使用ceres,它允许您使用模板化标量类型定义函子以进行自微分。标量被评估为TJet<T, N>

Ceres定义了 operator<(const Jet<T, N>&, const T&),它允许jet < 0.0但不允许jet < 0

在我的代码中,我可以通过使用双精度数或将整数显式转换为模板类型来解决这个问题T,但是当我尝试使用与complex<T>整数文字比较的方法时,我遇到了麻烦,比如_Div上面的方法。

0 投票
1 回答
330 浏览

ceres-solver - Ceres 捆绑调整,DENSE_NORMAL_CHOLESKY 比 SCHUR 快,但不应该吗?

我有一个简单的捆绑调整问题,有两个摄像头和 230 个点,我试图使用 Ceres 解决。我的目标是获得绝对最快的解决方案,但我看到的结果似乎与有关捆绑调整问题的文档相矛盾。

如此处所述:

one way to solve this problem is to set Solver::Options::linear_solver_type to SPARSE_NORMAL_CHOLESKY and call Solve(). And while this is a reasonable thing to do, bundle adjustment problems have a special sparsity structure that can be exploited to solve them much more efficiently. Ceres provides three specialized solvers (collectively known as Schur-based solvers) for this task.

但是,当我使用时DENSE_NORMAL_CHOLESKY,使用求解器设置:

它给了我:

但是,当我切换到 SCHUR 求解器时,如下所示:

它运行速度较慢,具有:

我能做些什么来获得更快的结果吗?我尝试过订购各种 linear_solver_type 和不同的预处理器。设置 options.num_threads = 8; 也没有明显的区别。我错过了什么吗?