ceres库是算法优化库,与g2o不同的是它需要自己搭建代价函数,高翔博士那本书上安装ceres默认是装在(/usr/local/include和/usr/local/lib)中。
原书CmakeList.txt是:
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
# 寻找Ceres库并添加它的头文件
find_package( ceres REQUIRED PATHS )
include_directories( ${CERES_INCLUDE_DIRS})
link_directories(${CERES_LIBRARY_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} )
但是如果我们把ceres安装到别处,那么上述的CmakeList.txt在搭建程序的时候会报错:
Could not find a package configuration file provided by "Ceres" with any of
the following names:
CeresConfig.cmake
ceres-config.cmake
Add the installation prefix of "Ceres" to CMAKE_PREFIX_PATH or set
"Ceres_DIR" to a directory containing one of the above files. If "Ceres"
provides a separate development package or SDK, be sure it has been
installed.
整个安装ceres 和配置ceres过程
1、下载ceres
2、根据http://ceres-solver.org/installation.html 来安装ceres
安装到别处的方法是
mkdir build
cd build
cmake -D CMAKE_INSTALL_PREFIX=/usr/local/ceres .. #前提是在local下自己建立了一个ceres文件
sudo make install
安装后的效果如下图:
3、对于以上CmakeList.txt文件中修改为:
#list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )#可有可无
set(Ceres_DIR /usr/local/ceres/lib/cmake/Ceres) #important,/usr/local/ceres这种还是报错,要到Ceres才行
find_package(Ceres REQUIRED )
include_directories(${CERES_INCLUDE_DIRS})
link_directories(${CERES_LIBRARY_DIRS})
add_executable( curve_fitting main.cpp )
target_link_libraries( curve_fitting ${CERES_LIBRARIES})
拟合y=ax+b的代码,设置ground truth y=2x+3
cmakelist.txt:
cmake_minimum_required(VERSION 2.8)
set( CMAKE_CXX_FLAGS "-std=c++11" )
project(useCeres)
#list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
set(Ceres_DIR /usr/local/ceres/lib/cmake/Ceres)
find_package(Ceres REQUIRED )
include_directories(${CERES_INCLUDE_DIRS})
link_directories(${CERES_LIBRARY_DIRS})
add_executable( curve_fitting main.cpp )
target_link_libraries( curve_fitting ${CERES_LIBRARIES})
cpp文件
#include <iostream>
#include<chrono>
#include<ceres/ceres.h>
#include<stdlib.h>
#include<vector>
#include<math.h>
using namespace std;
struct LineFitCost
{
LineFitCost(double x,double y):_x(x),_y(y){}//初始化列表
template<typename T> //重载(),函数对象
bool operator()(const T* const ab,T* residual)const
{
//y=ax+b
residual[0]=T(_y)-(ab[0]*T(_x)+ab[1]);
return true;
}
const double _x,_y;
};
int main(int argc, char *argv[])
{
google::InitGoogleLogging(argv[0]);
double a=2.0,b=3.0 ;//y=2x+3
int N=30; //sample
double ab[2]={};
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(a*x+b+(rand()%360/180.0)*M_PI/180);//加上噪声
cout<<x_data[i]<<" "<<y_data[i]<<endl;
}
//构建最小二乘
ceres::Problem problem;
for(int i=0;i<N;++i)
{
ceres::CostFunction *costfunction=new ceres::AutoDiffCostFunction<LineFitCost,1,2>(new LineFitCost(x_data[i],y_data[i]));
//将残差方程和观测值加入到problem,nullptr表示核函数为无,ab是待拟合参数
problem.AddResidualBlock(costfunction,nullptr,ab);
}
//解方程,copy and paste
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_SCHUR;
options.minimizer_progress_to_stdout = true;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
cout<<"a,b:"<<endl;
for(auto i:ab)
{
cout<<i<<endl;
}
return 0;
}
结果图