Eigen矩阵运算开源库使用完全指南

Eigen库是一个开源的矩阵运算库,其利用C++模板编程的思想,构造所有矩阵通过传递模板参数形式完成。由于模板类不支持库链接方式编译,而且模板类要求全部写在头文件中,从而导致导致Eigen库只能通过开源的方式供大家使用,并且只需要包含Eigen头文件就能直接使用。

Eigen库中矩阵为其基本数据类型,向量也是一种特殊的矩阵。其所有矩阵数据类型都是由一个模板类Matrix生成。

Matrix 类有6个模板参数,现在我们了解前三个足够。剩下的三个参数都有默认值.

Matrix 的三个强制的模板参数:

Matrix

 完整模板参数:

Matrix
  • Scalar 就是矩阵元素标量类型。
  • RowsAtCompileTime 和ColsAtCompileTime 分别指代编译时候的行和列值。 

Eigen中提供了许多typedefs ,例如Matrix4f 是4*4的float型矩阵

typedef Matrix Matrix4f;

在Eigen中,vectors 只是一种特殊形式的矩阵,有一行或者一列。在大多数情况下一列比较多,这样的向量也叫做列向量,也简称向量。其他情况叫做行向量。

例如typedef Vector3f 是一个(列)向量,它的定义如下:

typedef Matrix Vector3f;

同样我们也提供了行向量的定义:

typedef Matrix RowVector2i;

https://blog.csdn.net/sn_gis/article/details/79015488

动态矩阵和静态矩阵:动态矩阵是指其大小在运行时确定,静态矩阵是指其大小在编译时确定。

MatrixXd:表示任意大小的元素类型为double的矩阵变量,其大小只有在运行时被赋值之后才能知道。

Matrix3d:表示元素类型为double大小为3*3的矩阵变量,其大小在编译时就知道。

在Eigen中行优先的矩阵会在其名字中包含有row,否则就是列优先。

Eigen中的向量只是一个特殊的矩阵,其维度为1而已。

矩阵类型:Eigen中的矩阵类型一般都是用类似MatrixXXX来表示,可以根据该名字来判断其数据类型,比如”d”表示double类型,”f”表示float类型,”i”表示整数,”c”表示复数;Matrix2f,表示的是一个2*2维的,其每个元素都是float类型。

 

项目中使用Eigen库

CMakeLists.txt中写法:

# CMakeLists.txt
find_package(Eigen3 REQUIRED)

include_directories(${EIGEN3_INCLUDE_DIR})

头文件包含写法:

数据类型定义在Eigen命名空间下:

// main.cpp
#include 

矩阵构造


1)默认构造:不会进行动态内存分配,也不会初始化矩阵元素

Matrix3f a;
MatrixXf b;

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

2)指定行数列数构造:分配元素数组,不初始化元素

MatrixXf a(10,15);
VectorXf b(30);

这里,a是10x15动态矩阵,数组内存已经分配,但是没有初始化;b是一个大小为30的向量,数组内存已经分配,但是元素没有初始化。 

3)向量简单初始构造

对于比较小的、固定长度的向量提供直接构造元素方式。

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);
RowVector4d c(5.0, 6.0, 7.0, 8.0);

4)逗号初始化

矩阵和向量都可以通过逗号分隔方法进行初始化。

Eigen::Matrix3f m;
m << 1, 2, 3, 
     4, 5, 6, 
     7, 8, 9;

Eigen::VectorXd v(3);
v << 1,
     2,
     3;

注意这种初始化方法只能对确定大小矩阵进行,包括指定行列数的动态矩阵,即下面这种是会出现段错误的:

Eigen::MatrixXd m;

m <<1,2,3,

4,5,6,

7,8,9;

而下面这种构造方法可以

Eigen::MatrixXd m(3,3);

m <<1,2,3,

4,5,6,

7,8,9;

5)常用矩阵

MatrixXf::Zero(3,4); // 将矩阵3行4列初始化为0

MatrixXf::Ones(3,3); // 将矩阵3行3列初始化为1

Vector3f::Ones(); // 将3行的纵向量初始化为1

MatrixXi::Identity(3,3); //单位阵

Matrix3d::Random();//随机矩阵

注意对动态矩阵进行初始化的时候,必须指定行数和列数。

6)矩阵特定初始化

// 矩阵全部元素置0 

m1.setZero(); 

// 随机生成一个矩阵 

m1.setRandom(); 

// 置单位矩阵 

m1.setIdentity(3,3);

// 矩阵求逆 

m1.inverse(); 

// 矩阵转置 

m1.transpose(); 

 

矩阵元素的访问


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

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

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

 

矩阵常用成员函数


1、矩阵的行数、列数、大小(即行数与列数的乘积)可以通过rows()、cols()和size()来获取;

需要特别注意,遍历Eigen矩阵时最好通过rows和cols来限制访问范围,在Eigen中size()其实返回的是rows()*cols()的值,这就意味着如果Eigen矩阵的rows为0的时候,size()就会为0。

2、对于动态矩阵可以通过resize()函数来动态修改矩阵的大小。

注意:(1)、固定大小的矩阵是不能使用resize()来修改矩阵的大小;(2)、resize()函数会析构掉原来的数据,因此调用resize()函数之后将不能保证元素的值不改变;(3)、使用”=”操作符操作动态矩阵时,如果左右两边的矩阵大小不等,则左边的动态矩阵的大小会被修改为右边的大小。

 

矩阵赋值运算符注意事项


赋值是将一个矩阵拷贝进另外一个矩阵,使用操作符=。Eigen 会自动跳转左面元素的大小,从而使得它和右侧元素匹配。例如:

MatrixXf a(2,2);
std::cout << "a is of size " << a.rows() << "x" << a.cols() << std::endl;

MatrixXf b(3,3);
a = b;
std::cout << "a is now of size " << a.rows() << "x" << a.cols() << std::endl;

a原先大小 2x2 

a现在大小 3x3 

当然,如果左侧是固定大小的矩阵,那么改变大小是不允许的。 

如果你不需要这种自动调整大小,你可以将他关闭。

 

实用操作总结

给一个已经存在的矩阵后面增加一行:

MatrixXf s(3,4);

s<<1,2,3,4,

5,6,7,8,

9,10,11,12;

s = (MatrixXf(4,4)<

矩阵部分操作(感兴趣部分操作)


官网参考:

http://eigen.tuxfamily.org/dox/group__TutorialReductionsVisitorsBroadcasting.html#TutorialReductionsVisitorsBroadcastingPartialReductions

Eigen矩阵可以实现按列或按行操作:也叫partial reductions

主要利用colwise()和rowwise()实现对矩阵逐列或逐行操作,很重要的一个应用就是得到一个矩阵的行最大值或列最大值:

 

Eigen矩阵运算开源库使用完全指南_第1张图片

Eigen矩阵运算开源库使用完全指南_第2张图片

如果同时想要获得对应最值在矩阵中的索引,可以用:

Eigen::MatrixXf mat(2,4);

mat << 1, 2, 6, 9,

3, 1, 7, 2;

Eigen::VectorXi maxIndices;

Eigen::VectorXf maxVals;

MatrixXf::Index maxIndex[2];//存储对应索引

VectorXf maxVal(2);//存储最大值

for(int i=0;i<2;++i)

maxVal(i) = mat.row(i).maxCoeff( &maxIndex[i] );//行最大

元素读写


Eigen矩阵运算开源库使用完全指南_第3张图片

 

你可能感兴趣的:(常用库)