Eigen教程(2)


整理下Eigen庫的教程,參考:http://eigen.tuxfamily.org/dox/index.html

Matrix類

在Eigen,所有的矩陣和向量都是Matrix模板類的對象,Vector只是一種特殊的矩陣(一行或者一列)。

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

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

Scalar是表示元素的類型,RowsAtCompileTime為矩陣的行,ColsAtCompileTime為矩陣的列。

庫中提供了一些類型便於使用,比如:

typedef Matrix<float, 4, 4> Matrix4f;

Vectors向量

列向量

typedef Matrix<float, 3, 1> Vector3f;

行向量

typedef Matrix<int, 1, 2> RowVector2i;

Dynamic

Eigen不只限於已知大小(編譯階段)的矩陣,有些矩陣的尺寸是運行時確定的,於是引入了一個特殊的標識符:Dynamic

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<int, Dynamic, 1> VectorXi;
Matrix<float, 3, Dynamic>

構造函數

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

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,對指定大小的Matrix傳遞sizes也是合法的(傳遞也被忽略)。

Matrix3f a(3,3);

可以用構造函數提供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);

獲取元素

通過中括號獲取元素,對於矩陣是:(行,列);對於向量,只是傳遞它的索引,以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

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

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

逗號初始化

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

resizing

matrix的大小可以通過rows()、cols()、size()獲取,resize()可以重新調整動態matrix的大小。

#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 和 resizing

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;

a is of size 2x2
a is now of size 3x3

當然,如果左邊量是固定大小的,上面的resizing是不允許的。

固定尺寸 vs 動態尺寸

實際中,應該使用固定尺寸還是動態尺寸,簡單的答案是:小的尺寸用固定的,大的尺寸用動態的。使用固定尺寸可以避免動態內存的開辟,固定尺寸只是一個普通數組。

Matrix4f mymatrix; 等價於 float mymatrix[16];

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

使用固定尺寸(<=4*4)需要編譯前知道矩陣大小,而且對於足夠大的尺寸,如大於32,固定尺寸的收益可以忽略不計,而且可能導致棧崩潰。而且基於環境,Eigen會對動態尺寸做優化(類似於std::vector)

其他模板參數

上面只討論了前三個參數,完整的模板參數如下:

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]

一些方便的定義

Eigen定義了一些類型

  • MatrixNt = Matrix<type, N, N> 特殊地有 MatrxXi = Matrix<int, Dynamic, Dynamic>
  • VectorNt = Matrix<type, N, 1> 比如 Vector2f = Matrix<float, 2, 1>
  • RowVectorNt = Matrix<type, 1, N> 比如 RowVector3d = Matrix<double, 1, 3>

N可以是2,3,4或X(Dynamic)

t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM