视觉SLAM十四讲 读书编程笔记 Chapter6 非线性优化

视觉slam-----第四篇 卡尔曼滤波 最小二乘法和卡尔曼滤波 很多人都疑惑,一个滤波问题怎么才能用得上卡尔曼滤波呢?扩展卡尔曼滤波又和卡尔曼滤波有什么关系?本篇博客不讲这些内容之间的推导关系,毕竟已经有无数人详细讲解了这个过程,这里只大概捋一捋它们之间的关系,已经我们该如何进行选择。 ... 阅读详情

实践:Ceres

1. 安装Ceres依赖库

sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3.1.2 libgflags-dev libgoogle-glog-dev libgtest-dev

出现找不到package的错误:
在这里插入图片描述解决办法:
添加源,用下面命令打开source.list

sudo gedit /etc/apt/sources.list

在第一行添加:

deb http://cz.archive.ubuntu.com/ubuntu trusty main universe

然后更新一下:

sudo apt-get update

再执行Ceres依赖库的安装就不会报错啦

2. 编译安装Ceres

github上下载Ceres源码,下载地址为:https://github.com/ceres-solver
使用cmake编译它并安装到机器上,安装完成之后,在/usr/local/include/ceres/下可以找到Ceres的头文件,在/usr/local/lib/下可以找到名为libceres.a的库文件。

make过程出现错误:
在这里插入图片描述
error: no type named ‘Literal’ in ‘struct Eigen::NumTraits<ceres::Jet<double, 2> >’
这是因为eigen3与ceres发生了冲突。
解决办法:
下载与书中提供的ceres版本兼容的eigen,与书中提供的ceres版本兼容的eigen下载
编译并且安装它,然后再编译ceres工程就可以顺利通过啦

3. 曲线拟合问题描述

假设有一条满足以下方程的曲线:y=exp(ax2+bx+c)+w
其中,a,b,c为曲线的参数,w为高斯噪声。
为了模拟实际的曲线拟合问题,我们假设曲线参数a,b,c的真值,然后引入高斯噪声w生成观测x和y
我们在非线性优化问题中会首先给待估计变量a,b,c一个初始值,然后把观测(x,y)输入导ceres中用ceres拟合这条曲线。

4. ceres使用方法

(1)定义Cost Function模型。 方法是书写一个类。并在类中定义带模板的( )运算符,这样该类就成为了一个拟函数。这种定义方式使得ceres可以像调用函数一样,对该类的某个对象(比如 a)调用a( )方法,这使对象具有像函数那样的行为。

//代价函数的计算模型
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	//残差
	{
		
		//y-exp(ax^2+bx+c)
		residual[0] = T(_y) -ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) +abc[2]);
		return true;
	}

	const double _x,_y;//x,y数据
};

(2)构建最小二乘问题

定义一个问题对象:

ceres::Problem problem;

调用AddResidualBlock将误差项添加导目标函数中,残差block需要配置求导方式,核函数以及待估计的参数。
其中求导方式有a.使用ceres的自动求导(Auto Diff); b.使用数值求导(Numeric Diff); c.自行推导解析的导数形式,提供给ceres
自动求导需要设定误差项和优化变量的维度。这里误差项是我们定义的CURVE_FITTING_COST类;误差是标量,维度为1; 优化变量为abc,维度为3;不使用核函数;待估计参数为abc

	//构建最小二乘问题
	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		//待估计参数
		);
	}

(3)配置求解器
求解选项配置:

	ceres::Solver::Options options;//这里有很多配置项可以填
	options.linear_solver_type = ceres::DENSE_QR;//	增量方程如何求解
	options.minimizer_progress_to_stdout = true;//输出到cout

优化信息对象的定义:

	ceres::Solver::Summary summary;

(4)对问题进行优化

	ceres::Solve (options,&problem,&summary);//开始优化

优化信息对象输出结果:

	cout<<summary.BriefReport()<<endl;

最后优化的结果放在abc变量中

5.完整代码

ceres_curve_fitting.cpp

//2019.08.08
#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	//残差
	{
		
		//y-exp(ax^2+bx+c)
		residual[0] = T(_y) -ceres::exp(abc[0] * T(_x) * T(_x) + abc[1] * T(_x) +abc[2]);
		return true;
	}

	const double _x,_y;//x,y数据
};


