https://blog.csdn.net/weixin_39373577/article/details/81285420
sudo apt-get install liblapack-dev
sudo apt-get install libsuitesparse-dev
sudo apt-get install libcxsparse3.1.2
sudo apt-get install libgflags-dev
sudo apt-get install libgoogle-glog-dev libgtest-dev
deb http://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse
deb-src http://mirrors.ustc.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
下载地址:https://github.com/ceres-solver/ceres-solver
mkdir build
cd build
cmake ..
sudo make install
这里简单的介绍一下思路,下一篇博客会详细的介绍一下两种梯度下降方法。
假设有一条曲线满足如下方程: y = e x p ( a x 2 + b x + c ) + w y=exp(ax^2+bx+c)+w y=exp(ax2+bx+c)+w
其中, a , b , c a,b,c a,b,c为曲线的参数, w w w为高斯噪声。
如果我们有N对点(x, y),我们要根据这些点求出曲线的参数,那么问题可以转换为下面的优化问题: m i n a , b , c 1 2 ∑ i = 1 N ∥ y i − e x p ( a x i 2 + b x i + c ) ∥ 2 min_{a,b,c}\frac{1}{2}\sum_{i=1}^{N}\begin{Vmatrix}y_i-exp(ax_i^2+bx_i+c)\end{Vmatrix}^2 mina,b,c21i=1∑N∥∥yi−exp(axi2+bxi+c)∥∥2在上式中,待估计的变量是 a , b , c a,b,c a,b,c。
#include
#include
#include
#include
using namespace std;
//代价函数的计算模型
struct CURVE_FITTING_COST
{
const double _x, _y;
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(_y) + abc[2]);
return 0;
}
};
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;
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] << " " << y_data[i] << endl;
}
//构建最小二乘问题
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_SCHUR;
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;
}
CMakeLists.txt的内容如下:
cmake_minimum_required( VERSION 2.8 )
project( ceres_curve_fitting )
set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )
# 寻找Ceres库并添加它的头文件
find_package( Ceres REQUIRED )
include_directories( ${CERES_INCLUDE_DIRS} )
# OpenCV
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_DIRS} )
add_executable( curve_fitting main.cpp )
# 与Ceres和OpenCV链接
target_link_libraries( curve_fitting ${CERES_LIBRARIES} ${OpenCV_LIBS} )