Eigen學習筆記(2)-Matrix類

原文:Eigen官網-The Matrix class

在Eigen中,所有的矩陣Matrix和向量Vector都是由Matrix類構造的。向量只不過是矩陣的特殊形式,只有一列(列向量)或者一行(行向量)。

Matrix類的參數

Matrix有6個模板參數,主要使用前三個參數,剩下的三個參數有默認值。

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
  • Scalar是表示元素的類型,取值可以是 float ,int, double 等;
  • RowsAtCompileTime爲矩陣的行,在程序編譯的時候就已經知道的;
  • ColsAtCompileTime爲矩陣的列,在程序編譯的時候就已經知道的。

Eigen 提供了一些常用的 定義好的類型。比如,Matrix4f表示一個類型爲float的4*4矩陣,在Eigen中定義如下:

typedef Matrix<float, 4, 4> Matrix4f;

Vectors向量

列向量是默認向量。
Eigen中定義的包含3個float元素的列向量如下:

typedef Matrix<float, 3, 1> Vector3f;

行向量定義如下:

typedef Matrix<int, 1, 2> RowVector2i;

Dynamic

Eigen並沒有限制矩陣的尺寸必須在編譯的時候就要確定下來。如果矩陣的尺寸在編譯的時候是不確定的,而在運行的時候才能確定,Eigen提供了定義動態大小的方法,稱爲dynamic size ;將在編譯時候就能確定的尺寸稱爲fixed size.
MatrixXd表示一個具有動態大小的矩陣,定義如下:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

VectorXi表示一個具有動態大小的向量,定義如下:

typedef Matrix<int, Dynamic, 1> VectorXi;

還可以定義行數固定而列數是動態大小的矩陣:

Matrix<float, 3, Dynamic>

構造函數

(1)默認的構造函數不執行任何空間分配,也不初始化矩陣的元素。

Matrix3f a;
MatrixXf b;
  • a是一個3*3的矩陣,分配了float[9]的空間,但未初始化內部元素;
  • b是一個動態大小的矩陣,現在它的尺寸是0*0,還未分配空間。

(2)帶參數的構造函數。
對於矩陣,行數在列數前面,對於向量,只有向量的大小。當對矩陣或向量指定大小時,只是分配相應大小的空間,未初始化元素。

MatrixXf a(10,15);
VectorXf b(30);
  • a是一個10*15的動態大小的矩陣,分配了空間但未初始化元素;
  • b是一個30大小的向量,同樣分配空間未初始化元素。

(3)爲了對固定大小和動態大小的矩陣提供統一的API,對指定大小的Matrix傳遞sizes也是合法的(傳遞也被忽略)。

Matrix3f a(3,3);

(4)可以用構造函數提供4以內尺寸的vector的初始化。

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爲起始的。

m(index)也可以用於獲取矩陣元素,但取決於matrix的存儲順序,默認是按列存儲的(即一列一列的進行存儲),當然也可以改爲按行。

[]操作符可以用於向量元素的獲取,但是不能用於matrix,因爲C++中[]不能傳遞超過一個參數。

#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;
  std::cout << "m(2):\n" << m(2) << std::endl;
}

結果:

Here is the matrix m:
  3  -1
2.5 1.5
m(2):
-1

逗號初始化

可以使用逗號初始化方式(comma-initializer)給矩陣和向量賦值。例如:

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

結果如下:

1 2 3 
4 5 6 
7 8 9

這樣就將上述值賦給了矩陣,在Eigen中矩陣默認的存儲方式是行優先,就是先存儲行。

Resizing

rows() , cols() , size() 方法分別返回行數,列數和 元素的個數。

Eigen支持對動態大小的矩陣和向量重新指定大小,通過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

如果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;
}

Assignment and resizing

assignment(分配)是複製一個矩陣到另外一個,通過操作符“=”實現。Eigen會自動resize左變量的大小以等於右側變量的大小。
當然,如果左邊變量是固定大小的,resizing是不允許的。

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

固定尺寸VS動態尺寸

實際中,應該使用固定尺寸還是動態尺寸,簡單的答案是:對於小尺寸的矩陣,使用固定大小的方式,對於大尺寸的矩陣,使用動態大小的方式。

Matrix4f mymatrix; 等價於 float mymatrix[16];
MatrixXf mymatrix(rows,columns);等價於float *mymatrix = new float[rows*columns];

使用固定尺寸可以避免動態內存的開闢,固定尺寸只是一個普通數組。

使用固定尺寸(<=4*4)需要編譯前知道矩陣大小,而且對於足夠大的尺寸,如大於32,固定尺寸的收益可以忽略不計,相反,很可能會導致棧崩潰,因爲Eigen嘗試將數組自動分配爲局部變量,這通常在堆棧上完成。而且基於環境,Eigen會對動態尺寸做優化(類似於std::vector)。

Matrix類的其他模板參數

如下石Matrix類的完整參數列表:

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>
  • Options是一個比特標誌位,這裏,我們只介紹一種標誌位:RowMajor,它表明matrix使用按行存儲(row-major),默認情況下是按列存儲(column-major)。Matrix<float, 3, 3, RowMajor>表示一個按行存儲的3*3矩陣。
  • MaxRowsAtCompileTime和MaxColsAtCompileTime表示在編譯階段矩陣的上限。主要是避免動態內存分配,使用數組。

一些方便的類型定義

Eigen定義了一些Matrix的類型:

  • MatrixNt for Matrix<type, N, N>.
  • VectorNt for Matrix<type, N, 1>.
  • RowVectorNt for Matrix<type, 1, N>.

其中,N可以是2,3,4或X(Dynamic);
t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。

參考:

“Eigen教程(2)”
“Eigen學習筆記2-Matrix類”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章