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