官方文档:http://www.ceres-solver.org/nnls_tutorial.html#robust-curve-fitting
参考文章:一文助你Ceres 入门——Ceres Solver新手向全攻略
使用Ceres求解非线性优化问题,一共分为三个部分:
1、 第一部分:构建cost fuction(代价函数)。这个部分需要使用仿函数(就是使一个类的使用看上去像一个函数,就是重载了个括号运算符,所以对象调用operator()函数像个函数,理解就行这不重要)技巧来实现。这步定义一个cost function的结构体,在结构体内重载()运算符。
2、 第二部分:通过代价函数构建待求解的优化问题。
3、 第三部分:配置求解器参数并求解问题,这个步骤就是设置方程怎么求解、求解过程是否输出等,然后调用一下Solve方法。
Ceres库中提供的核函数主要有:TrivialLoss 、HuberLoss、 SoftLOneLoss 、 CauchyLoss。
要使用CauchyLoss,只需要将nullptr换成new ceres::CauchyLoss(0.5)就行(0.5为参数)
#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>
#include <chrono>
#include <fstream>
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;
}
private:
const double _x, _y;
};
int main ( int argc, char** argv )
{
double a=1.0, b=2.0, c=1.0;
int N=100;
double w_sigma=1.0;
cv::RNG rng;
double abc[3] = {0,0,0};
vector<double> x_data, y_data;
stringstream ss;
cout<<"生成数据 generating data: "<<endl;
for ( int i=0; i<N; i++ )
{
double x = i/100.0;
x_data.push_back ( x );
y_data.push_back (
exp ( a * x * x + b * x + c ) + rng.gaussian ( w_sigma )
);
cout<<x_data[i]<<"\t"<<y_data[i]<<endl;
ss << x_data[i] << " " << y_data[i] << endl;
}
ofstream file("points.txt");
file << ss.str();
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_QR;
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()<<" seconds. "<<endl;
cout<<summary.BriefReport() <<endl;
cout<<"estimated a,b,c = ";
for ( auto a:abc ) cout<<a<<" ";
cout<<endl;
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)