Eigen學習筆記2:C++矩陣運算庫Eigen介紹


Eigen常規矩陣定義

1.使用

Eigen的使用在官網上有詳細的介紹,這里對我學習過程中用到的基本操作進行介紹。首先是矩陣的定義。
在矩陣類的模板參數共有6個。一般情況下我們只需要關注前三個參數即可。前三個模板參數如下所示:

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>

 

  1. Scalar參數為矩陣元素的類型,該參數可以是int,float,double等。
  2. RowsAtCompileTime和ColsAtCompileTime是矩陣的行數和列數。

Matrix<float,4,4> M44是定義一個4×4的矩陣,矩陣元素以float類型存儲。直接使用矩陣模板定義一個矩陣往往會覺得麻煩,Eigen提供了一些基本矩陣的別名定義,如typedef Matrix<float,4,4> Matrix4f.下面是一些內置的別名定義.來源於官方手冊

typedef Matrix< std::complex<double> , 2 , 2 > Matrix2cd typedef Matrix< std::complex<float> , 2 , 2 > Matrix2cf typedef Matrix< double , 2 , 2 > Matrix2d typedef Matrix< float , 2 , 2 > Matrix2f typedef Matrix< int , 2 , 2 > Matrix2i typedef Matrix< std::complex<double> , 3 , 3 > Matrix3cd typedef Matrix< std::complex<float> , 3 , 3 > Matrix3cf typedef Matrix< double , 3 , 3 > Matrix3d typedef Matrix< float , 3 , 3 > Matrix3f typedef Matrix< int , 3 , 3 > Matrix3i typedef Matrix< std::complex<double> , 4 , 4 > Matrix4cd typedef Matrix< std::complex<float> , 4 , 4 > Matrix4cf typedef Matrix< double , 4 , 4 > Matrix4d typedef Matrix< float , 4 , 4 > Matrix4f typedef Matrix< int , 4 , 4 > Matrix4i typedef Matrix< std::complex<double> , Dynamic , Dynamic > MatrixXcd typedef Matrix< std::complex<float> , Dynamic , Dynamic > MatrixXcf typedef Matrix< double , Dynamic , Dynamic > MatrixXd typedef Matrix< float , Dynamic , Dynamic > MatrixXf typedef Matrix< int , Dynamic , Dynamic > MatrixXi typedef Matrix< std::complex<double> , 1, 2 > RowVector2cd typedef Matrix< std::complex<float> , 1, 2 > RowVector2cf typedef Matrix< double , 1, 2 > RowVector2d typedef Matrix< float , 1, 2 > RowVector2f typedef Matrix< int , 1, 2 > RowVector2i typedef Matrix< std::complex<double> , 1, 3 > RowVector3cd typedef Matrix< std::complex<float> , 1, 3 > RowVector3cf typedef Matrix< double , 1, 3 > RowVector3d typedef Matrix< float , 1, 3 > RowVector3f typedef Matrix< int , 1, 3 > RowVector3i typedef Matrix< std::complex<double> , 1, 4 > RowVector4cd typedef Matrix< std::complex<float> , 1, 4 > RowVector4cf typedef Matrix< double , 1, 4 > RowVector4d typedef Matrix< float , 1, 4 > RowVector4f typedef Matrix< int , 1, 4 > RowVector4i typedef Matrix< std::complex<double> , 1, Dynamic > RowVectorXcd typedef Matrix< std::complex<float> , 1, Dynamic > RowVectorXcf typedef Matrix< double , 1, Dynamic > RowVectorXd typedef Matrix< float , 1, Dynamic > RowVectorXf typedef Matrix< int , 1, Dynamic > RowVectorXi typedef Matrix< std::complex<double> , 2 , 1> Vector2cd typedef Matrix< std::complex<float> , 2 , 1> Vector2cf typedef Matrix< double , 2 , 1> Vector2d typedef Matrix< float , 2 , 1> Vector2f typedef Matrix< int , 2 , 1> Vector2i typedef Matrix< std::complex<double> , 3 , 1> Vector3cd typedef Matrix< std::complex<float> , 3 , 1> Vector3cf typedef Matrix< double , 3 , 1> Vector3d typedef Matrix< float , 3 , 1> Vector3f typedef Matrix< int , 3 , 1> Vector3i typedef Matrix< std::complex<double> , 4 , 1> Vector4cd typedef Matrix< std::complex<float> , 4 , 1> Vector4cf typedef Matrix< double , 4 , 1> Vector4d typedef Matrix< float , 4 , 1> Vector4f typedef Matrix< int , 4 , 1> Vector4i typedef Matrix< std::complex<double> , Dynamic , 1> VectorXcd typedef Matrix< std::complex<float> , Dynamic , 1> VectorXcf typedef Matrix< double , Dynamic , 1> VectorXd typedef Matrix< float , Dynamic , 1> VectorXf typedef Matrix< int , Dynamic , 1> VectorXi

