使用Ceres求解非线性优化问题,一共分为三个部分:

1、 第一部分:构建cost fuction,即代价函数,也就是寻优的目标式。这个部分需要使用仿函数(functor)这一技巧来实现,做法是定义一个cost function的结构体,在结构体内重载()运算符。

2、 第二部分:通过代价函数构建待求解的优化问题。

3、 第三部分:配置求解器参数并求解问题,这个步骤就是设置方程怎么求解、求解过程是否输出等,然后调用一下Solve方法

#include <iostream>
#include <opencv2/core/core.hpp>
#include <ceres/ceres.h>
#include <chrono> 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, // 模型参数,待优化的参数,有3维
T *residual) const {
residual[0] = T(_y) - ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) + abc[2]); // y-exp(ax^2+bx+c) //残差,也就是代价函数的输出
return true;
} const double _x, _y; // x,y数据
}; int main(int argc, char **argv) {
double ar = 1.0, br = 2.0, cr = 1.0; // 真实参数值
double ae = 2.0, be = -1.0, ce = 5.0; // 估计参数值
int N = 100; // 数据点
double w_sigma = 1.0; // 噪声Sigma值
double inv_sigma = 1.0 / w_sigma;
cv::RNG rng; // OpenCV随机数产生器 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(exp(ar * x * x + br * x + cr) + rng.gaussian(w_sigma * w_sigma));
} double abc[3] = {ae, be, ce}; // 构建最小二乘问题
ceres::Problem problem;
for (int i = 0; i < N; i++) {
problem.AddResidualBlock( // 向问题中添加误差项
// 使用自动求导,将定义的代价函数结构体传入。模板参数:误差类型,输出维度即残差的维度,输入维度即优化参数的维度,维数要与前面struct中一致
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_NORMAL_CHOLESKY; // 增量方程如何求解
//options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true; // 输出到cout 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(gaussnewton)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
include_directories("/usr/include/eigen3")
set(SOURCE_FILES main.cpp)
add_executable(gaussnewton ${SOURCE_FILES})
target_link_libraries(gaussnewton ${OpenCV_LIBS})
target_link_libraries(gaussnewton ${CERES_LIBRARIES})

视觉十四讲:第六讲_ceres非线性优化的更多相关文章

  1. ros系统21讲—前六讲

    课程介绍(第一讲) linux介绍安装(第二讲) linux的基础操作(第三讲) ROS中语言c++与python介绍(第四讲) 安装ROS系统(第五讲) 第一个: sudo sh -c echo d ...

  2. 高翔《视觉SLAM十四讲》从理论到实践

    目录 第1讲 前言:本书讲什么:如何使用本书: 第2讲 初始SLAM:引子-小萝卜的例子:经典视觉SLAM框架:SLAM问题的数学表述:实践-编程基础: 第3讲 三维空间刚体运动 旋转矩阵:实践-Ei ...

  3. 视觉slam学习之路(一)看高翔十四讲所遇到的问题

      目前实验室做机器人,主要分三个方向,定位导航,建图,图像识别,之前做的也是做了下Qt上位机,后面又弄红外识别,因为这学期上课也没怎么花时间在项目,然后导师让我们确定一个方向来,便于以后发论文什么. ...

  4. 浅读《视觉SLAM十四讲:从理论到实践》--操作1--初识SLAM

    下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/slambook 第二讲:初识SLAM 2.4.2 Hello SLAM(书本P2 ...

  5. 第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

    第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字 ...

  6. 高博-《视觉SLAM十四讲》

    0 讲座 (1)SLAM定义 对比雷达传感器和视觉传感器的优缺点(主要介绍视觉SLAM) 单目:不知道尺度信息 双目:知道尺度信息,但测量范围根据预定的基线相关 RGBD:知道深度信息,但是深度信息对 ...

  7. 《视觉SLAM十四讲》第2讲

    目录 一 视觉SLAM中的传感器 二 经典视觉SLAM框架 三 SLAM问题的数学表述 注:原创不易,转载请务必注明原作者和出处,感谢支持! 本讲主要内容: (1) 视觉SLAM中的传感器 (2) 经 ...

  8. 《视觉SLAM十四讲》第1讲

    目录 一 视觉SLAM 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 视觉SLAM 什么是视觉SLAM? SLAM是Simultaneous Localization and Mappin ...

  9. 视觉slam十四讲第七章课后习题6

    版权声明:本文为博主原创文章,转载请注明出处: http://www.cnblogs.com/newneul/p/8545450.html 6.在PnP优化中,将第一个相机的观测也考虑进来,程序应如何 ...

  10. 视觉slam十四讲第七章课后习题7

    版权声明:本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/newneul/p/8544369.html  7.题目要求:在ICP程序中,将空间点也作为优化变量考虑进来 ...

随机推荐

  1. xshell调整字体大小

    1. 进入设置 %default%:默认对全部终端生效 如果想对单一终端单独设置,可先进入会话管理,针对单一会话单独调整 2. 点击外观配置,修改字体大小

  2. 1、ArrayList源码解析

    目录 1 概述 2 底层数据结构 3 构造函数 4 自动扩容 5 set() get() remove() 6 Fail-Fast机制 1 概述 ArrayList实现了List接口,是 顺序容器,允 ...

  3. JDK中内嵌JS引擎介绍及使用

    原文: JDK中内嵌JS引擎介绍及使用 - Stars-One的杂货小窝 最近研究阅读这个APP,其主要功能就是通过一个个书源,从而实现移动端阅读的体验 比如说某些在线小说阅读网站,会加上相应的广告, ...

  4. 【数据库】pgsql窗口函数,分组求sum的方式

    select distinct    quantity,    standard_cost,    sum(a.quantity*a.standard_cost) over(partition by ...

  5. angr_ctf——从0学习angr(三):Hook与路径爆炸

    路径爆炸 之前说过,angr在处理分支时,采取统统收集的策略,因此每当遇见一个分支,angr的路径数量就会乘2,这是一种指数增长,也就是所说的路径爆炸. 以下是路径爆炸的一个例子: char buff ...

  6. 在微信上搭建ChatGpt机器人

    在微信上搭建ChatGpt机器人 项目地址:https://gitee.com/shtml/wechatbot?_from=gitee_search 准备 一个服务器:Windos,Centos,Ub ...

  7. MySQL数据结构(索引)

    目录 一:MySQL索引与慢查询优化 1.什么是索引? 2.索引类型分类介绍 3.不同的存储引擎支持的索引类型也不一样 二:索引的数据结构 1.二叉树(每个节点只能分两个叉) 2.数据结构(B树) 3 ...

  8. openresty package path

    openresty lua_package_path 是整个openresty最基础的功能,不理解 path就无法做项目,更无法写框架. 先看下文档lua_package_path https://g ...

  9. ArcObjects SDK开发 017 在ArcObject SDK 中使用Toolbox

    1.Geoprocessor和IGPProcess Geoprocessor是ArcObjects SDK中定义Tool执行器.IGPProcess接口是ArcObjects SDK中定义的ArcTo ...

  10. pytest常用参数汇总

    1.  -s    表示输出调试信息,包括print打印信息 D:\demo>pytest -s ./pytest_1 ===================================== ...