Eigen基础函数_基础函数图像及公式

一文学会Eigen库

添加微信:cv3d007,备注:SLAM,拉你入群。文末附行业细分群。

Eigen简介

Eigen:基于线性代数的C ++模板库,主要用于矩阵,向量,数值求解器和相关算法。SLAM中常用的Ceres、G2O等项目均是基于Eigen库。

Eigen库的优点:

  1. 支持整数、浮点数、复数,使用模板编程,可以为特殊的数据结构提供矩阵操作。

  2. OpenCV自带到Eigen的接口。

  3. 支持逐元素、分块、和整体的矩阵操作。

  4. 支持使用Intel MKL加速部分功能。

  5. 支持多线程,对稀疏矩阵支持良好。

  6. 支持常用几何运算,包括旋转矩阵、四元数、矩阵变换、角轴等等。

即使不做SLAM,在3D视觉中,当处理大量数学运算时,我们也会用到Eigen库,它帮我们优化了性能。在安装完成Eigen库后,开始接下来的学习。

数据类型

Eigen库的核心类是 Matrix,由6个参数构成:

Matrix

其中:

  • 前三个参数:需要我们指定

  • 后三个参数:默认即可,无需指定

因为经常需要实例化一些方阵、向量,因此Eigen库也提供了很多直接使用的模板(利用C++的关键字:typedef),例如 Matrix4f 的float型矩阵:

typedef?Matrix?Matrix4f;

还有例如列向量:Vector3f ,其本质也是 Matrix 类:

typedef?Matrix?Vector3f;

行向量RowVector

typedef?Matrix?RowVector2i;

静态-动态-矩阵

  • 静态矩阵:矩阵是静态的,即编译时候就知道运行结果,例如Matrix3d:表示元素类型为double大小为3*3的矩阵变量,其大小在编译时就知道。

  • 动态矩阵:有时候运行完之后,才可以知道,这里使用MatrixXd:表示任意大小的元素类型为double的矩阵变量,其大小只有在运行被赋值之后才能知道;


数据类型

Eigen中的矩阵类型一般都是用类似MatrixNX来表示,可以根据该名字来判断其大小(2,3,4,或X,意思Dynamic)和数据类型,比如:

  • d:表示double类型

  • f:表示float类型

  • i:表示整数

  • c:表示复数;

举例:Matrix2f,表示的是一个维的,其每个元素都是float类型。


新建矩阵

矩阵构造

默认构造,分配了大小和内存空间,但没有初始化矩阵元素(里面的数值是随机的,不能使用):

Matrix3f?a;?//?3*3的元素,其中还有一个float[9]数组,其中的元素没有初始化;MatrixXf?b;?//?动态大小的矩阵,目前的大小是0*0,它的元素数组完全没有分配。

对于动态数组,你也可以直接分配大小(失去作用了),同样没有初始化矩阵元素:

MatrixXf?a(,?);//?10x15动态矩阵,数组内存已经分配,但是没有初始化;VectorXf?b();???//?大小为的向量,数组内存已经分配,但是元素没有初始化。

或者更通用的:

Matrix?Vector3f_def;

矩阵初始化

在构造完后,我们需要对元素进行初始化,常用的是直接赋值:

Eigen::Matrix3f?m;?m?<

它是逐行写入的,这只适用于较小的矩阵:

Eigen::MatrixXd?m(3,3);m?<<1,2,3,?????4,5,6,?????7,8,9;

对于向量,还可以在构造的时候初始化:

Vector3d?v(1,?2,?3);Vector3d?w(1,?0,?0);

还有一些特殊函数,函数:

MatrixXf::Zero(3,4);?????//?将矩阵3行4列初始化为0?MatrixXf::Ones(3,3);?????//?将矩阵3行3列初始化为1?Vector3f::Ones();????????//?将3行的纵向量初始化为1?MatrixXi::Identity(3,3);?//?单位矩阵?Matrix3d::Random();??????//?随机矩阵

矩阵索引

当前矩阵的行数、列数、大小可以通过rows()、cols()和size()来获取。遍历Eigen矩阵时最好通过rows和cols来限制访问范围,索引的方法如下:

1、矩阵访问按照先索引、后索引方式进行,索引下标从0开始(与Matlab不同);

2、矩阵元素的访问可以通过**”( )”操作符完成。例如m(2, 3)**,矩阵m的第2行第3列元素;

3、针对向量还提供”**[ ]”操作符,注意矩阵则不可**如此使用。

