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

Eigen库是一个开源的矩阵运算库,其利用C++模板编程的思想,构造所有矩阵通过传递模板参数形式完成。由于模板类不支持库链接方式编译,而且模板类要求全部写在头文件中,从而导致导致Eigen库只能通过开源的方式供大家使用,并且只需要包含Eigen头文件就能直接使用。
Eigen库中矩阵为其基本数据类型,向量也是一种特殊的矩阵。其所有矩阵数据类型都是由一个 模板类Matrix 生成。
Matrix 类有6个模板参数,现在我们了解前三个足够。剩下的三个参数都有默认值.
Matrix 的三个强制的模板参数:
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
完整模板参数:
Matrix< typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options = 0 , int MaxRowsAtCompileTime = RowsAtCompileTime, int MaxColsAtCompileTime = ColsAtCompileTime>

  • Scalar 就是矩阵元素标量类型。
  • RowsAtCompileTime 和ColsAtCompileTime 分别指代编译时候的行和列值。 
Eigen中提供了许多typedefs ,例如Matrix4f 是4*4的float型矩阵
typedef Matrix<float, 4, 4> Matrix4f;
在Eigen中,vectors 只是一种特殊形式的矩阵,有一行或者一列。在大多数情况下一列比较多,这样的向量也叫做列向量,也简称向量。其他情况叫做行向量。
例如typedef Vector3f 是一个(列)向量,它的定义如下:
typedef Matrix<float, 3, 1> Vector3f;
同样我们也提供了行向量的定义:
typedef Matrix<int, 1, 2> RowVector2i;

动态矩阵和静态矩阵: 动态矩阵是指其大小在运行时确定,静态矩阵是指其大小在编译时确定。
MatrixXd:表示任意大小的元素类型为double的矩阵变量,其大小只有在运行时被赋值之后才能知道。
Matrix3d:表示元素类型为double大小为3*3的矩阵变量,其大小在编译时就知道。
在Eigen中行优先的矩阵会在其名字中包含有row,否则就是列优先。
Eigen中的向量只是一个特殊的矩阵,其维度为1而已。
矩阵类型:Eigen中的矩阵类型一般都是用类似MatrixXXX来表示,可以根据该名字来判断其数据类型, 比如”d”表示double类型,”f”表示float类型,”i”表示整数,”c”表示复数 ;Matrix2f,表示的是一个2*2维的,其每个元素都是float类型。

项目中使用Eigen库

find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})

#include <Eigen/Dense>
数据类型定义在Eigen命名空间下

矩阵构造

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) ;
4)逗号初始化
Eigen::Matrix3f m; m << 1, 2, 3, 4, 5, 6, 7, 8, 9;
矩阵和向量都可以通过逗号分隔方法进行初始化。
注意这种初始化方法只能对确定大小矩阵进行,包括指定行列数的动态矩阵,即下面这种是会出现段错误的:
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、针对向量还提供”[]”操作符,注意矩阵则不可如此使用。

矩阵常用成员函数

当前矩阵的行数、列数、大小可以通过rows()、cols()和size()来获取,对于动态矩阵可以通过resize()函数来动态修改矩阵的大小。注意:(1)、固定大小的矩阵是不能使用resize()来修改矩阵的大小;(2)、resize()函数会析构掉原来的数据,因此调用resize()函数之后将不能保证元素的值不改变;(3)、使用”=”操作符操作动态矩阵时,如果左右两边的矩阵大小不等,则左边的动态矩阵的大小会被修改为右边的大小。
需要特别注意,遍历Eigen矩阵时最好通过rows和cols来限制访问范围,在Eigen中size()其实返回的是rows()*cols()的值,这就意味着如果Eigen矩阵的rows为0的时候,size()就会为0。


矩阵赋值运算符注意事项

赋值是将一个矩阵拷贝进另外一个矩阵,使用操作符=。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 )<<s, 1 , 1 , 1 , 1 ).finished();

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

官网参考:
Eigen矩阵可以实现按列或按行操作:也叫partial reductions
主要利用colwise()和rowwise()实现对矩阵逐列或逐行操作,很重要的一个应用就是得到一个矩阵的行最大值或列最大值:


如果同时想要获得对应最值在矩阵中的索引,可以用:
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] );//行最大



元素读写



猜你喜欢

转载自blog.csdn.net/zhanghm1995/article/details/80709455