Eigen矩陣運算開源庫完全使用指南
阿新 • • 發佈:2018-12-31
Eigen庫是一個開源的矩陣運算庫,其利用C++模板程式設計的思想,構造所有矩陣通過傳遞模板引數形式完成。由於模板類不支援庫連結方式編譯,而且模板類要求全部寫在標頭檔案中,從而導致導致Eigen庫只能通過開源的方式供大家使用,並且只需要包含Eigen標頭檔案就能直接使用。Eigen庫中矩陣為其基本資料型別,向量也是一種特殊的矩陣。其所有矩陣資料型別都是由一個模板類Matrix生成。Matrix 類有6個模板引數,現在我們瞭解前三個足夠。剩下的三個引數都有預設值.Matrix 的三個強制的模板引數:Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> 完整模板引數:Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options = 0, int MaxRowsAtCompileTime = RowsAtCompileTime, int MaxColsAtCompileTime = ColsAtCompileTime> typedef Matrix<float, 4, 4> Matrix4f;在Eigen中,vectors 只是一種特殊形式的矩陣,有一行或者一列。在大多數情況下一列比較多,這樣的向量也叫做列向量,也簡稱向量。其他情況叫做行向量。例如typedef Vector3f 是一個(列)向量,它的定義如下:typedef Matrix<float, 3, 1> Vector3f;同樣我們也提供了行向量的定義:typedef Matrix<int, 1, 2> RowVector2i;動態矩陣和靜態矩陣:動態矩陣是指其大小在執行時確定,靜態矩陣是指其大小在編譯時確定。MatrixXd:表示任意大小的元素型別為double的矩陣變數,其大小隻有在執行時被賦值之後才能知道。 Matrix3d:表示元素型別為double大小為3*3的矩陣變數,其大小在編譯時就知道。在Eigen中行優先的矩陣會在其名字中包含有row,否則就是列優先。Eigen中的向量只是一個特殊的矩陣,其維度為1而已。矩陣型別:Eigen中的矩陣型別一般都是用類似MatrixXXX來表示,可以根據該名字來判斷其資料型別,比如”d”表示double型別,”f”表示float型別,”i”表示整數,”c”表示複數;Matrix2f,表示的是一個2*2維的,其每個元素都是float型別。專案中使用Eigen庫find_package(Eigen3 REQUIRED)include_directories(${EIGEN3_INCLUDE_DIR}) #include <Eigen/Dense>資料型別定義在Eigen名稱空間下矩陣構造1)預設構造:不會進行動態記憶體分配,也不會初始化矩陣元素Matrix3f a;MatrixXf b;a是一個3*3的元素,其中還有一個float[9]陣列,其中的元素沒有初始化;b是一個動態大小的矩陣,目前的大小是0*0,它的元素陣列完全沒有分配。 2)指定行數列數構造:分配元素陣列,不初始化元素MatrixXf a(10,15);VectorXf b(30);這裡,a是10x15動態矩陣,陣列記憶體已經分配,但是沒有初始化;b是一個大小為30的向量,陣列記憶體已經分配,但是元素沒有初始化。 3)向量簡單初始構造對於比較小的、固定長度的向量提供直接構造元素方式。Vector2d a(5.0, 6.0);Vector3d b(5.0, 6.0, 7.0);Vector4d c(5.0, 6.0, 7.0, 8.0);4)逗號初始化Eigen::Matrix3f m;m << 1, 2, 3, 4, 5, 6, 7, 8, 9;矩陣和向量都可以通過逗號分隔方法進行初始化。注意這種初始化方法只能對確定大小矩陣進行,包括指定行列數的動態矩陣,即下面這種是會出現段錯誤的:Eigen::MatrixXd m; m <<1,2,3, 4,5,6, 7,8,9;而下面這種可以Eigen::MatrixXd m(3,3); m <<1,2,3, 4,5,6, 7,8,9;5)常用矩陣MatrixXf::Zero(3,4); // 將矩陣3行4列初始化為0MatrixXf::Ones(3,3); // 將矩陣3行3列初始化為1Vector3f::Ones(); // 將3行的縱向量初始化為1MatrixXi::Identity(3,3); //單位陣注意對動態矩陣初始化的時候,必須指定行數和列數。6)矩陣特定初始化// 矩陣全部元素置0 m1.setZero(); // 隨機生成一個矩陣 m1.setRandom(); // 置單位矩陣 m1.setIdentity(3,3);// 矩陣求逆 m1.inverse(); // 矩陣轉置 m1.transpose(); 矩陣元素的訪問1、矩陣訪問按照先行索引、後列索引方式進行,索引下標從0開始(與Matlab不同);2、矩陣元素的訪問可以通過”()”操作符完成。例如m(2, 3)既是獲取矩陣m的第2行第3列元素;3、針對向量還提供”[]”操作符,注意矩陣則不可如此使用。矩陣常用成員函式當前矩陣的行數、列數、大小可以通過rows()、cols()和size()來獲取,對於動態矩陣可以通過resize()函式來動態修改矩陣的大小。注意:(1)、固定大小的矩陣是不能使用resize()來修改矩陣的大小;(2)、resize()函式會析構掉原來的資料,因此呼叫resize()函式之後將不能保證元素的值不改變;(3)、使用”=”操作符操作動態矩陣時,如果左右兩邊的矩陣大小不等,則左邊的動態矩陣的大小會被修改為右邊的大小。需要特別注意,遍歷Eigen矩陣時最好通過rows和cols來限制訪問範圍,在Eigen中size()其實返回的是rows()*cols()的值,這就意味著如果Eigen矩陣的rows為0的時候,size()就會為0。矩陣賦值運算子注意事項賦值是將一個矩陣拷貝進另外一個矩陣,使用操作符=。Eigen 會自動跳轉左面元素的大小,從而使得它和右側元素匹配。例如: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原先大小 2x2 a現在大小 3x3 當然,如果左側是固定大小的矩陣,那麼改變大小是不允許的。 如果你不需要這種自動調整大小,你可以將他關閉。
如果同時想要獲得對應最值在矩陣中的索引,可以用:Eigen::MatrixXf mat(2,4); mat << 1, 2, 6, 9, 3, 1, 7, 2; Eigen::VectorXi maxIndices; Eigen::VectorXf maxVals; MatrixXf::Index maxIndex[2];//儲存對應索引 VectorXf maxVal(2);//儲存最大值 for(int i=0;i<2;++i) maxVal(i) = mat.row(i).maxCoeff( &maxIndex[i] );//行最大元素讀寫
- Scalar 就是矩陣元素標量型別。
- RowsAtCompileTime 和ColsAtCompileTime 分別指代編譯時候的行和列值。
實用操作總結
給一個已經存在的矩陣後面增加一行:MatrixXf s(3,4);s<<1,2,3,4,5,6,7,8,9,10,11,12;s = (MatrixXf(4,4)<<s,1,1,1,1).finished();矩陣部分操作(感興趣部分操作)官網參考:Eigen矩陣可以實現按列或按行操作:也叫partial reductions主要利用colwise()和rowwise()實現對矩陣逐列或逐行操作,很重要的一個應用就是得到一個矩陣的行最大值或列最大值:如果同時想要獲得對應最值在矩陣中的索引,可以用:Eigen::MatrixXf mat(2,4); mat << 1, 2, 6, 9, 3, 1, 7, 2; Eigen::VectorXi maxIndices; Eigen::VectorXf maxVals; MatrixXf::Index maxIndex[2];//儲存對應索引 VectorXf maxVal(2);//儲存最大值 for(int i=0;i<2;++i) maxVal(i) = mat.row(i).maxCoeff( &maxIndex[i] );//行最大元素讀寫