爱玩科技网
您的当前位置:首页eigen:矩阵处理工具

eigen:矩阵处理工具

来源:爱玩科技网
C++开源矩阵计算工具Eigen简单用法(一)

矩阵转置函数m.transpose(); 矩阵的特征值m.eigenvalues(); 矩阵求逆矩阵m.inverse(); 特征向量m.eignvectors();

1、 矩阵的定义

Eigen中关于矩阵类的模板函数中,共有6个模板参数,但是目前常用的只有前三个,如下所示:

[cpp] view plaincopy

1. template

2. struct traits > 3. .......

其前三个参数分别表示矩阵元素的类型,行数和列数。

矩阵定义时可以使用Dynamic来表示矩阵的行列数为未知,例如: typedef Matrix MatrixXd; 在Eigen中也提供了很多常见的简化定义形式,例如: typedef Matrix< double , 3 , 1> Vector3d 注意: (1)Eigen中无论是矩阵还是数组、向量,无论是静态矩阵还是动态矩阵都提供默认构造函数,也就是你定义这些数据结构时都可以不用提供任何参数,其大小均由运行时来确定。

(2)矩阵的构造函数中只提供行列数、元素类型的构造参数,而不提供元素值的构造,对于比较小的、固定长度的向量提供初始化元素的定义,例如: [cpp] view plaincopy

1. Vector2d a(5.0, 6.0);

2. Vector3d b(5.0, 6.0, 7.0);

3. Vector4d c(5.0, 6.0, 7.0, 8.0); 2、动态矩阵和静态矩阵

动态矩阵是指其大小在运行时确定,静态矩阵是指其大小在编译时确定,在Eigen中并未这样称呼矩阵。具体可见如下两段代码: 代码段1:

[cpp] view plaincopy

1. #include 2. #include 3. using namespace Eigen; 4. using namespace std; 5. int main() 6. {

7. MatrixXd m = MatrixXd::Random(3,3);

8. m = (m + MatrixXd::Constant(3,3,1.2)) * 50; 9. cout << \"m =\" << endl << m << endl;

10.VectorXd v(3); 11.v << 1, 2, 3;

12.cout << \"m * v =\" << endl << m * v << endl; 13.} 代码段2:

[cpp] view plaincopy

1. #include 2. #include 3. using namespace Eigen; 4. using namespace std; 5. int main() 6. {

7. Matrix3d m = Matrix3d::Random();

8. m = (m + Matrix3d::Constant(1.2)) * 50; 9. cout << \"m =\" << endl << m << endl; 10.Vector3d v(1,2,3);

11.cout << \"m * v =\" << endl << m * v << endl; 12.} 说明: 1)代码段1中MatrixXd表示任意大小的元素类型为double的矩阵变量,其大小只有在运行时被赋值之后才能知道; MatrixXd::Random(3,3)表示产生一个元素类型为double的3*3的临时矩阵对象。

2) 代码段2中Matrix3d表示元素类型为double大小为3*3的矩阵变量,其大小在编译时就知道;

3)上例中向量的定义也是类似,不过这里的向量时列优先,在Eigen中行优先的矩阵会在其名字中包含有row,否则就是列优先。

4)向量只是一个特殊的矩阵,其一个维度为1而已,如:typedef Matrix< double , 3 , 1> Vector3d

3、矩阵元素的访问 在矩阵的访问中,行索引总是作为第一个参数,需注意Eigen中遵循大家的习惯让矩阵、数组、向量的下标都是从0开始。矩阵元素的访问可以通过()操作符完成,例如m(2,3)即是获取矩阵m的第2行第3列元素(注意行列数从0开始)。可参看如下代码: [cpp] view plaincopy

1. #include 2. #include 3. using namespace Eigen; 4. int main() 5. {

6. MatrixXd m(2,2); 7. m(0,0) = 3; 8. m(1,0) = 2.5; 9. m(0,1) = -1;

10.m(1,1) = m(1,0) + m(0,1);

11.std::cout << \"Here is the matrix m:\\n\" << m << std::endl; 12.VectorXd v(2);

13.v(0) = 4;

14.v(1) = v(0) - 1;

15.std::cout << \"Here is the vector v:\\n\" << v << std::endl; 16.} 其输出结果为: Here is the matrix m: 3 -1 2.5 1.5

Here is the vector v: 4 3

针对向量还提供[]操作符,注意矩阵则不可如此使用,原因为:在C++中m[i, j]中逗号表达式 “i, j”的值始终都是“j”的值,即m[i, j]对于C++来讲就是m[j]; 4、设置矩阵的元素