int main()
{
	double a=1, b=2.0, c=1.0;	//真实参数值
	int N = 100;			//数据点
	double w_sigma = 1.0;		//噪声Sigma(标准差)值
	cv::RNG rng;			//opencv随机数产生器
	double abc[3] = {0,0,0};	//abc参数的估计值,初始值为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_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

#2019.08.08-08.09
# 添加C++标准文件
set(CMAKE_CXX_FLAGS "-std=c++11")

#寻找opencv库
find_package(OpenCV REQUIRED)
#寻找ceres库
find_package(Ceres REQUIRED)

#添加Eigen的头文件
include_directories("/usr/include/eigen3")
#添加Opencv的头文件
include_directories( ${OpenCV_INCLUDE_DIRS})
#添加ceres的头文件,下面两种方法等价
#include_directories(${CERES_INCLUDE_DIRS})
include_directories("/usr/local/include/ceres/")



add_executable(ceres_curve_fitting ceres_curve_fitting.cpp)

#链接OpenCV库
target_link_libraries(ceres_curve_fitting ${OpenCV_LIBS} )

#链接ceres库,以下两种方法不等价
target_link_libraries(ceres_curve_fitting ${CERES_LIBRARIES})
#target_link_libraries(ceres_curve_fitting "/usr/local/lib/")

运行结果:
在这里插入图片描述
在这里插入图片描述

实践:g2o

1.安装g2o依赖库

sudo apt-get install libqt4-dev qt4-qmake libqglviewer-dev libsuitesparse-dev libcxsparse3.1.2 libcholmod-dev

安装时出现:
在这里插入图片描述
E: Unable to locate package libcholmod-dev
解决办法:
先把其他依赖库安装好:

sudo apt-get install libqt4-dev qt4-qmake libqglviewer-dev libsuitesparse-dev libcxsparse3.1.2

然后单独安装libcholmod-dev,输入以下命令然后按下Tab键

sudo apt-get install libcholmod

在这里插入图片描述
我们安装libcholmod3.0.6

sudo apt-get install libcholmod3.0.6

至此,依赖库安装完毕

2.编译安装g2o

github上下载g2o源码,下载地址为:https://github.com/RainerKuemmerle/g2o
使用cmake编译它并安装到机器上,安装完成之后,在/usr/local/include/g2o/下可以找到g2o的头文件,在/usr/local/lib/下可以找到它的库文件。

make出现错误:
在这里插入图片描述
moc: Cannot open options file specified with @
这是因为路径中包含了中文名称,把源码放在无中文名称的路径中,make就可以顺利通过。

3. g2o使用方法

(1)图优化基础
传统的非线性优化问题仅有一组优化变量和很多个误差项,我们并不知道它们之间的关联。图优化是把优化问题表现成图的一种方式,用顶点表示优化变量,用边表示误差项。
(2)SLAM中图优化问题举例
在这里插入图片描述
(3) 曲线拟合问题的图优化表示
在这里插入图片描述
节点为优化变量,边为误差项,这里的边是一元边

(4)使用g2o的基本步骤
定义顶点和边的类型
构建图
选择优化算法
调用g2o进行优化,返回结果
(5)g2o头文件

#include <g2o/core/base_vertex.h>
#include <g2o/core/base_unary_edge.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/core/optimization_algorithm_gauss_newton.h>
#include <g2o/core/optimization_algorithm_dogleg.h>
#include <g2o/solvers/dense/linear_solver_dense.h>

(6)派生顶点CurveFittingVertex
在其中要重写两个重要的虚函数:
顶点的更新函数:oplusImpl(),该函数处理的是xk+1=xk+增量x
顶点的重置函数:setToOriginImpl(),把估计值置零,是平凡的

//定义曲线模型的顶点(优化变量),参数模板:优化变量维度和数据类型
class CurveFittingVertex: public g2o::BaseVertex<3,Eigen::Vector3d>
{
public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
	virtual void setToOriginImpl()//重置
	{
		_estimate << 0,0,0;
	}

	virtual void oplusImpl(const double* update)//更新
	{
		_estimate += Eigen::Vector3d(update);
	}

	//存盘和读盘,留空
	virtual bool read(istream& in){}
	virtual bool write(ostream& out) const {}
};

(7)派生边CurveFittingEdge
其中要重写一个重要的虚函数:
边的误差计算函数:computeError(),这里是观测值-曲线系数拟合的值

//定义曲线模型的边(误差项) 模板参数:观测值维度,数据类型,连接顶点类型
class CurveFittingEdge: public g2o::BaseUnaryEdge<1,double,CurveFittingVertex>
{
public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
	CurveFittingEdge(double x):BaseUnaryEdge(),_x(x){}
	//计算曲线模型误差
	void computeError()
	{
		const CurveFittingVertex* v = static_cast<const CurveFittingVertex*>(_vertices[0]);
		const Eigen::Vector3d abc = v->estimate();
		_error(0,0) = _measurement - std::exp(abc(0,0)*_x*_x + abc(1,0)*_x + abc(2,0));
	}

	virtual bool read(istream& in) {}
	virtual bool write(ostream& out) const {}

public:
	double _x;//x值,y值为_measurement
};

(8)配置图优化

	//构建图优化,先设定g2o
	//矩阵块,每个误差项优化变量维度为3,误差值维度为1
	typedef g2o::BlockSolver<g2o::BlockSolverTraits<3,1>> Block;
	//线性方程求解器,稠密的增量方程
	Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>();
	Block* solver_ptr = new Block(linearSolver);//矩阵块求解器
	//梯度下降方法,从GN,LM,DogLeg中选
	g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
	//取消下面的注释,以使用GN或DogLeg
	//g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton(solver_ptr);
	//g2o::OptimizationAlgorithmDogleg* solver = new g2o::OptimizationAlgorithmDogleg(solver_ptr);

	g2o::SparseOptimizer optimizer;//图模型
	optimizer.setAlgorithm(solver);//设置求解器
	optimizer.setVerbose(true);//打开调试输出

(9)向图中填充顶点和边

	//向图中增加顶点
	CurveFittingVertex* v = new CurveFittingVertex();
	v->setEstimate(Eigen::Vector3d(0,0,0));
	v->setId(0);
	optimizer.addVertex(v);

	//向图中增加边
	for(int i=0;i<N;i++)
	{
		CurveFittingEdge* edge = new CurveFittingEdge(x_data[i]);
		edge->setId(i);
		edge->setVertex(0,v);//设置连接的顶点
		edge->setMeasurement(y_data[i]);//观测数值
		//信息矩阵:协防差矩阵的逆
		edge->setInformation(Eigen::Matrix<double,1,1>::Identity()*1/(w_sigma*w_sigma));
		optimizer.addEdge(edge);
	}

(10)执行优化

	optimizer.initializeOptimization();
	optimizer.optimize(100);

4. 完整代码

g2o_curve_fitting.cpp

//2019.08.09
#include <iostream>

#include <g2o/core/base_vertex.h>
#include <g2o/core/base_unary_edge.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/core/optimization_algorithm_gauss_newton.h>
#include <g2o/core/optimization_algorithm_dogleg.h>
#include <g2o/solvers/dense/linear_solver_dense.h>

#include <Eigen/Core>

#include <opencv2/core/core.hpp>

#include <cmath>
#include <chrono>

using namespace std;




//定义曲线模型的顶点(优化变量),参数模板:优化变量维度和数据类型
class CurveFittingVertex: public g2o::BaseVertex<3,Eigen::Vector3d>
{
public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
	virtual void setToOriginImpl()//重置
	{
		_estimate << 0,0,0;
	}

	virtual void oplusImpl(const double* update)//更新
	{
		_estimate += Eigen::Vector3d(update);
	}

	//存盘和读盘,留空
	virtual bool read(istream& in){}
	virtual bool write(ostream& out) const {}
};

//定义曲线模型的边(误差项) 模板参数:观测值维度,数据类型,连接顶点类型
class CurveFittingEdge: public g2o::BaseUnaryEdge<1,double,CurveFittingVertex>
{
public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
	CurveFittingEdge(double x):BaseUnaryEdge(),_x(x){}
	//计算曲线模型误差
	void computeError()
	{
		const CurveFittingVertex* v = static_cast<const CurveFittingVertex*>(_vertices[0]);
		const Eigen::Vector3d abc = v->estimate();
		_error(0,0) = _measurement - std::exp(abc(0,0)*_x*_x + abc(1,0)*_x + abc(2,0));
	}

	virtual bool read(istream& in) {}
	virtual bool write(ostream& out) const {}

public:
	double _x;//x值,y值为_measurement
};




int main()
{
	double a=1, b=2.0, c=1.0;	//真实参数值
	int N = 100;			//数据点
	double w_sigma = 1.0;		//噪声Sigma(标准差)值
	cv::RNG rng;			//opencv随机数产生器
	double abc[3] = {0,0,0};	//abc参数的估计值,初始值为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;
	}



	//构建图优化,先设定g2o
	//矩阵块,每个误差项优化变量维度为3,误差值维度为1
	typedef g2o::BlockSolver<g2o::BlockSolverTraits<3,1>> Block;
	//线性方程求解器,稠密的增量方程
	Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>();
	Block* solver_ptr = new Block(linearSolver);//矩阵块求解器
	//梯度下降方法,从GN,LM,DogLeg中选
	g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
	//取消下面的注释,以使用GN或DogLeg
	//g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton(solver_ptr);
	//g2o::OptimizationAlgorithmDogleg* solver = new g2o::OptimizationAlgorithmDogleg(solver_ptr);

	g2o::SparseOptimizer optimizer;//图模型
	optimizer.setAlgorithm(solver);//设置求解器
	optimizer.setVerbose(true);//打开调试输出

	//向图中增加顶点
	CurveFittingVertex* v = new CurveFittingVertex();
	v->setEstimate(Eigen::Vector3d(0,0,0));
	v->setId(0);
	optimizer.addVertex(v);

	//向图中增加边
	for(int i=0;i<N;i++)
	{
		CurveFittingEdge* edge = new CurveFittingEdge(x_data[i]);
		edge->setId(i);
		edge->setVertex(0,v);//设置连接的顶点
		edge->setMeasurement(y_data[i]);//观测数值
		//信息矩阵:协防差矩阵的逆
		edge->setInformation(Eigen::Matrix<double,1,1>::Identity()*1/(w_sigma*w_sigma));
		optimizer.addEdge(edge);
		
	}


	//执行优化
	cout<<"start optimization"<<endl;
	chrono::steady_clock::time_point t1 = chrono::steady_clock::now();//开始计时
	optimizer.initializeOptimization();
	optimizer.optimize(100);
	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;

	//输出结果
	Eigen::Vector3d abc_estimate = v->estimate();
	cout<<"estimated model:"<<abc_estimate.transpose()<<endl;


	return 0; 

}