2 向量

向量被作為一種特殊的矩陣進行處理,即要么行為一要么列為一。除非顯式的說明為行向量,否則這里將向量默認為列向量。請看下面兩個別名定義:

typedef Matrix<float,3,1> Vector3f; typedef Matrix<int,1,2> RowVector2i;

3 矩陣的動態空間分配

很多時候在程序的編譯階段也許我們並不知道矩陣具體的行列數,這時候使用動態控件分配就顯得很必要了。當我們給矩陣模板中參數RowsAtCompileTime或者ColsAtCompileTime參數指定為Dynamic時,表示該矩陣對應行或列為一個動態分配的值。下面是兩個動態矩陣的別名定義:

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

4 矩陣的構建

經過上面的介紹以后,我們應該能定義一些基本的矩陣了。如:

Matrix3f a; //定義一個float類型3×3固定矩陣a MatrixXf b; //定義一個float類型動態矩陣b(0×0) Matrix<int,Dynamic,3> b; //定義一個int類型動態矩陣(0×3)

對應動態矩陣,我們也可以在構造的時候給出矩陣所占用的空間,比如:

MatrixXf a(10,15); //定義float類型10×15動態矩陣 VectorXf b(30); //定義float類型30×1動態矩陣(列向量)

為了保持一致性,我們也可以使用上面構造函數的形式定義一個固定的矩陣,即Matrix3f a(3,3)也是允許的。

上面矩陣在構造的過程中並沒有初始化,Eigen還為一些小的(列)向量提供了可以初始化的構造函數。如:

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提供了矩陣元素的訪問形式和matlab中矩陣的訪問形式非常相似,最大的不同是matlab中元素從1開始,而Eigen的矩陣中元素是從0開始訪問。對於矩陣,第一個參數為行索引,第二個參數為列索引。而對於向量只需要給出一個索引即可。

#include <iostream> #include "Eigen\Core" //import most common Eigen types 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<<"Hear 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; }

輸出結果如下:

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

m(index)這種訪問形式並不僅限於向量之中,對於矩陣也可以這樣訪問。這一點和matlab相同,我們知道在matlab中定義一個矩陣a(3,4),如果我訪問a(5)相當於訪問a(2,2),這是因為在matlab中矩陣是按列存儲的。這里比較靈活,默認矩陣元素也是按列存儲的,但是我們也可以通過矩陣模板構造參數Options=RowMajor改變存儲方式(這個參數是我們還沒有提到的矩陣構造參數的第4個參數)。

6 一般初始化方法

對於矩陣的初始化,我們可以采用下面的方法方便且直觀的進行:

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

7 矩陣的大小

Eigen提供了rows(),cols(),size()方法來獲取矩陣的大小,同時也同了resize()方法從新改變動態數組的大小。

#include <iostream> #include "Eigen\Core" using namespace Eigen; int main() { MatrixXd m(2,5); m<<1,2,3,4,5, 6,7,8,9,10; m.resize(4,3); std::cout<<"The matrix m is:\n"<<m<<std::endl; 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<<1,2; v.resize(5); std::cout<<"The vector v is:\n"<<v<<std::endl; 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: 1 3 5 6 8 10 2 4 9.58787e-315 7 9 1.17493e-309 The matrix m is of size 4x3 It has 12 coefficients The vector v is: 1 2 1.17477e-309 7.0868e-304 0 The vector v is of size 5 As a matrix,v is of size 5x1