在Eigen中重载了\"<<\"操作符,通过该操作符即可以一个一个元素的进行赋值,也可以一块一块的赋值。另外也可以使用下标进行复制,例如下面两段代码: 代码段1

[cpp] view plaincopy

1. Matrix3f m;

2. m << 1, 2, 3, 3. 4, 5, 6, 4. 7, 8, 9;

5. std::cout << m; 输出结果为: 1 2 3 4 5 6 7 8 9

代码段二(使用下标进行复制) [cpp] view plaincopy

1. VectorXf m_Vector_A; 2. MatrixXf m_matrix_B; 3. int m_iN =-1; 4.

5. bool InitData(int pSrc[100][100], int iWidth, int iHeight) 6. {

7. if (NULL == pSrc || iWidth <=0 || iHeight <= 0) 8. return false; 9. m_iN = iWidth*iHeight; 10. VectorXf tmp_A(m_iN);

11. MatrixXf tmp_B(m_iN, 5); 12. int i =0, j=0, iPos =0; 13. while(i15. j=0;

16. while(j18. tmp_A(iPos) = pSrc[i][j] * log((float)pSrc[i][j]); 19.

20. tmp_B(iPos,0) = pSrc[i][j] ; 21. tmp_B(iPos,1) = pSrc[i][j] * i; 22. tmp_B(iPos,2) = pSrc[i][j] * j;

23. tmp_B(iPos,3) = pSrc[i][j] * i * i; 24. tmp_B(iPos,4) = pSrc[i][j] * j * j; 25. ++iPos; 26. ++j; 27. } 28. ++i; 29. }

30. m_Vector_A = tmp_A; 31. m_matrix_B = tmp_B; 32.}

5、重置矩阵大小

当前矩阵的行数、列数、大小可以通过rows(),cols()和size()来获取,对于动态矩阵可以通过resize()函数来动态修改矩阵的大小. 需注意:

(1) 固定大小的矩阵是不能使用resize()来修改矩阵的大小;

(2) resize()函数会析构掉原来的数据,因此调用resize()函数之后将不能保证元素的值不改变。

(3) 使用“=”操作符操作动态矩阵时,如果左右边的矩阵大小不等,则左边的动态矩阵的大小会被修改为右边的大小。例如下面的代码段: [cpp] view plaincopy

1. MatrixXf a(2,2);

2. std::cout << \"a is of size \" << a.rows() << \"x\" << a.cols() << std::endl;

3. MatrixXf b(3,3); 4. a = b;

5. 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

6、如何选择动态矩阵和静态矩阵?

Eigen对于这问题的答案是:对于小矩阵(一般大小小于16)的使用固定大小的静态矩阵,它可以带来比较高的效率,对于大矩阵(一般大小大于32)建议使用动态矩阵。

还需特别注意的是:如果特别大的矩阵使用了固定大小的静态矩阵则可能造成栈溢出的问题 本文主要是Eigen中矩阵和向量的算术运算,在Eigen中的这些算术运算重载了C++的+,-,*,所以使用起来非常方便。 1、矩阵的运算

Eigen提供+、-、一元操作符“-”、+=、-=,例如: 二元操作符+/-表示两矩阵相加(矩阵中对应元素相加/减,返回一个临时矩阵): B+C 或 B-C; 一元操作符-表示对矩阵取负(矩阵中对应元素取负,返回一个临时矩阵): -C; 组合操作法+=或者-=表示(对应每隔元素都做相应操作):A += B 或者 A-=B 代码段1为矩阵的加减操作,代码如下: [cpp] view plaincopy

1. #include 2. #include 3. using namespace Eigen; 4. int main() 5. {

6. Matrix2d a; 7. a << 1, 2, 8. 3, 4;

9. MatrixXd b(2,2); 10.b << 2, 3, 11.1, 4;

12.std::cout << \"a + b =\\n\" << a + b << std::endl; 13.std::cout << \"a - b =\\n\" << a - b << std::endl; 14.std::cout << \"Doing a += b;\" << std::endl; 15.a += b;

16.std::cout << \"Now a =\\n\" << a << std::endl; 17.Vector3d v(1,2,3); 18.Vector3d w(1,0,0);

19.std::cout << \"-v + w - v =\\n\" << -v + w - v << std::endl; 20.} 输出结果为: a + b = 3 5 4 8 a - b = -1 -1 2 0

Doing a += b; Now a = 3 5 4 8