CMakeLists.txt

cmake_minimum_required( VERSION 2.8 )
project( g2o_curve_fitting )

set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

# 添加cmake模块以使用g20库
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )

# 寻找G2O
find_package( G2O REQUIRED )
include_directories( 
    ${G2O_INCLUDE_DIRS}
    "/usr/include/eigen3"
)

# OpenCV
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_DIRS} )

add_executable( curve_fitting g2o_curve_fitting.cpp )
# 与G2O和OpenCV链接
target_link_libraries( curve_fitting 
    ${OpenCV_LIBS}
    g2o_core g2o_stuff
)

运行结果:
在这里插入图片描述在这里插入图片描述

多角度模板匹配的模板创建技巧 基于形状的模板匹配多角度创建技巧 阅读详情

相关推荐

python + QXDM5高通平台通过自动化截取log方法及代码

python + QXDM5高通平台通过自动化截取log方法及代码

dgzj2001的博客 1822

SLAM安装eigen报错: error: no type named ‘Literal’ in ‘struct Eigen::NumTraits<ceres::Jet<double, 9> >’

eigen3编译报错

qq_46107892的博客 1767

工业组态软件Intouch(单机版)入门{第二篇}

第5步:*都装好之后,需要进行测试授权是否生效,测试1:能否正常运行项目和编辑项目(能否编辑项目,取决于你的授权是否包含开发功能,如果只是单一的runtime授权,则只能运行项目,不能编辑项目)。在线第3步:点击第一个框右边的按钮,弹出文件浏览窗口,选中你的XMl授权文件,打开,然后你的授权出现在下方的列表中,勾选你的授权,然后点击Activate,等待几秒,授权就会出现在管理器页面的列表中,并且Status会显示Activated。第1步:软件安装好之后,先要配置好授权服务器。等待几秒,激活完成。

