代码来源为 SLAM 14讲 ch6
1 #include <iostream> 2 #include <opencv2/core/core.hpp> 3 #include <ceres/ceres.h> 4 #include <chrono> 5 6 using namespace std; 7 8 // STEP1.代价函数的计算模型 此处为 Functor 具体概念可见底端链接 9 struct CURVE_FITTING_COST { 10 CURVE_FITTING_COST(double x, double y) : _x(x), _y(y) {} 11 12 // 残差的计算 13 template<typename T> 14 bool operator()( 15 const T *const abc, // 模型参数,有3维 16 T *residual) const { 17 residual[0] = T(_y) - ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) + abc[2]); // y-exp(ax^2+bx+c) 18 return true; 19 } 20 21 const double _x, _y; // x,y数据 22 }; 23 24 int main(int argc, char **argv) { 25 double ar = 1.0, br = 2.0, cr = 1.0; // 真实参数值 26 double ae = 2.0, be = -1.0, ce = 5.0; // 估计参数值 27 int N = 100; // 数据点 28 double w_sigma = 1.0; // 噪声Sigma值 29 double inv_sigma = 1.0 / w_sigma; 30 cv::RNG rng; // OpenCV随机数产生器 31 32 vector<double> x_data, y_data; // 生成具有噪声的数据 33 for (int i = 0; i < N; i++) { 34 double x = i / 100.0; 35 x_data.push_back(x); 36 y_data.push_back(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma * w_sigma)); 37 } 38 39 double abc[3] = {ae, be, ce}; 40 41 // STEP2.构建最小二乘问题 42 ceres::Problem problem; 43 for (int i = 0; i < N; i++) { 44 problem.AddResidualBlock( // 向问题中添加误差项 45 // 使用自动求导,模板参数:①误差类型,②输出维度[residual],③输入维度[参数块abc] 最多支持10个独立变量,维数要与前面struct中一致 46 new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3>( 47 new CURVE_FITTING_COST(x_data[i], y_data[i]) 48 ), 49 nullptr, // 核函数,这里不使用,为空 50 abc // 待估计参数 51 ); 52 } 53 54 // STEP3.配置求解器 55 ceres::Solver::Options options; // 这里有很多配置项可以填 56 options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY; // 增量方程如何求解 57 options.minimizer_progress_to_stdout = true; // 输出到cout 58 59 ceres::Solver::Summary summary; // 优化信息 60 chrono::steady_clock::time_point t1 = chrono::steady_clock::now(); 61 ceres::Solve(options, &problem, &summary); // 开始优化 62 chrono::steady_clock::time_point t2 = chrono::steady_clock::now(); 63 chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1); 64 cout << "solve time cost = " << time_used.count() << " seconds. " << endl; 65 66 // 输出结果 67 cout << summary.BriefReport() << endl; 68 cout << "estimated a,b,c = "; 69 for (auto a:abc) cout << a << " "; 70 cout << endl; 71 72 return 0; 73 }
# 相关参考链接
关于ceres官方文档笔记参考 -> [Ceres Solver 官方教程学习笔记(十一)——非线性最小二乘法建模Modeling Non-linear Least Squares (上)_小政哥的博客-CSDN博客_ceres solver]
关于仿函数的理解参考 -> [https://www.cnblogs.com/decade-dnbc66/p/5347088.html]
关于explicit关键字参考 -> [https://www.cnblogs.com/rednodel/p/9299251.html]
标签:ceres,20,abc,chrono,double,Ceres,2022.9,1.0,data From: https://www.cnblogs.com/isaac0617/p/16710962.html