Eigen入门之密集矩阵 1 -- 类Matrix介绍

Prunella ·
更新时间:2024-11-10
· 635 次阅读

简介 本篇介绍Eigen中的Matrix类。在Eigen中,矩阵和向量的类型都用Matrix来表示。向量是一种特殊的矩阵,其只有一行或者一列。 Matrix构造

Matrix.h中,定义了Matrix类,
其中的构造器包括如下的5个,可以看到定义Vector也是使用Matrix。

/** \brief Constructs a fixed-sized matrix initialized with coefficients starting at \a data */ EIGEN_DEVICE_FUNC explicit Matrix(const Scalar *data); /** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors * * This is useful for dynamic-size vectors. For fixed-size vectors, * it is redundant to pass these parameters, so one should use the default constructor * Matrix() instead. * * \warning This constructor is disabled for fixed-size \c 1x1 matrices. For instance, * calling Matrix(1) will call the initialization constructor: Matrix(const Scalar&). * For fixed-size \c 1x1 matrices it is therefore recommended to use the default * constructor Matrix() instead, especially when using one of the non standard * \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives). */ EIGEN_STRONG_INLINE explicit Matrix(Index dim); /** \brief Constructs an initialized 1x1 matrix with the given coefficient */ Matrix(const Scalar& x); /** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns. * * This is useful for dynamic-size matrices. For fixed-size matrices, * it is redundant to pass these parameters, so one should use the default constructor * Matrix() instead. * * \warning This constructor is disabled for fixed-size \c 1x2 and \c 2x1 vectors. For instance, * calling Matrix2f(2,1) will call the initialization constructor: Matrix(const Scalar& x, const Scalar& y). * For fixed-size \c 1x2 or \c 2x1 vectors it is therefore recommended to use the default * constructor Matrix() instead, especially when using one of the non standard * \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives). */ EIGEN_DEVICE_FUNC Matrix(Index rows, Index cols); /** \brief Constructs an initialized 2D vector with given coefficients */ Matrix(const Scalar& x, const Scalar& y); //...... 简化Matrix和Vector定义

还有使用macro定义的一些简化类名定义,用于固定column 或者Row的方阵,以及向量。比如在一些项目中看到的 Matrix3f, Matrix4i, Vector4f……。

这些macro如下:

#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ /** \ingroup matrixtypedefs */ \ typedef Matrix Matrix##SizeSuffix##TypeSuffix; \ /** \ingroup matrixtypedefs */ \ typedef Matrix Vector##SizeSuffix##TypeSuffix; \ /** \ingroup matrixtypedefs */ \ typedef Matrix RowVector##SizeSuffix##TypeSuffix; #define EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \ /** \ingroup matrixtypedefs */ \ typedef Matrix Matrix##Size##X##TypeSuffix; \ /** \ingroup matrixtypedefs */ \ typedef Matrix Matrix##X##Size##TypeSuffix;

如上的定义,则有:

// 定义一个浮点型的4X4的方阵类型。 typedef Matrix Matrix4f; // 定义一个浮点型的3行的列向量类型。 typedef Matrix Vector3f; // 定义一个整形的长度为2的行向量类型。 typedef Matrix RowVector2i; 特殊值 Dynamic

上面都是固定大小的矩阵或者向量。Eigen不仅支持在编译时指定了维度的矩阵Matrix,而且支持使用一个特殊值Dynamic来指定Rows或(和)Columns,指示编译时大小并不知道。而在运行时,才会真正地处理其大小尺寸。

template class Matrix : public PlainObjectBase<Matrix >

就如上面固定大小的矩阵,有其简化定义形式。Dynamic指示的非固定的Matrix也有简化定义形式。如:

// 定义一个double型的,行数和列数均编译时未知的Matrix。 typedef Matrix MatrixXd; // 定义一个向量,但编译时还不知道其长度。 typedef Matrix VectorXi;

当然行数或者列数可以知道其中之一。如下:

Matrix matrixA; Matrix matrixB; 示例

如下示例,使用构造器定义一下Matrix

使用默认构造器

这时,不会执行内存分配,也不会初始化矩阵参数,仅定义了一个Matrix变量。

Matrix3f a; MatrixXf b; 构造器指定大小尺寸

此时,指定了大小,将分配内存空间,但是并不初始化各个矩阵或者向量参数。

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

Eigen中提到,为统一固定大小或者Dynamic类型的Matrix的定义,可以在构造器参数中指定大小值,但这些值可能并不需要,也没有用处。比如:

// 这里构造器上的rows =3, columns = 3并不需要 Matrix3f a(3,3); 指定Matrix系数的构造器

对具有较少系数的Matrix,可以在构造时指定这些系数。比如:

// 定义具有长度为2的整形向量 Vector2i a(5, 6); // 定义具有长度为3的double型向量 Vector3d b(5.0, 6.0, 7.0); // 定义具有长度为4的浮点向量 Vector4f c(5.0, 6.0, 7.0, 8.0); 对Matrix的系数访问

在使用Matrix或者Vector时,一定要有系数Coefficient。如何操作/访问这些系数呢?