weixin_41571357的博客 1万+

安装ceres出现错误,与eigen3.3发生冲突

错误信息:error: no type named ‘Literal’ in ‘struct Eigen::NumTraits > make[2]: *** [internal/ceres/CMakeFiles/jet_test.dir/jet_test.cc.o] error 1 make[1]: *** [internal/ceres/CMakeFiles/jet_test.dir/all]

wangshuailpp的博客 8056

opencv的cmake报错

1、下载 ippicv_2021.8_win_intel64_20230330_general.zip、v0.1.2a.zip、opencv_videoio_ffmpeg.dll、opencv_videoio_ffmpeg_64.dll、ffmpeg_version.cmake。由于下载源在https://raw.githubusercontent.com,由于网络原因下载不顺畅,可以先找到文件下载到对应文件夹下,或者更改网络环境。ffmpeg_version.cmake文件,打开后显示如下, 另存即可。

nownow_的博客 1299

体验灵雀云-创建基于Docker的云服务

今天体验了一下灵雀云,创建了第一个基于Docker的云服务。 1.登录灵雀云 2.开始使用 登录之后,从"控制台"进入操作界面,开始创建服务。 首先需要选择一个镜像。灵雀云已经为您提供了一些常用的镜像列表。请在“常用镜像”列表中,选择“其它”,然后找到“alauda/hello-world”镜像,点击它右侧的“选择”按钮,进入服务参数配置页面。 选择完要创建的

