使用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. 图扑 Web SCADA 零代码组态水泥生产工艺流程 HMI

    前言 水泥是建筑工业三大基本材料之一,素有"建筑工业的粮食"之称.2022 年 1-9 月水泥产量为 15.63 亿吨,生产方法包括新型干法.立窑.湿窑.干法中空窑和立波尔窑等. ...

  2. layui table表格使用table.resize()方法 重置表格尺寸

    解决 使用layui中的table表格重置表格尺寸 问题 表格的高度共有两种写法 相对应的就有两种解决方法 第一种 当表格高度设置为固定高度时,改变表格高度使用 tableIns=table.rend ...

  3. i春秋exec

    打开是一个gif,提示文字未登录 话不多说,查看源码 发现vim字样,可能是文件泄露 直接在url后加/.index.php.swp来下载泄露文件 下载好了之后放vm上使用vim -r  .index ...

  4. sublime text设置build system automatic提示no build system

    解决办法: 将: "selector": "source.asm" 改为: "selector": ["source.asm&qu ...

  5. day10 集合——队列(Queue)、Vector & Map集合常用方法 & HashMap的实现原理&二叉树&二叉查找树AVL树&红黑树

    集合--List 栈先进后出 队列 先进先出 Queue队列 方法 Queue<Integer> q = new LinkedList<>(); //添加元素 q.add(2) ...

  6. CGI、WSGI、uWSGI、ASGI……

    在学习 Python Web 开发时候,可能会遇到诸如 uwsgi.wsgi 等名词,下面通过梳理总结,探究它们之间的关系. CGI CGI(Common Gateway Interface)通用网关 ...

  7. 前端知识之JS(javascirpt)

    目录 JS简介 JS基础 1.注释语法 2.引入JS的多种方式 3.结束符号 变量与常量 基本数据类型 1.数字类型(Number) 2.字符类型(string) 3.布尔类型(Boolean) 4. ...

  8. pulsar集群搭建——生产环境

    pulsar集群搭建 前置条件,需要JDK环境 192.168.1.1 192.168.1.2 192.168.1.3 写入hosts 所有机器都需要执行 $ cat >>/etc/hos ...

  9. python之路38 SQL注入问题 索引触发器 事务 存储过程 函数 流程控制

    SQL注入问题 怪像1:输对用户名就可以登录成功 怪像2:不需要对的用户名和密码也可以登录成功 SQL注入:利用特殊符号的组合产生特殊的含义 从而避开正常的业务逻辑 select * from use ...

  10. 【RocketMQ】负载均衡源码分析

    RocketMQ在集群模式下,同一个消费组内,一个消息队列同一时间只能分配给组内的某一个消费者,也就是一条消息只能被组内的一个消费者进行消费,为了合理的对消息队列进行分配,于是就有了负载均衡. 接下来 ...