-v + w - v = -1 -4 -6

另外,矩阵还提供与标量(单一个数字)的乘除操作,表示每个元素都与该标量进行乘除操作。例如:

二元操作符*在:A*a中表示矩阵A中的每隔元素都与数字a相乘,结果放在一个临时矩阵中,矩阵的值不会改变。

对于a*A、A/a、A*=a、A /=a也是一样,例如下面的代码: [cpp] view plaincopy

1. #include 2. #include 3. using namespace Eigen; 4. int main() 5. {

6. Matrix2d a; 7. a << 1, 2, 8. 3, 4;

9. Vector3d v(1,2,3);

10.std::cout << \"a * 2.5 =\\n\" << a * 2.5 << std::endl; 11.std::cout << \"0.1 * v =\\n\" << 0.1 * v << std::endl; 12.std::cout << \"Doing v *= 2;\" << std::endl; 13.v *= 2;

14.std::cout << \"Now v =\\n\" << v << std::endl; 15.} 输出结果为: a * 2.5 = 2.5 5 7.5 10 0.1 * v = 0.1 0.2 0.3

Doing v *= 2; Now v = 2 4 6

需要注意:

在Eigen中,算术操作例如 “操作符+”并不会自己执行计算操作,他们只是返回一个“算术表达式对象”,而实际的计算则会延迟到后面的赋值时才进行。这些不影响你的使用,它只是为了方便Eigen的优化。

2、求矩阵的转秩、共轭矩阵、伴随矩阵。

可以通过 成员函数transpose(), conjugate(),和 adjoint()来完成,注意这些函数返回操作后的结果,而不会对原矩阵的元素进行直接操作,如果要让原矩阵的进行转换,则需要使用响应的InPlace函数,例如:transposeInPlace() 、 adjointInPlace() 之类。 例如下面的代码所示: [cpp] view plaincopy

1. MatrixXcf a = MatrixXcf::Random(2,2);

2. cout << \"Here is the matrix a\\n\" << a << endl;

3. cout << \"Here is the matrix a^T\\n\" << a.transpose() << endl; 4. cout << \"Here is the conjugate of a\\n\" << a.conjugate() << endl;

5. cout << \"Here is the matrix a^*\\n\" << a.adjoint() << endl; 输出结果为: Here is the matrix a (-0.211,0.68) (-0.605,0.823) (0.597,0.566) (0.536,-0.33) Here is the matrix a^T (-0.211,0.68) (0.597,0.566) (-0.605,0.823) (0.536,-0.33) Here is the conjugate of a (-0.211,-0.68) (-0.605,-0.823) (0.597,-0.566) (0.536,0.33) Here is the matrix a^* (-0.211,-0.68) (0.597,-0.566) (-0.605,-0.823) (0.536,0.33) 3、矩阵相乘、矩阵向量相乘 矩阵的相乘,矩阵与向量的相乘也是使用操作符*,共有*和*=两种操作符,其用法可以参考如下代码: [cpp] view plaincopy 1. #include 2. #include 3. using namespace Eigen; 4. int main() 5. { 6. Matrix2d mat; 7. mat << 1, 2, 8. 3, 4; 9. Vector2d u(-1,1), v(2,0); 10.std::cout << \"Here is mat*mat:\\n\" << mat*mat << std::endl; 11.std::cout << \"Here is mat*u:\\n\" << mat*u << std::endl; 12.std::cout << \"Here is u^T*mat:\\n\" << u.transpose()*mat << std::endl; 13.std::cout << \"Here is u^T*v:\\n\" << u.transpose()*v << std::endl; 14.std::cout << \"Here is u*v^T:\\n\" << u*v.transpose() << std::endl; 15.std::cout << \"Let's multiply mat by itself\" << std::endl; 16.mat = mat*mat; 17.std::cout << \"Now mat is mat:\\n\" << mat << std::endl; 18.} 输出结果为: Here is mat*mat: 7 10 15 22 Here is mat*u: 1 1 Here is u^T*mat: 2 2

Here is u^T*v: -2

Here is u*v^T: -2 -0 2 0

Let's multiply mat by itself Now mat is mat: 7 10 15 22

本节主要涉及Eigen的块操作以及QR分解 1、矩阵的块操作

1)矩阵的块操作有两种使用方法,其定义形式为: [cpp] view plaincopy

1. matrix.block(i,j,p,q); (1) 2.