tomcat的专栏 3236

ubuntu安装ceres库

一、安装相关依赖项 sudo apt-get install liblapack-dev libsuitesparse-dev libcxsparse3.1.2 libgflags-dev libgoogle-glog-dev libgtest-dev 出现无法定位libcxsoarse3.1.2时的解决方法: //第一步,打开sources.list sudo gedit /etc/apt/sources.list //第二步,将下面的源粘贴到最上方sources.list deb http://cz.

weixin_45444802的博客 1518

解决AutoDock与Python版本冲突导致的内存泄漏问题:从BHtree *错误到环境配置优化

本文深入解析了AutoDock分子对接中常见的‘BHtree *’内存泄漏错误,其根源在于SWIG接口模块与Python运行环境的版本不匹配。文章提供了根治方案:通过构建Python 2.5.4与MGLTools 1.5.6的黄金兼容组合,并详细指导环境清理、安装配置及实战测试,从而彻底解决该内存泄漏问题,确保AutoDock工作流的稳定运行。

g5h6i的博客 1116

2021-09-24

安装ceres库,发现与eigen不兼容 报错no type named ‘Literal’ in ‘struct Eigen::NumTraits<ceres::Jet<double, 6> >’ 1.下载eigen库 参考 将eigen库换成3.3.7版本,ceres库换成1.13版本!!!! ROS下编译谷歌CARTOGRAPHER 安装ceres提示“找不到要求版本3.3的Eigen3”解决办法 ...

qq_41818598的博客 562

时空数据建模的跨节点联邦图神经网络:KDD21 Cross-Node Federated Graph Neural Network for Spatio-Temporal Data Modeling

前言 联邦学习(FL)虽然已经被广泛研究,但是对复杂的时空依赖关系进行建模以提高预测能力仍然是一个开放的问题。此外目前最优的时空预测模型假定对数据的访问不受限制,忽略了对数据共享的限制。基于此,本文提了一个基于图联邦学习的时空数据模型 Cross-Node Federated Graph Neural Network (CNFGNN),该模型在跨节点联邦学习的约束下,使用基于图神经网络(GNN)的架构对底层图结构进行编码,属于结构化联邦的一种,每个本地模型利用私有数据进行学习,并保持分散性。CNFGNN

qq_56027260的博客 1810