可以看到我們可以把矩陣任意的resize,但是resize后矩陣的元素會改變,如果resize后的矩陣比之前的大會出現一些未初始化的元素。如果被resize的矩陣按列存儲(默認),那么resize命令和matlab中的reshape執行結果相同,只是matlab要求reshape的矩陣前后元素必須相同,也就是不允許resize后不能出現未初始化的元素。
對於固定大小的矩陣雖然也支持resize命令,但是resize后的大小只能是它本身的大小,否則就會報錯。因為resize前后如果矩陣大小一樣,就不會執行resize。如果我們不想在resize后改變矩陣的對應元素,那么可以使用conservativeResize()方法。對應上面程序中的m矩陣我們調用m.conservativeResize(4,3)后得到結果如下。其中因為行數增加了,增加的行會以未初始化的形式出現。

The matrix m is:
           1 2 3 6 7 8 9.58787e-315 2.122e-314 1.52909e+249 0 0 2.47039e+249

http://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html

8 賦值和大小變換

在Eigen中使用=可以直接將一個矩陣復制給另外一個矩陣,如果被復制的和賦值矩陣大小不一致,會自動對被復制矩陣執行resize函數。當然如果被復制的矩陣為固定矩陣當然就不會執行resize函數。當然也可以通過一些設置取消這個自動resize的過程。

using namespace Eigen; int main() { MatrixXf a(2,2); MatrixXf b(3,3); b<<1,2,3, 4,5,6, 7,8,9; a = b; std::cout<<a<<std::endl; }

輸出結果:

1 2 3 4 5 6 7 8 9

9 固定矩陣和動態矩陣

什么時候使用固定矩陣什么時候使用動態矩陣呢?簡單的說:當矩陣尺寸比較小時使用固定矩陣(一般小於16),當矩陣尺寸較大時使用動態矩陣(一般大於32)。使用固定矩陣有更好的表現,它可以避免重復的動態內存分配,固定矩陣實際上是一個array。即Matrix4f mymatrix;事實上是float mymatrix[16];。所以這個是真的不花費任何運行時間。相反動態矩陣的建立需要在
heap中分配空間。即MatrixXf mymatrix(rows,colums);實際上是float *mymatrix = new float[rows*colums];.此外動態矩陣還要保存行和列的值。
當然固定矩陣也存在着顯而易見的弊端。當數組的大小過大時,固定數組的速度優勢就不那么明顯了,相反過大的固定數組有可能造成stack的溢出。這時候動態矩陣的靈活性就顯得十分重要了。

10 其他模板參數

最開始我們已經提到了建立一個矩陣一共有6個模板參數,其中有3個我們還沒有提到(其實第三個參數已經提到過了)。

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options=0, int MaxRowsAtCompileTime = RowsAtCompileTime, int MaxColsAtCompileTime = ColsAtCompileTime>
  1. Options:這個參數決定了矩陣在存儲過程中實際是按行還是按列存儲。這個存儲方式在前面我們提到的矩陣變換時必須要注意。默認是按列存儲,我們可以顯示的使用Options=RowMajor讓矩陣實際按行存儲。如Matrix<float,2,3,RowMajor> a;.
  2. MaxRowsAtCompileTime和MaxColsAtCompileTime:這兩個值是設定動態矩陣在分配空間時最大的行數和列數。如Matrix<float,Dynamic,Dynamic,0,3,4>;.

11 常規的矩陣typedef

我們前面給出了一些常用的矩陣typedef.其實可以總結如下:

  1. MatrixNt對應的是Matrix
  2. VectorNt對應的是Matrix
  3. RowVectorNt對應的是Matrix

其中:

  1. N可以是2,3,4或者X(表示Dynamic).
  2. t可以是i(int),f(float),d(double),cf(complex


免責聲明!

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



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