resize:不同于matlab、Python,对于动态矩阵虽然可以通过resize()函数来动态修改矩阵的大小,但是需要说明的是,在Eigen中:

  • 不能用:固定大小的矩阵是不能使用resize()来修改矩阵的大小;

  • 数据会变:resize()函数会析构掉原来的数据,变为0.,因此最好使用:conservativeResize()函数

  • 大小修改:使用”=”操作符操作动态矩阵时,如果左右两边的矩阵大小不等,则左边的动态矩阵的大小会被修改为右边的大小。

利用block()函数,可以从Matrix中取出一个小矩阵来进行处理,使用的语法为:

matrix.block(i,j);

例如:

Eigen::MatrixXf?m(4,?4);m?<(1,?1)?<

单独的列和行是块的特殊情况。Eigen提供了可以轻松解决它们的方法:.col()和.row():

Eigen::MatrixXi?m(2,?2);m?<

数学运算

Eigen帮我们重载了,直接运算:

Vector3d?v(1,?2,?3);Vector3d?w(1,?0,?0);cout?<

除法:通常我们是除以标量。对于矩阵除法,我们是求它的逆,再转换为矩阵乘法。因此较为简单:

Vector3d?v(1,?2,?3);Vector3d?r?=?v?/?3;cout?<

矩阵乘法*

乘法,标量非常简单:

cout?<
Matrix2d?mat;mat?<

补充:转置

向量、矩阵的乘法,因为需要size一致,因此需要用到转置:

MatrixXcf?a?=?MatrixXcf::Random(2,?2);?//MatrixXcf?为复数矩阵cout?<

需要说明的是,在Eigen中,对于自身的操作,都有专门的函数,例如对自身的转置:

?a.transposeInPlace();?//?直接在a上操作

点乘和叉乘

Vector3d?v(1,?2,?3);Vector3d?w(0,?1,?2);//?点乘cout?<

在Eigen中,向量的叉乘只支持三维的向量,这是因为叉乘通常用于计算方向、夹角等,它的计算规则如下:

//?Eigen?also?provides?some?reduction?operations?to?reduce?a?given?matrix?or?vector?to?a?single?value//?such?as?the?sum?(computed?by?sum()),?product?(prod()),?or?the?maximum?(maxCoeff())?and?minimum?(minCoeff())?of?all?its?coefficients.Eigen::Matrix2d?mat;mat?<

通用数组

Array类提供了通用数组。此外,Array类提供了一种执行逐系数运算的简便方法,该运算可能没有线性代数含义,例如将常数添加到数组中的每个系数或按系数乘两个数组。

注:Eigen计算三角函数等,Matrix并不支持,需要通过.array() 转换到Array类,再计算!

m1.array().atan();

常见数据类型

Array???????????????????ArrayXfArray?????????????????????????Array3fArray????????????ArrayXXdArray????????????????????????Array

常见操作:

//?逐元素操作Vectorized?operations?on?each?element?independently??//?Eigen???????????????????????//?Matlab????????//注释??R?=?P.cwiseProduct(Q);?????????//?R?=?P?.*?Q????//逐元素乘法??R?=?P.array()?*?s.array();?????//?R?=?P?.*?s????//逐元素乘法(s为标量)??R?=?P.cwiseQuotient(Q);????????//?R?=?P?./?Q????//逐元素除法??R?=?P.array()?/?Q.array();?????//?R?=?P?./?Q????//逐元素除法??R?=?P.array()?+?s.array();?????//?R?=?P?+?s?????//逐元素加法(s为标量)??R?=?P.array()?-?s.array();?????//?R?=?P?-?s?????//逐元素减法(s为标量)??R.array()?+=?s;????????????????//?R?=?R?+?s?????//逐元素加法(s为标量)??R.array()?-=?s;????????????????//?R?=?R?-?s?????//逐元素减法(s为标量)??R.array()?

更多操作

对于Eigen,它适合一个简单的数值计算库,并没有什么实用技巧。其实大多数时候,你只需要利用Google和百度去查询你需要的操作即可!对于更多的操作,可以参考:Eigen 常用函数查询,对比MatLab操作 。

—END—

目前工坊已经建立了3D视觉方向多个社群,包括SLAM、工业3D视觉、自动驾驶方向,细分群包括:[工业方向]三维点云、结构光、机械臂、缺陷检测、三维测量、TOF、相机标定、综合群;[SLAM方向]多传感器融合、ORB-SLAM、激光SLAM、机器人导航、RTK|GPS|UWB等传感器交流群、SLAM综合讨论群;[自动驾驶方向]深度估计、Transformer、毫米波|激光雷达|视觉摄像头传感器讨论群、多传感器标定、自动驾驶综合群等。[三维重建方向]NeRF、colmap、OpenMVS等。除了这些,还有求职、硬件选型、视觉产品落地等交流群。大家可以添加小助理微信: cv3d007,备注:加群+方向+学校|公司, 小助理会拉你入群。

原文链接:,转发请注明来源!