软考高级-系统架构设计师 知识点整理 (一篇就够了 建议收藏)

软考高级-系统架构设计师知识点整理---十万字总结,助你通过高级

片言可决讼,半纸能缚龙 7356

大型稀疏矩阵求解库SuiteSparse的Cholmod模块的配置使用

大型稀疏矩阵求解库SuiteSparse的Cholmod模块的配置使用

qwe33433的博客 5717

PHP实现SM2算法(附完整源码)

PHP实现SM2算法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 4026

《视觉SLAM十四讲 第二版》笔记及课后习题(第一讲)

前言 之所以想要写这个系列的博客,是因为想要总结一下高博的《SLAM视觉十四讲第二版》的各章内容以及自己对书后习题的一些做法,也算是对自己学习过程的一个总结和回顾。那么,正式开始! 第一讲、预备知识 SLAM 是Simultaneous Localization and Mapping 的缩写,中文译作“同时定位与地图构建”。它是指搭载特定传感器的主体,在没有环境先验信息的情况下,于运动过程中建...

weixin_43619346的博客 4459

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《视觉SLAM十四讲 第二版》笔记及课后习题(第六讲)

读书笔记:非线性优化 在前面几章,我们介绍了经典SLAM 模型的运动方程和观测方程。现在我们已经知 道,方程中的位姿可以由变换矩阵来描述,然后用李代数进行优化。观测方程由相机成像模型给出,其中内参是随相机固定的,而外参则是相机的位姿。于是,我们已经弄清了经典SLAM 模型在视觉情况下的具体表达。 然而,由于噪声的存在,运动方程和观测方程的等式必定不是精确成立的。尽管相机可以非常好地符合针孔模型,但...

weixin_43619346的博客 2986

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

《视觉SLAM十四讲 第二版》笔记及课后习题(第七讲)

读书笔记:视觉里程计1

weixin_43619346的博客 4539

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

《第6讲 非线性优化 》读书笔记

本文是《视觉SLAM十四讲》第6讲的个人读书笔记,为防止后期记忆遗忘写的。 本节知识脉络 对状态估计问题,通过概率论中贝叶斯公式,求解后验概率等价于求解最大似然函数。求解最大似然函数等价于其最小化负对数的求解。通过公式推导,引出最小二乘。问题转换为:求解最大似然,需要求解目标函数最小二乘公式。 最小二乘的求解需要求导,为避免求导数的巨大计算代价,采用下降迭代近似来求解问题。对于 ∆x的确定,...

LWHGMAN的博客 1632

视觉SLAM十四讲 读书编程笔记 Chapter 1&2

视觉SLAM十四讲 读书编程笔记 Chapter 1&21.有线性方程组Ax=b,若已知A,b,需要求解x,该如何求解?这对A和b有哪些要求?2.单目SLAM有哪些特性?3.双目相机有哪些特性?4.整体视觉SLAM流程图5.视觉SLAM流程图的一些理解6.SLAM问题的数学表达 1.有线性方程组Ax=b,若已知A,b,需要求解x,该如何求解?这对A和b有哪些要求? 答:x=A-1b,其中A...

wolfcsharp的博客 899

视觉SLAM十四讲(2):初识SLAM

这一讲主要介绍视觉SLAM的结构,并完成第一个SLAM程序:HelloSLAM。 目录 2.1 小萝卜的例子 单目相机 双目相机 深度相机 2.2 经典视觉SLAM框架 2.3 SLAM问题的数学表述 2.4 编程实践 Hello SLAM 使用cmake 使用库 【高翔】视觉SLAM十四讲 2.1 小萝卜的例子 这一节高翔博士首先介绍了自己组装的“小萝卜”机器人,小萝卜要想具有自主运动的能力,首先要知道自身的姿态,然后是了解外界的环境。这两类问题都需要使用传感器,视觉SL.

10点43的博客 3418

《视觉SLAM十四讲》读书笔记--前八讲

一.初识SLAM 1.单目相机局限性:平移之后才能计算深度以及无法确定真实尺度。 双目相机测量原理:由两个单目相机构成,由两个相机之间的距离-基线估计每个像素的空间位置。基线距离越大测量的越远。 局限性:深度量程和精度受基线和分辨率限制,视差计算量大非常耗资源(主要问题),需GPU和FPGA加速才能实时输出 图像距离信息。 深度...