3. matrix.block(i,j); (2) 定义(1)表示返回从矩阵的(i, j)开始,每行取p个元素,每列取q个元素所组成的临时新矩阵对象,原矩阵的元素不变。

定义(2)中block(p, q)可理解为一个p行q列的子矩阵,该定义表示从原矩阵中第(i, j)开始,获取一个p行q列的子矩阵,返回该子矩阵组成的临时 矩阵对象,原矩阵的元素不变。详细使用情况,可参考下面的代码段: [cpp] view plaincopy

1. #include 2. #include 3. using namespace std; 4. int main() 5. {

6. Eigen::MatrixXf m(4,4); 7. m << 1, 2, 3, 4, 8. 5, 6, 7, 8, 9. 9,10,11,12, 10.13,14,15,16;

11.cout << \"Block in the middle\" << endl; 12.cout << m.block<2,2>(1,1) << endl << endl; 13.for (int i = 1; i <= 3; ++i) 14.{

15.cout << \"Block of size \" << i << \"x\" << i << endl; 16.cout << m.block(0,0,i,i) << endl << endl; 17.} 18.}

输出的结果为: Block in the middle 6 7

10 11 Block of size 1x1 1 Block of size 2x2 1 2 5 6 Block of size 3x3 1 2 3 5 6 7 9 10 11 通过上述方式获取的子矩阵即可以作为左值也可以作为右值,也就是即可以用这个子矩阵给其他矩阵赋值,也可以给这个子矩阵对象赋值。 2)矩阵也提供了获取其指定行/列的函数,其实获取某行/列也是一种特殊的获取子块。可以通过 .col()和 .row()来完成获取指定列/行的操作,参数为列/行的索引。 注意: (1)需与获取矩阵的行数/列数的函数( rows(), cols() )的进行区别,不要弄混淆。 (2)函数参数为响应行/列的索引,需注意矩阵的行列均以0开始。 下面的代码段用于演示获取矩阵的指定行列: [cpp] view plaincopy 1. #include 2. #include 3. using namespace std; 4. int main() 5. { 6. Eigen::MatrixXf m(3,3); 7. m << 1,2,3, 8. 4,5,6, 9. 7,8,9; 10.cout << \"Here is the matrix m:\" << endl << m << endl; 11.cout << \"2nd Row: \" << m.row(1) << endl; 12.m.col(2) += 3 * m.col(0); 13.cout << \"After adding 3 times the first column into the third column, the matrix m is:\\n\"; 14.cout << m << endl; 15.} 输出结果为: Here is the matrix m: 1 2 3 4 5 6 7 8 9 2nd Row: 4 5 6 After adding 3 times the first column into the third column, the matrix m is: 1 2 6 4 5 18 7 8 30 3)向量的块操作,其实向量只是一个特殊的矩阵,但是Eigen也为它单独提供了一些简化的块操作,如下三种形式: 获取向量的前n个元素:vector.head(n); 获取向量尾部的n个元素:vector.tail(n); 获取从向量的第i个元素开始的n个元素:vector.segment(i,n); 其用法可参考如下代码段: [cpp] view plaincopy 1. #include 2. #include 3. using namespace std; 4. int main() 5. { 6. Eigen::ArrayXf v(6); 7. v << 1, 2, 3, 4, 5, 6; 8. cout << \"v.head(3) =\" << endl << v.head(3) << endl << endl; 9. cout << \"v.tail<3>() = \" << endl << v.tail<3>() << endl << endl; 10.v.segment(1,4) *= 2; 11.cout << \"after 'v.segment(1,4) *= 2', v =\" << endl << v << endl; 12.} 输出结果为: v.head(3) = 1 2 3 v.tail<3>() = 4 5 6 after 'v.segment(1,4) *= 2', v = 1 4 6 8 10 6 2、QR分解 Eigen的QR分解非常绕人,它总共提供了下面这些矩阵的分解方式: Decomposition Method Requirements on Speed Accuracy the matrix

PartialPivLUFullPivLU

partialPivLu() fullPivLu()

Invertible None None None

++ - ++ + -

+ +++ + ++ +++ + ++

HouseholderQRhouseholderQr()

ColPivHouseholderQRcolPivHouseholderQr()

FullPivHouseholderQRLLT

fullPivHouseholderQr() None llt()

Positive definite +++ Positive or negative semidefinite

+++

LDLT

ldlt()

由于我只用到了QR分解,而且Eigen的QR分解开始使用时确实不容易入手,因此这里只提供了householderQR的分解方式的演示代码: [cpp] view plaincopy

