用Ceres解决最小二乘问题步骤一般是这样
- 我们要先建立一个最小二乘问题;(代码中就是构建一个用Problem类构建一个problem对象)
- 接着我们需要建立代价函数costFunction。(如果是用AutoDiff自动求解,用法是这样的:AutoDiffCostFunction<仿函数类,残差的维度,剩下的一堆是优化变量的维度>);
我们看到这里有一个“仿函数类”需要我们填。所以,这时我们需要在外面定义一个仿函数类:这个仿函数类主要是告诉Ceres怎么计算残差。
注意:这里“剩下一堆是优化变量的维度”含义是,如果把目个变量写在一起变成向量的形式(成了一个变量),那就直接写向量的维度m;要是分开写的话就是m个1; - 添加残差模块,用problem.AddResidualBlock(costFunc, 鲁邦核函数,优化变量们用指针传)
(鲁棒核函数没有的话就是nullptr;引用也是指针) - 设置求解器和输出报告
#include <iostream>
#include <ceres/ceres.h>
#include <opencv2/core/core.hpp>
/*这个工程优化 y=mx+c中的参数m和参数c*/
// 设计一个仿函数(函数对象)用于残差计算 cost function
class computeResidual
{
public:
computeResidual(double x, double y) : _x(x), _y(y) {}
// template <typename T>
// bool operator()(const T *m, const T *c, T *residual) const
// {
// residual[0] = T(_y) - (m[0] * T(_x) + c[0]);
// return true;
// }
template <typename T>
bool operator()(const T *const paraMC, // 参数维度,2维
T *residual) const
{
residual[0] = T(_y) - (paraMC[0] * T(_x) + paraMC[1]);
return true;
}
const double _x;
const double _y;
};
int main(int argc, char **argv)
{
// 参数
double m = 0.0, c = 0.0;
// 参数块
double paraMC[2] = {m, c};
cv::RNG rng;
double sigma = 0.2;
// 1、建立最小二乘问题
ceres::Problem problem;
for (int i = 0; i < 100; ++i)
{
// 按照m = 0.3, c = 0.1来对100个点进行赋值,并给予白噪声
double y_with_noise = std::exp(0.3 * i / 100.0 + 0.1) + rng.gaussian(sigma * sigma);
// 2、建立costFunction。如果是AutoDiff自动求解就如下 :
// AutoDiffCostFunction<仿函数类,残差的维度,剩下的一堆是优化变量的维度>
// ceres::CostFunction *cost_function =
// new ceres::AutoDiffCostFunction<computeResidual, 1, 1, 1>(
// new computeResidual(i / 100.0, y_with_noise));
//
// // 3、添加残差模块,用problem.AddResidualBlock(costFunc, 鲁邦核函数,优化变量们用指针传)
// problem.AddResidualBlock(cost_function, nullptr, &m, &c);
/*********************************************************************************************/
ceres::CostFunction *cost_function =
new ceres::AutoDiffCostFunction<computeResidual, 1, 2>(
new computeResidual(i / 100.0, y_with_noise));
problem.AddResidualBlock(cost_function, nullptr, paraMC);
}
// 4、设置求解器和输出报告
ceres::Solver::Options options; // 这其中有很多配置项可以填
options.linear_solver_type = ceres::DENSE_QR; // 增量方程怎么求解
options.minimizer_progress_to_stdout = true; // 输出到cout
options.max_num_iterations = 10;
ceres::Solver::Summary summary; // 优化信息
ceres::Solve(options, &problem, &summary); // 开始优化
std::cout << summary.BriefReport() << std::endl;
// std::cout << "m=" << m << " "
// << "c=" << c << std::endl;
/*********************************************************************************************/
std::cout << summary.BriefReport() << std::endl;
std::cout << "m=" << paraMC[0] << "c=" << paraMC[1] << std::endl;
return 0;
}
标签:ceres,const,函数,double,简单,Ceres,使用,problem,cost
From: https://www.cnblogs.com/qizhengxun/p/18087318