Matrix类重载了括号操作符(),提供对系数的访问。针对矩阵,参数为(row, column),而针对Vector,则只有一个参数index了。这些参数都是以0作为起始的整数。

注意:
对矩阵访问,单个参数也是允许的,但其操作是按照矩阵的系数数组来进行操作的。而这会有个内存存储顺序的问题,Eigen按照Column为主的顺序进行存储,但可以更改设置,变为以Row为主序。

如有有源程序 matrix_1.cpp:

#include #include using namespace Eigen; int main() { // 定义matrix MatrixXd m(2,2); m(0,0) = 3; m(1,0) = 2.5; m(0,1) = -1; m(1,1) = m(1,0) + m(0,1); std::cout << "The matrix m:\n" << m << std::endl; std::cout << "The matrix m(1):\n" << m(1) << std::endl; // 定义vector VectorXd v(2); v(0) = 4; v(1) = v(0) - 1; std::cout << "The vector v:\n" << v << std::endl; }

编译:

$ g++ matrix_1.cpp -o matrix_1 -I /usr/local/include/eigen3 $

输出:

$ ls matrix_1 The matrix m: 3 -1 2.5 1.5 The matrix m(1): 2.5 The vector v: 4 3 初始化: Comma_initializtion

在Eigen内,使用comma-initializer的语法来进行matrix、vector的初始化。

**注意:**使用comma-initializer来初始化matrix时,是以row为主序来进行输入的。这和上面提到的访问时的顺序可能不一致。
如下的示例:

// matrix_2.cpp #include #include using namespace Eigen; int main() { // 定义matrix Matrix3f m; m << 1, 2, 3, 4, 5, 6, 7, 8, 9; std::cout << "The matrix m:\n" << m << std::endl; // 定义vector VectorXd v(2); v<< 1,2; std::cout << "The vector v:\n" << v << std::endl; }

编译一下,执行后,可以看到结果。

$ g++ matrix_2.cpp -o matrix_2 -I /usr/local/include/eigen3 $ ./matrix_2 The matrix m: 1 2 3 4 5 6 7 8 9 The vector v: 1 2 size及赋值

对一个matrix的row,column数量的访问,Eigen中的Matrix提供了row(), columns(), size()函数。

Matrix m; std::cout << "rows: " << m.rows() ; // rows: 4 std::cout << "columns: " << m.cols() << std::endl; // columns: 3 std::cout << "It has " << m.size() << " coefficients" << std::endl; // It has 12 coefficients

对一个Matrix的大小可以使用resize(int rows,int columns)来修改其大小。

Matrix m;

可以把一个Matrix/Vector变量赋值给另一个对应的变量,而对他们的Size并没有限制,如:

Matrix4d md4; Matrix2f mf2; mf2 = md4; mf2.size(); resize & conservativeResize

只有Dynamic类型的Matrix可以改变大小。固定大小的matrix调用resize,执行时也会出错。

MatrixXf a(2,2); a.resize(5,5);

resize()一个matrix,可以想象,其系数可能会发生变化,所以此函数是有破坏性的。Eigen中还提供了conservativeResize()函数,用于保护其系数。

对比 fixed、Dynamic对matrix的大小影响

有这样一个问题: 我们应该使用固定大小的matrix、还是选择使用不固定的Dynamic大小的matrix呢?Eigen官方对此问题的答案是: 如果你的matrix尺寸大小很小,不超过16,就使用固定尺寸的,否则使用浮动的不固定尺寸的matrix。固定大小尺寸的matrix有性能上的极大优势。因为在内部实现上,固定尺寸大小的matrix简单地使用了数组Array来管理系数。而使用Dynamic的matrix,会使用动态内存分配,而且存在系数访问时的展开位计算。

比如:Matrix4f mymatrix;就相当于float mymatrix[16];;而MatrixXf mymatrix(rows,columns); 相当于float *mymatrix = new float[rows*columns];

可选构造器参数

模板类Matrix,保护了6个参数,后3个参数具有缺省的参数,如下:

Matrix Options参数
这个参数使用使用bit为标识的一些选项。这里只介绍一下最重要的RowMajor,其标识Matrix使用行优先策略来存储系数数据。缺省下,其值为0,为列优先(column-major)策略。 MaxRowsAtCompileTime 和 MaxColsAtCompileTime
在你不知道matrix具体大小时,但知道你大小的最大尺寸,使用此参数来指定编译时其最大值。如果合适,Eigen会创建固定尺寸大小的Matrix来替代。 简化Matrix类名

在第一篇中,介绍了使用Macro定义了一些简化Matrix类型和类名。

MatrixNt --> Matrix. 比如: MatrixXi 即为 Matrix. VectorNt --> Matrix. 比如: Vector2f 即为 Matrix. RowVectorNt --> Matrix. 比如: RowVector3d 即为 Matrix.

这里的

N 表示数量,可以1,2,3……,或者代表Dynamic的不固定大小的X t 表示系数的数据类型,可以是 i(int), f(float), d(double), cf(complex) cd(complex)
作者:whereismatrix



matrix eigen 矩阵

需要 登录 后方可回复, 如果你还没有账号请 注册新账号