1. void QR2() 2. {

3. Matrix3d A; 4. A<<1,1,1,

5. 2,-1,-1, 6. 2,-4,5; 7.

8. HouseholderQR qr; 9. qr.compute(A);

10. MatrixXd R = qr.matrixQR().triangularView(); 11. MatrixXd Q = qr.householderQ();

12. std::cout << \"QR2(): HouseholderQR---------------------------------------------\"<< std::endl;

13. std::cout << \"A \"<< std::endl <14. std::cout <<\"qr.matrixQR()\"<< std::endl << qr.matrixQR() << std::endl << std::endl;

15. std::cout << \"R\"<< std::endl <16. std::cout << \"Q \"<< std::endl <17. std::cout <<\"Q*R\" << std::endl <3、一个矩阵使用的例子:用矩阵操作完成二维高斯拟合,并求取光斑中心

下面的代码段是一个使用Eigen的矩阵操作完成二维高斯拟合求取光点的代码例子,关于二维高斯拟合求取光点的详细内容可参考: [cpp] view plaincopy

1. bool GetCentrePoint(float& x0,float& y0) 2. {

3. if (m_iN<=0)

4. return false; 5. //QR分解

6. HouseholderQR qr; 7. qr.compute(m_matrix_B);

8. MatrixXf R = qr.matrixQR().triangularView(); 9. MatrixXf Q = qr.householderQ(); 10.

11. //块操作,获取向量或矩阵的局部 12. VectorXf S;

13. S = (Q.transpose()* m_Vector_A).head(5); 14. MatrixXf R1;

15. R1 = R.block(0,0,5,5); 16.

17. VectorXf C;

18. C = R1.inverse() * S; 19.

20. x0 = -0.5 * C[1] / C[3]; 21. y0 = -0.5 * C[2] / C[4]; 22.

23. return true; 24.}

1.首先,要把这个东东加到VS中,提供我们使用。

先下载,解压缩:

我的环境是 WIN7+VS2010 下载的3.2.2版本。

解压缩以后有这个文件夹:eigen-eigen-1306d75b4a21 恩,我只取了里面的 Eigen文件夹,

放到了VS2010文件夹下的vs_2010文件夹下VC文件夹下的include文件夹中, 也就是: 盘符:\\VS2010\\vs_2010\\VC\\include

然后就可以新建项目了,新建项目后,可以用: [cpp] view plaincopyprint?

1. #include \"Eigen/Eigen\" 2. using namespace Eigen;

加进来它的头文件,使用命名空间,and then 你就可以用它的函数了。 2.认识它的一些头文件。

Eigen这个类库,存的东西好多的,来看一下主要的几个头文件吧:

最上面那段英文意思是:

Eigen库分为 核心模块和额外模块两部分,

每个模块都有一个用这个模块所相对应的头文件,

Eigen和Dense头文件方便的同时包含了几个头文件以供使用。 ——Core

有关矩阵和数组的类,有基本的线性代数(包含 三角形 和 自伴乘积 相关),还有相应对数组的操作。 ——Geometry

几何学的类,有关转换、平移、进位制、2D旋转、3D旋转(四元组和角轴相关) ——LU

逻辑单元的类,有关求逆,求行列式,LU分解解算器(FullPivLU,PartialPivLU) ——Cholesky

包含LLT和LDLT的乔里斯基因式分解法。

(小科普:Cholesky分解是把一个对称正定的矩阵表示成一个下三角矩阵L和其转置的乘积的分解)

——Householder

豪斯霍尔德变换,这个模块供几个线性代数模块使用。 (Householder transform: 维基百科 ) ——SVD

奇异值分解,最小二乘解算器解决奇异值分解。 ——QR

QR分解求解,三种方法:HouseholderQR、ColPivHouseholderQR、FullPivHouseholderQR ——Eigenvalues

特征值和特征向量分解的方法:EigenSolver、SelfAdjointEigenSolver、ComplexEigenSolver ——Sparse

稀疏矩阵相关类,对于稀疏矩阵的存储及相关基本线性代数 ——Dense

包含: Core、Gelometry、LU、Cholesky、SVD、QR和Eigenvalues模块(头文件) ——Eigen

包含上述所有的模块(头文件) 3.对矩阵的简单操作

Eigen提供了两种密集的对象Matrix(矩阵)和Vector(向量)。 这两者是通过矩阵模板类和一维或二维的数组模板类来实现的。 这两者有几点不同:

——Matrix类型变量加减法,若行列数不相等,则不能做加减; Array类型的可以加减一个常数(各个元素分别加减该常数)。 ——Matrix与Array类型变量做乘法也会有不同,Matrix是矩阵相乘,Array是对应元素相乘。 ——但两者可以相互转换,方法为 .array() 和 .matrix()。

→①定义(注意:定义矩阵时,默认没有初始化,必须自己初始化) Eigen的矩阵类型,一般是Matrix后面跟类型符号来表示,比如说: ——' d ' 代表 double,矩阵存储的是double型的数据 ——' f ' 代表float,矩阵存储的是float类型数据 ——' c '代表complex,矩阵存数的是复数类型数据 ——' i '代表int,矩阵存储的是整数类型 相应关系为:

比如:

[cpp] view plaincopyprint?

1. MatrixXf m1(3,4); //建立3行4列的动态矩阵 2. MatrixXf m2(3,3);

3. Vector3f v1; //建立静态向量 X代表动态,f代表float型 →②初始化

[cpp] view plaincopyprint?

1. m1=MatrixXf::Zero(3,4); // 将矩阵3行4列初始化为0 2. m2=MatrixXf::Ones(3,3); // 将矩阵3行3列初始化为1 3. v1=Vector3f::Ones(); // 将3行的纵向量初始化为1 4.

5. cout<<\"m1=\\n\"<进一步,测试一下:

[cpp] view plaincopyprint?

1. MatrixXf m3(4,5);

2. m3=MatrixXf::Zero(4,5);

3. cout<<\"m3_1=\\n\"<初始化为0,4行5列,这时输出,就发现是4行5列的0 初始化为3行3列的1,输出,3行3列的1

初始化为6行6列的1,输出,则成为6行6列的1, 具体看图:

也就是说,矩阵的大小与初始化息息相关,初始化多少,它就是多少。

谁让它是动态的呢?!

那么,你肯定会说,定义的时候声明行列干啥? 因为,下种方法初始化,就需要行列值了: [cpp] view plaincopyprint?

1. MatrixXf m3(2,3); 2. m3<<1,2,3,4,5,6;

3. cout<<\"m3_1\\n\"<4. // 为了美观点,更像个矩阵,可以换行写 5. m3<<1.3,4,-8, 6. 0,0.9,2;

7. cout<<\"m3_2=\\n\"<→③访问

这个就很简单了,直接就同数组的访问方式, 但是不是方括号,而是圆括号: [cpp] view plaincopyprint?

1. MatrixXf m3(2,3); 2. m3<<1,2,3,4,5,6;

3. cout<<\"m3_1\\n\"<4. // 为了美观点,更像个矩阵,可以换行写 5. m3<<1.3,4,-8, 6. 0,0.9,2;

7. cout<<\"m3_2=\\n\"<10.cout<<\"m3_3=\\n\"<当然,同数组一样,第一行第一列的下标为(0,0)

4.矩阵的基础运算 代码执行了矩阵的:

——置0 ——置1 ——随机矩阵 ——单位阵 ——求逆 ——转置 ——数乘矩阵 [cpp] view plaincopyprint?

1. MatrixXf m1(3,3); 2. // 矩阵全部元素置0 3. m1.setZero();

4. cout<<\"m1_1=\\n\"<5. // 矩阵全部元素置1 ( 这里行列值不填,默认定义时候的行列, 6. // 若填写,则矩阵也会更改为填写的行列值 )

7. m1.setOnes(2,2);

8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 运行结果:

cout<<\"m1_2=\\n\"<cout<<\"m1_3=\\n\"<m1.setIdentity(3,3);

cout<<\"m1_4=\\n\"<cout<<\"m1_5=\\n\"<cout<<\"m1_6=\\n\"<// 数 * 矩阵 ( 数 / 矩阵 ) m1 = 2.6 * m1 ;

cout<<\"m1_7=\\n\"<啊,还有矩阵的加减乘除,这个不用写了吧?和平常的加减乘除一样的, 就是矩阵乘法要注意,两个矩阵的行列值哟~ 5.矩阵的高级运算

Eigen 矩阵定义

#include

Matrix A; // Fixed rows and cols. Same as Matrix3d. Matrix B; // Fixed rows, dynamic cols.

Matrix C; // Full dynamic. Same as MatrixXd. Matrix E; // Row major; default is column-major. Matrix3f P, Q, R; // 3x3 float matrix. Vector3f x, y, z; // 3x1 float matrix. RowVector3f a, b, c; // 1x3 float matrix.

VectorXd v; // Dynamic column vector of doubles // Eigen // Matlab // comments x.size() // length(x) // vector size C.rows() // size(C,1) // number of rows C.cols() // size(C,2) // number of columns x(i) // x(i+1) // Matlab is 1-based C(i,j) // C(i+1,j+1) //

Eigen 基础使用

// Basic usage

// Eigen // Matlab // comments x.size() // length(x) // vector size C.rows() // size(C,1) // number of rows C.cols() // size(C,2) // number of columns x(i) // x(i+1) // Matlab is 1-based C(i, j) // C(i+1,j+1) //

A.resize(4, 4); // Runtime error if assertions are on. B.resize(4, 9); // Runtime error if assertions are on. A.resize(3, 3); // Ok; size didn't change.

B.resize(3, 9); // Ok; only dynamic cols changed.

A << 1, 2, 3, // Initialize A. The elements can also be 4, 5, 6, // matrices, which are stacked along cols 7, 8, 9; // and then the rows are stacked.

B << A, A, A; // B is three horizontally stacked A's. A.fill(10); // Fill A with all 10's.

Eigen 特殊矩阵生成

// Eigen // Matlab

MatrixXd::Identity(rows,cols) // eye(rows,cols) C.setIdentity(rows,cols) // C = eye(rows,cols) MatrixXd::Zero(rows,cols) // zeros(rows,cols) C.setZero(rows,cols) // C = ones(rows,cols) MatrixXd::Ones(rows,cols) // ones(rows,cols) C.setOnes(rows,cols) // C = ones(rows,cols)

MatrixXd::Random(rows,cols) // rand(rows,cols)*2-1 // MatrixXd::Random returns uniform random numbers in (-1, 1). C.setRandom(rows,cols) // C = rand(rows,cols)*2-1 VectorXd::LinSpaced(size,low,high) // linspace(low,high,size)'

v.setLinSpaced(size,low,high) // v = linspace(low,high,size)'

Eigen 矩阵分块

// Matrix slicing and blocks. All expressions listed here are read/write. // Templated size versions are faster. Note that Matlab is 1-based (a size N // vector is x(1)...x(N)).

// Eigen // Matlab x.head(n) // x(1:n) x.head() // x(1:n)

x.tail(n) // x(end - n + 1: end) x.tail() // x(end - n + 1: end) x.segment(i, n) // x(i+1 : i+n) x.segment(i) // x(i+1 : i+n)

P.block(i, j, rows, cols) // P(i+1 : i+rows, j+1 : j+cols) P.block(i, j) // P(i+1 : i+rows, j+1 : j+cols) P.row(i) // P(i+1, :) P.col(j) // P(:, j+1) P.leftCols() // P(:, 1:cols) P.leftCols(cols) // P(:, 1:cols) P.middleCols(j) // P(:, j+1:j+cols) P.middleCols(j, cols) // P(:, j+1:j+cols) P.rightCols() // P(:, end-cols+1:end) P.rightCols(cols) // P(:, end-cols+1:end) P.topRows() // P(1:rows, :) P.topRows(rows) // P(1:rows, :) P.middleRows(i) // P(i+1:i+rows, :) P.middleRows(i, rows) // P(i+1:i+rows, :)

P.bottomRows() // P(end-rows+1:end, :) P.bottomRows(rows) // P(end-rows+1:end, :) P.topLeftCorner(rows, cols) // P(1:rows, 1:cols)

P.topRightCorner(rows, cols) // P(1:rows, end-cols+1:end) P.bottomLeftCorner(rows, cols) // P(end-rows+1:end, 1:cols)

P.bottomRightCorner(rows, cols) // P(end-rows+1:end, end-cols+1:end) P.topLeftCorner() // P(1:rows, 1:cols)

P.topRightCorner() // P(1:rows, end-cols+1:end) P.bottomLeftCorner() // P(end-rows+1:end, 1:cols)

P.bottomRightCorner() // P(end-rows+1:end, end-cols+1:end)

Eigen 矩阵元素交换 // Of particular note is Eigen's s which is highly optimized. // Eigen // Matlab

R.row(i) = P.col(j); // R(i, :) = P(:, i) R.col(j1).s(j2)); // R(:, [j1 j2]) = R(:, [j2, j1])

Eigen 矩阵转置

// Views, transpose, etc; all read-write except for .adjoint(). // Eigen // Matlab R.adjoint() // R'

R.transpose() // R.' or conj(R') R.diagonal() // diag(R) x.asDiagonal() // diag(x) R.transpose().colwise().reverse(); // rot90(R) R.conjugate() // conj(R)

Eigen 矩阵乘积

// All the same as Matlab, but matlab doesn't have *= style operators. // Matrix-vector. Matrix-matrix. Matrix-scalar. y = M*x; R = P*Q; R = P*s; a = b*M; R = P - Q; R = s*P; a *= M; R = P + Q; R = P/s; R *= Q; R = s*P; R += Q; R *= s; R -= Q; R /= s;

Eigen 矩阵单个元素操作

// Vectorized operations on each element independently // Eigen // Matlab R = P.cwiseProduct(Q); // R = P .* Q R = P.array() * s.array();// R = P .* s R = P.cwiseQuotient(Q); // R = P ./ Q R = P.array() / Q.array();// R = P ./ Q R = P.array() + s.array();// R = P + s R = P.array() - s.array();// R = P - s R.array() += s; // R = R + s R.array() -= s; // R = R - s R.array() < Q.array(); // R < Q R.array() <= Q.array(); // R <= Q R.cwiseInverse(); // 1 ./ P R.array().inverse(); // 1 ./ P R.array().sin() // sin(P) R.array().cos() // cos(P) R.array().pow(s) // P .^ s R.array().square() // P .^ 2 R.array().cube() // P .^ 3 R.cwiseSqrt() // sqrt(P) R.array().sqrt() // sqrt(P) R.array().exp() // exp(P) R.array().log() // log(P) R.cwiseMax(P) // max(R, P) R.array().max(P.array()) // max(R, P) R.cwiseMin(P) // min(R, P) R.array().min(P.array()) // min(R, P) R.cwiseAbs() // abs(P) R.array().abs() // abs(P) R.cwiseAbs2() // abs(P.^2) R.array().abs2() // abs(P.^2)

(R.array() < s).select(P,Q); // (R < s ? P : Q)

Eigen 矩阵化简

// Reductions. int r, c;

// Eigen // Matlab R.minCoeff() // min(R(:))

R.maxCoeff() // max(R(:))

s = R.minCoeff(&r, &c) // [s, i] = min(R(:)); [r, c] = ind2sub(size(R), i); s = R.maxCoeff(&r, &c) // [s, i] = max(R(:)); [r, c] = ind2sub(size(R), i); R.sum() // sum(R(:)) R.colwise().sum() // sum(R)

R.rowwise().sum() // sum(R, 2) or sum(R')' R.prod() // prod(R(:)) R.colwise().prod() // prod(R)

R.rowwise().prod() // prod(R, 2) or prod(R')' R.trace() // trace(R) R.all() // all(R(:)) R.colwise().all() // all(R) R.rowwise().all() // all(R, 2) R.any() // any(R(:)) R.colwise().any() // any(R) R.rowwise().any() // any(R, 2)

Eigen 矩阵点乘 // Dot products, norms, etc.

// Eigen // Matlab

x.norm() // norm(x). Note that norm(R) doesn't work in Eigen. x.squaredNorm() // dot(x, x) Note the equivalence is not true for complex x.dot(y) // dot(x, y)

x.cross(y) // cross(x, y) Requires #include

Eigen 矩阵类型转换

//// Type conversion

// Eigen // Matlab A.cast(); // double(A) A.cast(); // single(A) A.cast(); // int32(A) A.real(); // real(A) A.imag(); // imag(A)

// if the original type equals destination type, no work is done

Eigen 求解线性方程组 Ax = b

// Solve Ax = b. Result stored in x. Matlab: x = A \\ b.

x = A.ldlt().solve(b)); // A sym. p.s.d. #include x = A.llt() .solve(b)); // A sym. p.d. #include x = A.lu() .solve(b)); // Stable and fast. #include x = A.qr() .solve(b)); // No pivoting. #include x = A.svd() .solve(b)); // Stable, slowest. #include // .ldlt() -> .matrixL() and .matrixD() // .llt() -> .matrixL()

// .lu() -> .matrixL() and .matrixU() // .qr() -> .matrixQ() and .matrixR()

// .svd() -> .matrixU(), .singularValues(), and .matrixV()

Eigen 矩阵特征值

// Eigenvalue problems

// Eigen // Matlab A.eigenvalues(); // eig(A);

EigenSolver eig(A); // [vec val] = eig(A) eig.eigenvalues(); // diag(val) eig.eigenvectors(); // vec

// For self-adjoint matrices use SelfAdjointEigenSolver<>