zhang__shuang_的博客 6560

【读书笔记】《视觉SLAM十四讲(高翔著)》 第9讲

文章目录9.2.1 两两帧的视觉里程计 9.2.1 两两帧的视觉里程计 程序编译运行的方法: 1、测试数据集的准备: 首先下载书P223所推荐的数据集fr1_xyz: 下载网址:https://vision.in.tum.de/data/datasets/rgbd-dataset/download#,选择下载:fr1/xyz 下载之后,将解压后的文件夹放在程序所在路径下。本人放置的路径:/home...

dahailuoa6的博客 978

视觉Slam十四讲读书笔记

视觉Slam十四讲读书笔记 文章目录视觉Slam十四讲读书笔记@[toc]2 初识SLAM2.4 编程基础2.4.2 hello slam2.4.3 cmake编译2.4.4 使用库2.3 SLAM问题的数学表达3 三维空间刚体运动3.1 旋转矩阵3.3 旋转向量和欧拉角3.3.1 旋转向量3.3.2 欧拉角3.4 四元数3.5 相似、仿射、射影4 李群与李代数6 非线性优化6.1 状态估计问题6.1.1 最大后验与最大似然6.1.2 最小二乘法引入6.2 非线性最小二乘6.2.1 一阶二阶梯度6.2.2

weixin_43521275的博客 250

《视觉SLAM十四讲》学习笔记

双目相机:由已知i基线的双单目组成,通过基线(双单目间距)估计各像素空间位置,但配置与标定较为复杂,视差计算耗费资源,深度量程和精度受双目基线和分辨率限制。(1)g++ stoi.cpp -o stoi -std=c++11 使用标准c++11来编译程序, 将stoi.cpp 编译为名为stoi的可执行文件。SLAM问题其实就是状态估计问题,一致运动测量读数u和传感器读数z,求解定位问题和建图问题,对x和y进行估计。功能:主要有O1,O2,O3,Os,分别优化大小,功能,功能,大小。

qq_51164061的博客 557

《视觉SLAM十四讲 第二版》笔记及课后习题(第九讲)

读书笔记:后端1 本讲开始,我们转入SLAM 系统的另一个重要模块:后端优化。 我们看到,前端视觉里程计能给出一个短时间内的轨迹和地图,但由于不可避免的误差累积,这个地图在长时间内是不准确的。所以,在视觉里程计的基础上,我们还希望构建一个尺度、规模更大的优化问题,以考虑长时间内的最优轨迹和地图。不过,考虑到精度与性能的平衡,实际当中存在着许多不同的做法。 ...

weixin_43619346的博客 2495

视觉SLAM十四讲 读书编程笔记 Chapter7 视觉里程计1

Chapter7 视觉里程计1特征点法ORB特征特征匹配实践:特征提取与匹配2D-2D:对极几何对极约束的推导本质矩阵E的求解 特征点法 ORB特征 ORB(Oriented FAST and Rotated BRIEF)特征的关键点是"Oriented FAST",这是一种带有方向信息的FAST角点 ORB的描述子称为BRIEF(Binary Robust Independent Elemen...

wolfcsharp的博客 946

《视觉slam十四讲》阅读笔记及课后习题详解——第一讲

前言 今天开始,开启这一系列博客,记录自己的学习过程。博客大致分为阅读笔记和课后习题。 更新计划: 2020.08.19——2020.08.31:更新第一、二、三、四讲 2020.09.01——2020.09.31:更新第五、六、七讲 2020.10.01——2020.10.31:更新第八、九、十、十一讲 2020.11.01——2020.11.31:更新第十二、十三、十四讲 读书笔记 1.1 主要内容 SLAM: SLAM,全称是Simultaneous Localization and Mapping,

qq_42910179的博客 480
上一篇: 视觉SLAM十四讲 Chapter4 课后练习
下一篇: 视觉SLAM十四讲 读书编程笔记 Chapter10 后端1
Leo-Ma
博客等级 码龄11年 1701粉丝 124原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值