[Eigen] 2-Matrix类

Matrix 类

在Eigen里,所有的矩阵及向量都是Matrix模板类的对象。向量仅仅是一种特殊的矩阵,拥有一行或者一列。

Matrix类的前三个模板参数

Matrix模板类有六个模板参数,但是目前,我们仅需要了解前三个参数。
前三个必须的参数是:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
  • Scalar 是数据类型,比如说,你想创建一个float类型元素的矩阵,那么这里就该选float。
  • RowsAtCompileTime 与 ColsAtCompileTime 是在编译时期所能确定的行数及列数。(后续会介绍如果不能在编译时确实大小的情况)

也提供了一些常用的类型定义,比如,Matrix4f 是4*4 的float类型的矩阵,定义如下:

typedef Matrix<float, 4, 4> Matrix4f;

向量

最常用的是列向量,当然也有行向量。举例:

  • Vector3f 是一个拥有3个float类型数据的列向量:
    Eigen里的定义:
typedef Matrix<float, 3, 1> Vector3f;
  • 行向量:
typedef Matrix<int, 1, 2> RowVector2i;

特殊值 Dynamic

当然,Eigen不会局限于在编译时期就确定矩阵的大小。RowsAtCompileTime 与 ColsAtCompileTime模板参数可以取一个特殊值 Dynamic,表面在编译时期是不知道矩阵的大小的,在运行时才处理。这叫动态大小,与之对应的在编译期确定的叫固定大小。例如,MatrixXd意味着这是一个动态大小的double类型的矩阵:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

又或者,VectorXi:

typedef Matrix<int, Dynamic, 1> VectorXi;

当然你也可以固定行的数量,让列取动态值,如:

Matrix<float, 3, Dynamic>

构造函数

Matrix模板类提供默认构造函数,但是不分配内存,也不初始化元素,如:

Matrix3f a;
MatrixXf b;
  • a是一个3*3的矩阵,如同float[9]数组,元素都未初始化
  • b是一个动态大小的矩阵,当前的大小为0*0,元素均未分配。

带有大小参数的构造函数也是可以的。对于矩阵,行的大小数量是先传递的,对于向量,仅需要给出向量的大小,他们会申请分配对应的内存,但是不初始化。

MatrixXf a(10,15);
VectorXf b(30);
  • a是一个10*15大小的动态数组,已经分配内存,未初始化。
  • b是一个大小为30的向量,已分配内存,未初始化。

为了使固定大小与动态大小矩阵的API一致,像如下的对固定大小矩阵的构造也是允许的,但其实是无效操作。

Matrix3f a(3,3);

最后,也提供了一些初始化元素的构造函数,向量固定大小最多到4:

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

元素访问

Eigen中最主要的访问元素的方式是通过重载的()圆括号。对于矩阵,行标首先传递,对于向量,仅需要给一个索引,均是从0开始,如下:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  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 << "Here is the matrix m:\n" << m << std::endl;
  VectorXd v(2);
  v(0) = 4;
  v(1) = v(0) - 1;
  std::cout << "Here is the vector v:\n" << v << std::endl;
}

输出如下:

Here is the matrix m:
  3  -1
2.5 1.5
Here is the vector v:
4
3

对于向量来说,[ ]也是可以的,但是记住,C++不允许[ ]里的参数超过一个。

逗号初始化

下面的例子足以说明:

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

输出:

1 2 3
4 5 6
7 8 9

改变大小(Resizing)

当前矩阵的大小可以通过 rows(), cols(), size() 函数获得,分别返回行数,列数,总元素个数。对一个动态矩阵重新分配大小可以用resize()方法。

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  MatrixXd m(2,5);
  m.resize(4,3);
  std::cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
  std::cout << "It has " << m.size() << " coefficients" << std::endl;
  VectorXd v(2);
  v.resize(5);
  std::cout << "The vector v is of size " << v.size() << std::endl;
  std::cout << "As a matrix, v is of size "
            << v.rows() << "x" << v.cols() << std::endl;
}

输出为:

The matrix m is of size 4x3
It has 12 coefficients
The vector v is of size 5
As a matrix, v is of size 5x1

resize()方法在实际矩阵的大小未发生变化时,是一个无效操作。否则,它是具有破坏性的,矩阵元素的值会发生改变。如果你想保留原来的元素值,参见conservativeResize()方法。

上述的方法对固定大小的矩阵仍然有效。当然,实际上是不能改变一个固定大小的矩阵的。下面的代码仍然可以运行:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  Matrix4d m;
  m.resize(4,4); // no operation
  std::cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
}

输出:

The matrix m is of size 4x4

赋值与改变大小

用等号=可以完成赋值操作,把一个矩阵拷贝给另一个。并且会将=号左边的矩阵重新分配大小,依据的是等号=右边的矩阵。如:

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 is of size 2x2
a is now of size 3x3

当然,如果等号左侧的矩阵的固定大小,则重新分配大小是不允许的。

固定大小与动态大小

一个疑问,何时使用固定大小(Matrix4f),何时使用动态大小的矩阵(MatrixXf)?答案很简单,当矩阵较小时,使用固定大小的;当矩阵较大或者确实需要时,使用动态大小的矩阵。对于较小的矩阵,尤其是少于16大小的矩阵,使用固定大小性能将会更优秀。一个固定大小的矩阵,实际上就是一个一维数组,如:

Matrix4f mymatrix;

实际上就如同:

float mymatrix[16];

相反的,动态大小的矩阵,其内存分配是在堆上,如:

MatrixXf mymatrix(rows,columns); 

如同:

float *mymatrix = new float[rows*columns]; 

此外,MatrixXf对象将行与列的数目作为成员变量存储起来了。

固定大小矩阵的不足之处是,你在编译时就得确定矩阵的大小。尤其是在矩阵的大小超过32时,固定大小矩阵的性能的优越性就微不足道了。更糟糕的是,尝试用固定大小的矩阵来定义一个特别大的矩阵时,可能会引起栈溢出。

其他模板参数

我们前面提到,Matrix类有6个模板参数,之前讨论了前三个。剩下的三个是可选参数。完整的参数如下:

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>
  • Option是一个位字段。我们只讨论一个位:行优先。它指定了这种类型的矩阵以行优先存储。默认的是列优先。
  • MaxRowsAtCompileTime 与 MaxColsAtCompileTime 在需要时可以使用。尽管在编译时,矩阵的实际大小未知,但是上限值可以指定。如下的定义可以避免动态内存分配:
Matrix<float, Dynamic, Dynamic, 0, 3, 4>

内部一些类型定义

Eigen定义了如下的类型:

  • MatrixNt: Matrix<type, N, N>。如:MatrixXi表示的是:Matrix<int, Dynamic, Dynamic>。
  • VectorNt:Matrix<type, N, 1>。 如:Vector2f 表示: Matrix<float, 2, 1>.
  • RowVectorNt:Matrix<type, 1, N>。如: RowVector3d 表示的是: Matrix<double, 1, 3>.
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值