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列初始化为0MatrixXf::Ones(3,3); // 将矩阵3行3列初始化为1Vector3f::Ones(); // 将3行的纵向量初始化为1MatrixXi::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矩阵运算开源库使用完全指南
文章图片

Eigen矩阵运算开源库使用完全指南
文章图片

如果同时想要获得对应最值在矩阵中的索引,可以用:
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矩阵运算开源库使用完全指南
文章图片

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

    推荐阅读