00 Eigen簡介
Eigen:基于線性代數的C ++模板庫,主要用于矩陣,向量,數值求解器和相關算法。SLAM中常用的Ceres、G2O等項目均是基于Eigen庫。
Eigen庫的優點:
支持整數、浮點數、復數,使用模板編程,可以為特殊的數據結構提供矩陣操作。
OpenCV自帶到Eigen的接口。
支持逐元素、分塊、和整體的矩陣操作。
支持使用Intel MKL加速部分功能。
支持多線程,對稀疏矩陣支持良好。
支持常用幾何運算,包括旋轉矩陣、四元數、矩陣變換、角軸等等。
即使不做SLAM,在3D視覺中,當處理大量數學運算時,我們也會用到Eigen庫,它幫我們優化了性能。在安裝完成Eigen庫后,開始接下來的學習。
01 數據類型
Eigen庫的核心類是Matrix,由6個參數構成:
Matrix< ????????typename?Scalar, ????????int?RowsAtCompileTime, ????????int?ColsAtCompileTime, ????????int?Options?=?0,???????????????????????????????//?默認(無需更改) ????????int?MaxRowsAtCompileTime?=?RowsAtCompileTime,??//?默認(最大行數,提前知道極限) ????????int?MaxColsAtCompileTime?=?ColsAtCompileTime???//?默認(最大列數,提前知道極限) >
其中:
前三個參數:需要我們指定
后三個參數:默認即可,無需指定
因為經常需要實例化一些方陣、向量,因此Eigen庫也提供了很多直接使用的模板(利用C++的關鍵字:typedef),例如Matrix4f是的float型矩陣:
typedefMatrixMatrix4f;
還有例如列向量:Vector3f,其本質也是Matrix類:
typedefMatrixVector3f;
行向量RowVector:
typedefMatrixRowVector2i;
靜態-動態-矩陣
靜態矩陣:矩陣是靜態的,即編譯時候就知道運行結果,例如Matrix3d:表示元素類型為double大小為3*3的矩陣變量,其大小在編譯時就知道。
動態矩陣:有時候運行完之后,才可以知道,這里使用MatrixXd:表示任意大小的元素類型為double的矩陣變量,其大小只有在運行被賦值之后才能知道;
數據類型
Eigen中的矩陣類型一般都是用類似MatrixNX來表示,可以根據該名字來判斷其大小(2,3,4,或X,意思Dynamic)和數據類型,比如:
d:表示double類型
f:表示float類型
i:表示整數
c:表示復數;
舉例:Matrix2f,表示的是一個維的,其每個元素都是float類型。
02 新建矩陣
矩陣構造
默認構造,分配了大小和內存空間,但沒有初始化矩陣元素(里面的數值是隨機的,不能使用):
Matrix3fa;// 3*3的元素,其中還有一個float[9]數組,其中的元素沒有初始化; MatrixXfb;//動態大小的矩陣,目前的大小是0*0,它的元素數組完全沒有分配。
對于動態數組,你也可以直接分配大?。ㄊプ饔昧耍?,同樣沒有初始化矩陣元素:
MatrixXfa(10,15);// 10x15動態矩陣,數組內存已經分配,但是沒有初始化; VectorXfb(30);//大小為30的向量,數組內存已經分配,但是元素沒有初始化。
或者更通用的:
MatrixVector3f_def;
矩陣初始化
在構造完后,我們需要對元素進行初始化,常用的是直接賦值:
Eigen::Matrix3fm; m<1,?2,?3,?????4,?5,?6,?????7,?8,?9;???
它是逐行寫入的,這只適用于較小的矩陣:
Eigen::MatrixXdm(3,3); m<<1,2,3,?????4,5,6,?????7,8,9;
對于向量,還可以在構造的時候初始化:
Vector3dv(1,2,3); Vector3dw(1,0,0);
還有一些特殊函數,函數:
MatrixXf::Zero(3,4);//將矩陣3行4列初始化為0 MatrixXf::Ones(3,3);//將矩陣3行3列初始化為1 Vector3f::Ones();//將3行的縱向量初始化為1 MatrixXi::Identity(3,3);//單位矩陣 Matrix3d::Random();//隨機矩陣
03 矩陣索引
當前矩陣的行數、列數、大小可以通過rows()、cols()和size()來獲取。遍歷Eigen矩陣時最好通過rows和cols來限制訪問范圍,索引的方法如下:
1、矩陣訪問按照先行索引、后列索引方式進行,索引下標從0開始(與Matlab不同);
2、矩陣元素的訪問可以通過**”( )”操作符完成。例如m(2, 3)**,矩陣m的第2行第3列元素;
3、針對向量還提供”**[ ]”操作符,注意矩陣則不可**如此使用。
resize:不同于matlab、Python,對于動態矩陣雖然可以通過resize()函數來動態修改矩陣的大小,但是需要說明的是,在Eigen中:
不能用:固定大小的矩陣是不能使用resize()來修改矩陣的大小;
數據會變:resize()函數會析構掉原來的數據,變為0.,因此最好使用:conservativeResize()函數
大小修改:使用”=”操作符操作動態矩陣時,如果左右兩邊的矩陣大小不等,則左邊的動態矩陣的大小會被修改為右邊的大小。
利用block()函數,可以從Matrix中取出一個小矩陣來進行處理,使用的語法為:
matrix.block(i,j);
例如:
Eigen::MatrixXfm(4,4); m<1,?2,?3,?4, ????5,?6,?7,?8, ????9,?10,?11,?12, ????13,?14,?15,?16; cout?<"Block?in?the?middle"?<(1,1)<
單獨的列和行是塊的特殊情況。Eigen提供了可以輕松解決它們的方法:.col()和.row():
Eigen::MatrixXim(2,2); m<1,?2,?3,?4; cout?<
04 數學運算
4.1 加減法
Eigen幫我們重載了,直接運算:
Vector3dv(1,2,3); Vector3dw(1,0,0); cout<
4.2 乘除法
除法:通常我們是除以標量。對于矩陣除法,我們是求它的逆,再轉換為矩陣乘法。因此較為簡單:
Vector3dv(1,2,3); Vector3dr=v/3; cout<
矩陣乘法:*
乘法,標量非常簡單:
cout<Matrix2dmat; mat<1,?2, ????3,?4; Vector2d?u(-1,?1),?v(2,?0); //?矩陣乘法?乘以矩陣 std::cout?<"Here?is?mat*mat: " ??????????<
補充:轉置
向量、矩陣的乘法,因為需要size一致,因此需要用到轉置:
MatrixXcfa=MatrixXcf::Random(2,2);//MatrixXcf為復數矩陣 cout<"Here?is?the?matrix?a "?<
需要說明的是,在Eigen中,對于自身的操作,都有專門的函數,例如對自身的轉置:
a.transposeInPlace();//直接在a上操作
點乘和叉乘
Vector3dv(1,2,3); Vector3dw(0,1,2); //點乘 cout<"Dot?product:?"?<
在Eigen中,向量的叉乘只支持三維的向量,這是因為叉乘通常用于計算方向、夾角等,它的計算規則如下:
4.3 特征運算
//Eigenalsoprovidessomereductionoperationstoreduceagivenmatrixorvectortoasinglevalue //suchasthesum(computedbysum()),product(prod()),orthemaximum(maxCoeff())andminimum(minCoeff())ofallitscoefficients. Eigen::Matrix2dmat; mat<1,?2, ???????3,?4; //元素和,元素乘積,元素均值,最小系數,最大系數,蹤 cout?<"Here?is?mat.sum():???????"?<
05 通用數組
Array類提供了通用數組。此外,Array類提供了一種執行逐系數運算的簡便方法,該運算可能沒有線性代數含義,例如將常數添加到數組中的每個系數或按系數乘兩個數組。
注:Eigen計算三角函數等,Matrix并不支持,需要通過.array()轉換到Array類,再計算!
m1.array().atan();
常見數據類型
ArrayArrayXf Array Array3f Array ArrayXXd Array Array
常見操作:
//逐元素操作Vectorizedoperationsoneachelementindependently //Eigen//Matlab//注釋 R=P.cwiseProduct(Q);//R=P.*Q//逐元素乘法 R=P.array()*s.array();//R=P.*s//逐元素乘法(s為標量) R=P.cwiseQuotient(Q);//R=P./Q//逐元素除法 R=P.array()/Q.array();//R=P./Q//逐元素除法 R=P.array()+s.array();//R=P+s//逐元素加法(s為標量) R=P.array()-s.array();//R=P-s//逐元素減法(s為標量) R.array()+=s;//R=R+s//逐元素加法(s為標量) R.array()-=s;//R=R-s//逐元素減法(s為標量) R.array()
06 更多操作
對于Eigen,它適合一個簡單的數值計算庫,并沒有什么實用技巧。其實大多數時候,你只需要利用Google和百度去查詢你需要的操作即可!對于更多的操作,可以參考:Eigen 常用函數查詢,對比MatLab操作 。
責任編輯:彭菁
-
接口
+關注
關注
33文章
8598瀏覽量
151157 -
模板
+關注
關注
0文章
108瀏覽量
20563 -
C++
+關注
關注
22文章
2108瀏覽量
73651
原文標題:06 更多操作
文章出處:【微信號:3D視覺工坊,微信公眾號:3D視覺工坊】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論