一、Ceres简介
Ceres是一个最小二乘问题求解库,我们只需要定义待优化的问题,然后交给它计算即可。
① 基本概念
常用的最小二乘问题形式如下:
参数块:$x_1$, … $x_n$等优化变量
代价函数(残差块/误差项):$f_i$
核函数:ρ(·),目标函数由许多平方项经过核函数求和自称
② 使用方法
定义每个参数块。参数块就是简单的向量,也可以是四元数、李代数等特殊的结构。
定义残差块的计算方式。残差块对参数块进行自定义计算,返回残差值,然后求平方和作为目标函数的值。
定义雅可比的计算方式。
把所有的参数块和残差块加入Ceres定义的Problem对象中,调用Solve函数求解
二、Ceres安装
首先下载Ceres的源代码
1 git clone https://github.com/ceres-solver/ceres-solver.git
安装ceres所需要的依赖
1 sudo apt install libsuitesparse-dev libcxsparse3 libgflags-dev libgoogle-glog-dev libgtest-dev
然后进入文件夹编译安装ceres,这里耗时比较久大概20min左右。
1 2 3 4 5 6 cd ceres-solver/mkdir buildcd buildcmake .. make sudo make install
安装完成后,如果在/usr/local/include/ceres/
目录下能找到Ceres的头文件,并且也有库文件/usr/local/lib/libceres.a
,说明安装成功了,可以使用Ceres进行优化计算了。
1 2 ll /usr/local/include/ceres/ ll /usr/local/lib/libceres.a
三、使用Ceres拟合曲线
此示例程序依赖opencv、Eigen库,需要预先安装。
main.cpp 文件代码程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <iostream> #include <opencv2/core/core.hpp> #include <ceres/ceres.h> #include <chrono> using namespace std;struct CURVE_FITTING_COST { CURVE_FITTING_COST (double x, double y) : _x(x), _y(y) {} template <typename T> bool operator () ( const T *const abc, T *residual) const { residual[0 ] = T (_y) - ceres::exp (abc[0 ] * T (_x) * T (_x) + abc[1 ] * T (_x) + abc[2 ]); return true ; } const double _x, _y; }; int main (int argc, char **argv) { double ar = 1.0 , br = 2.0 , cr = 1.0 ; double ae = 2.0 , be = -1.0 , ce = 5.0 ; int N = 100 ; double w_sigma = 1.0 ; double inv_sigma = 1.0 / w_sigma; cv::RNG rng; vector<double > x_data, y_data; for (int i = 0 ; i < N; i++){ double x = i / 100.0 ; x_data.push_back (x); y_data.push_back (exp (ar * x * x + br * x + cr) + rng.gaussian (w_sigma * w_sigma)); } double abc[3 ] = {ae, be, ce}; ceres::Problem problem; for (int i = 0 ; i < N; i++){ problem.AddResidualBlock (new ceres::AutoDiffCostFunction <CURVE_FITTING_COST, 1 , 3 >(new CURVE_FITTING_COST (x_data[i], y_data[i])),nullptr ,abc); } ceres::Solver::Options options; options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY; options.minimizer_progress_to_stdout = true ; ceres::Solver::Summary summary; chrono::steady_clock::time_point t1 = chrono::steady_clock::now (); ceres::Solve (options, &problem, &summary); chrono::steady_clock::time_point t2 = chrono::steady_clock::now (); chrono::duration<double > time_used = chrono::duration_cast<chrono::duration<double >>(t2 - t1); cout << "solve time cost = " << time_used.count () << "s." << endl; cout << summary.BriefReport () << endl; cout << "estimated a, b, c = " ; for (auto a:abc) cout << a << " " ; cout << endl; return 0 ; }
CMakeLists.txt 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cmake_minimum_required (VERSION 3.20 )project (ceresCurveFitting)set (CMAKE_CXX_STANDARD 14 )# OpenCV库 find_package (OpenCV REQUIRED)include_directories (${OpenCV_INCLUDE_DIRS})# Ceres库 find_package (Ceres REQUIRED)include_directories (${CERES_INCLUDE_DIRS})# Eigen库 include_directories ("/usr/include/eigen3" )# 定义可执行文件 add_executable (ceresCurveFitting main.cpp)# 链接库 target_link_libraries (ceresCurveFitting ${OpenCV_LIBS})target_link_libraries (ceresCurveFitting ${CERES_LIBRARIES})
【Ceres基本使用方法】使用Ceres拟合曲线求解最小二乘问题