Eigen(1)-The Matrix class(矩阵类)

点击这里开始进入Eigen官网

参考Eigen官网叙述

ps:老老实实的看文档,才能熟悉和了解一个库…

Eigen Matrix 简述

在Eigen中,所有的matrices 和vectors 都是模板类Matrix 的对象,Vectors 只是一种特殊的矩阵,行或者列的数目为1.

  • Matrix的前三个模板参数,Matrix 类有6个模板参数,现在我们了解前三个足够。剩下的三个参数都有默认值。
1.Matrix 类

它的三个必备的模板参数:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
  • Scalar 就是矩阵元素的标量类型
  • RowsAtCompileTime 和ColsAtCompileTime 分别指代矩阵的矩阵的行数和列数
  Eigen中提供了许多typedefs ,例如Matrix4f 是4*4的float型矩阵:
  typedef Matrix<float, 4, 4> Matrix4f;
2.Vectors向量

在Eigen中,vectors 只是一种特殊形式的矩阵,有一行或者一列。
只有一列向量也叫做列向量,也简称向量
只有一行的向量叫做行向量,简称行向量

例如typedef Vector3f 是一个(列)向量,它的定义如下:
typedef Matrix<float, 3, 1> Vector3f;
同样我们也提供了行向量的定义:
typedef Matrix<int, 1, 2> RowVector2i;

在Eigen中提供的简化定义形式:

typedef Matrix< double , 3 , 1> Vector3d
特殊值 Dynamic

Eigen不只限于已知大小(编译阶段)的矩阵,有些矩阵的尺寸是运行时确定的,于是引入了一个特殊的标识符:Dynamic

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

typedef Matrix<int, Dynamic, 1> VectorXi;

Matrix<float, 3, Dynamic>
4.构造函数

默认的构造函数不执行任何空间分配,也不初始化矩阵的元素。

Matrix3f a;
MatrixXf b;

这里,a是一个33的矩阵,分配了float[9]的空间,但未初始化内部元素;b是一个动态大小的矩阵,定义是未分配空间(00)。
指定大小的矩阵,只是分配相应大小的空间,未初始化元素。

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

这里,a是一个10*15的动态大小的矩阵,分配了空间但未初始化元素;b是一个30大小的向量,同样分配空间未初始化元素。
为了对固定大小和动态大小的矩阵提供统一的API,对指定大小的Matrix传递sizes也是合法的(传递也被忽略)

Matrix3f a(3,3);

可以用构造函数提供4以内尺寸的vector的初始化。

注意:
(1)Eigen中无论是矩阵还是数组、向量,无论是静态矩阵还是动态矩阵都提供默认构造函数,也就是你定义这些数据结构时都可以不用提供任何参数,其大小均由运行时来确定。
(2)矩阵的构造函数中只提供行列数、元素类型的构造参数,而不提供元素值的构造,对于比较小的、固定长度的向量提供初始化元素的定义,例如:

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);
5.获取元素

在矩阵的访问中,行索引总是作为第一个参数,需注意Eigen中遵循大家的习惯让矩阵、数组、向量的下标都是从0开始。矩阵元素的访问可以通过()操作符完成,例如m(2,3)即是获取矩阵m的第2行第3列元素(注意行列数从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
6.逗号初始化

在Eigen中重载了"<<"操作符,通过该操作符即可以一个一个元素的进行赋值,也可以一块一块的赋值。另外也可以使用下标进行复制,例如下面两段代码:
<1>

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

输出:

1 2 3
4 5 6
7 8 9

<2>(使用下标进行赋值)

VectorXf m_Vector_A;
MatrixXf m_matrix_B;
int m_iN =-1;
 
bool InitData(int pSrc[100][100], int iWidth, int iHeight)
{
	if (NULL == pSrc || iWidth <=0 || iHeight <= 0)
		return false;
	m_iN = iWidth*iHeight;
	VectorXf tmp_A(m_iN);
	MatrixXf tmp_B(m_iN, 5);
	int i =0, j=0, iPos =0;
	while(i<iWidth)
	{
		 j=0;
		while(j<iHeight)
		{
			tmp_A(iPos) = pSrc[i][j] * log((float)pSrc[i][j]);
			tmp_B(iPos,0) = pSrc[i][j] ;
			tmp_B(iPos,1) = pSrc[i][j] * i;
			tmp_B(iPos,2) = pSrc[i][j] * j;
			tmp_B(iPos,3) = pSrc[i][j] * i * i;
			tmp_B(iPos,4) = pSrc[i][j] * j * j;
			++iPos;
			++j;
		}
		++i;
	}
	m_Vector_A = tmp_A;
	m_matrix_B = tmp_B;
}
7.重置大小

当前矩阵的行数、列数、大小可以通过rows(),cols()和size()来获取,对于动态矩阵可以通过resize()函数来动态修改矩阵的大小.
需注意:
(1) 固定大小的矩阵是不能使用resize()来修改矩阵的大小;
(2) resize()函数会析构掉原来的数据,因此调用resize()函数之后将不能保证元素的值不改变。
(3) 使用“=”操作符操作动态矩阵时,如果左右边的矩阵大小不等,则左边的动态矩阵的大小会被修改为右边的大小。例如下面的代码段:


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

如果matrix的实际大小不改变,resize函数不做任何操作。resize操作会执行析构函数:元素的值会被改变,如果不想改变执行 conservativeResize()。
为了统一API,所有的操作可用于指定大小的matrix,当然,实际中它不会改变大小。尝试去改变一个固定大小的matrix到一个不同的值,会出发警告失败。只有如下是合法的。

#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;
}
8.分配和重置大小

assignment(分配)是复制一个矩阵到另外一个,操作符=。Eigen会自动resize左变量大小等于右变量大小,比如:

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;
9.静态矩阵vs动态矩阵

Eigen对于这问题的答案是:对于小矩阵(一般大小小于16)的使用固定大小的静态矩阵,它可以带来比较高的效率,对于大矩阵(一般大小大于32)建议使用动态矩阵。
还需特别注意的是:如果特别大的矩阵使用了固定大小的静态矩阵则可能造成栈溢出的问题

10.其他模板参数选项
Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>

Options是一个比特标志位,这里,我们只介绍一种RowMajor,它表明matrix使用按行存储,默认是按列存储。Matrix<float, 3, 3, RowMajor>
MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。主要是避免动态内存分配,使用数组。
Matrix<float, Dynamic, Dynamic, 0, 3, 4> 等价于 float [12]

11.一些方便的定义

Eigen定义了一些类型

MatrixNt = Matrix<type, N, N>
For example, MatrxXi = Matrix<int, Dynamic, Dynamic>

VectorNt = Matrix<type, N, 1>
For example,Vector2f = Matrix<float, 2, 1>

RowVectorNt = Matrix<type, 1, N>
For example, RowVector3d = Matrix<double, 1, 3>
N可以是2,3,4或X(Dynamic)
t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值