Eigen库的基本使用方法、PCL计算协方差矩阵

转载自:https://blog.csdn.net/r1254/article/details/47418871

以及https://blog.csdn.net/wokaowokaowokao12345/article/details/53397488

第一部分:

1.1前言

Eigen是一个高层次的C ++库,有效支持 得到的线性代数,矩阵和矢量运算,数值分析及其相关的算法。

1.2配置

关于Eigen库的配置只需要在属性表包含目录中添加Eigen路径即可。 
这里写图片描述

1.3例子

Example 1:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. void main()
  4. {
  5. Eigen:: MatrixXd m(2, 2); //声明一个MatrixXd类型的变量,它是2*2的矩阵,未初始化
  6. m( 0, 0) = 3; //将矩阵第1个元素初始化3
  7. m( 1, 0) = 2.5; //将矩阵第3个元素初始化3
  8. m( 0, 1) = -1;
  9. m( 1, 1) = m( 1, 0) + m( 0, 1);
  10. std:: cout << m << std:: endl;
  11. }
  •  

Eigen头文件定义了很多类型,但对于简单的应用程序,可能只使用MatrixXd类型。 这表示任意大小的矩阵(MatrixXd中的X),其中每个条目是双精度(MatrixXd中的d)。 Eigen / Dense头文件定义了MatrixXd类型和相关类型的所有成员函数。 在这个头文件中定义的所有类和函数都在特征名称空间中。

这里写图片描述

Example 2:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. MatrixXd m = MatrixXd::Random( 3, 3); //使用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. }
  •  

    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. Matrix3d m = Matrix3d::Random(); //使用Random随机初始化固定大小的3*3的矩阵
  8. m = (m + Matrix3d::Constant( 1.2)) * 50;
  9. cout << "m =" << endl << m << endl; Vector3d v(1,2,3);
  10. cout << "m * v =" << endl << m * v << endl;
  11. }
  •  

Matrix&Vector

Example 3:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  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. }
  •  

逗号初始化

Example 4:


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

通过Resize调整矩阵大小

矩阵的当前大小可以通过rows(),cols()和size()检索。 这些方法分别返回行数,列数和系数数。 通过resize()方法调整动态大小矩阵的大小。 
Example 5:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. MatrixXd m(2,5); //初始化大小2*5
  7. m.resize( 4, 3); //重新调整为4*3
  8. std:: cout << "The matrix m is of size " << m.rows() << "x" << m.cols() << std:: endl;
  9. std:: cout << "It has " << m.size() << " coefficients" << std:: endl;
  10. VectorXd v(2); v.resize( 5);
  11. std:: cout << "The vector v is of size " << v.size() << std:: endl;
  12. std:: cout << "As a matrix, v is of size " << v.rows() << "x" << v.cols() << std:: endl;
  13. }
  •  

通过赋值调整矩阵大小

Example 6:


    
    
  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;
  •  

Eigen + - * 等运算

Eigen通过通用的C ++算术运算符(例如+, - ,)或通过特殊方法(如dot(),cross()等)的重载提供矩阵/向量算术运算。对于Matrix类(矩阵和向量) 只被重载以支持线性代数运算。 例如,matrix1 matrix2表示矩阵矩阵乘积。 
Example 7:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d a; a << 1, 2, 3, 4;
  7. MatrixXd b(2,2);
  8. b << 2, 3, 1, 4;
  9. std:: cout << "a + b =\n" << a + b << std:: endl;
  10. std:: cout << "a - b =\n" << a - b << std:: endl;
  11. std:: cout << "Doing a += b;" << std:: endl;
  12. a += b;
  13. std:: cout << "Now a =\n" << a << std:: endl;
  14. Vector3d v(1,2,3);
  15. Vector3d w(1,0,0);
  16. std:: cout << "-v + w - v =\n" << -v + w - v << std:: endl;
  17. }
  •  

Example 8:


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d a;
  7. a << 1, 2, 3, 4;
  8. Vector3d v(1,2,3);
  9. std:: cout << "a * 2.5 =\n" << a * 2.5 << std:: endl;
  10. std:: cout << "0.1 * v =\n" << 0.1 * v << std:: endl;
  11. std:: cout << "Doing v *= 2;" << std:: endl; v *= 2;
  12. std:: cout << "Now v =\n" << v << std:: endl;
  13. }
  •  

矩阵转置、共轭和伴随矩阵


    
    
  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;
  •  

禁止如下操作:

a = a.transpose(); // !!! do NOT do this !!!
    
    
  •  

但是可以使用如下函数:

a.transposeInPlace();
    
    
  •  

此时a被其转置替换。


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2i a;
  7. a << 1, 2, 3, 4;
  8. std:: cout << "Here is the matrix a:\n" << a << std:: endl;
  9. a = a.transpose(); // !!! do NOT do this !!!
  10. std:: cout << "and the result of the aliasing effect:\n" << a << std:: endl;
  11. }
  •  

矩阵* 矩阵和矩阵* 向量操作


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d mat; mat << 1, 2, 3, 4;
  7. Vector2d u( -1, 1), v( 2, 0);
  8. std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
  9. std::cout << "Here is mat*u:\n" << mat*u << std::endl;
  10. std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
  11. std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
  12. std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
  13. std::cout << "Let's multiply mat by itself" << std::endl;
  14. mat = mat*mat; std::cout << "Now mat is mat:\n" << mat << std::endl;
  15. }
  •  

点乘和叉乘

对于点积和叉乘积,需要使用dot()和cross()方法。


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. Vector3d v(1,2,3);
  8. Vector3d w(0,1,2);
  9. cout << "Dot product: " << v.dot(w) << endl;
  10. double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
  11. cout << "Dot product via a matrix product: " << dp << endl;
  12. cout << "Cross product:\n" << v.cross(w) << endl;
  13. }
  •  

    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. int main()
  5. {
  6. Eigen::Matrix2d mat;
  7. mat << 1, 2, 3, 4;
  8. cout << "Here is mat.sum(): " << mat.sum() << endl;
  9. cout << "Here is mat.prod(): " << mat.prod() << endl;
  10. cout << "Here is mat.mean(): " << mat.mean() << endl;
  11. cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl;
  12. cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl;
  13. cout << "Here is mat.trace(): " << mat.trace() << endl;
  14. }
  •  

数组的运算(未完待续)
Eigen最小二乘估计

最小平方求解的最好方法是使用SVD分解。 Eigen提供一个作为JacobiSVD类,它的solve()是做最小二乘解。式子为Ax=b 
经过和Matlab对比。


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. MatrixXf A = MatrixXf::Random( 3, 2);
  8. cout << "Here is the matrix A:\n" << A << endl;
  9. VectorXf b = VectorXf::Random( 3);
  10. cout << "Here is the right hand side b:\n" << b << endl;
  11. cout << "The least-squares solution is:\n" << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
  12. }
  •  

这里写图片描述

第二部分:

矩阵、向量初始化


    
    
  1. #include <iostream>
  2. #include "Eigen/Dense"
  3. using namespace Eigen;
  4. int main()
  5. {
  6. MatrixXf m1(3,4); //动态矩阵,建立3行4列。
  7. MatrixXf m2(4,3); //4行3列,依此类推。
  8. MatrixXf m3(3,3);
  9. Vector3f v1; //若是静态数组,则不用指定行或者列
  10. /* 初始化 */
  11. Matrix3d m = Matrix3d::Random();
  12. m1 = MatrixXf::Zero( 3, 4); //用0矩阵初始化,要指定行列数
  13. m2 = MatrixXf::Zero( 4, 3);
  14. m3 = MatrixXf::Identity( 3, 3); //用单位矩阵初始化
  15. v1 = Vector3f::Zero(); //同理,若是静态的,不用指定行列数
  16. m1 << 1, 0, 0, 1, //也可以以这种方式初始化
  17. 1, 5, 0, 1,
  18. 0, 0, 9, 1;
  19. m2 << 1, 0, 0,
  20. 0, 4, 0,
  21. 0, 0, 7,
  22. 1, 1, 1;
  23. //向量初始化,与矩阵类似
  24. Vector3d v3(1,2,3);
  25. VectorXf vx(30);
  26. }
  •  

C++数组和矩阵转换

使用Map函数,可以实现Eigen的矩阵和c++中的数组直接转换,语法如下:


    
    
  1. //@param MatrixType 矩阵类型
  2. //@param MapOptions 可选参数,指的是指针是否对齐,Aligned, or Unaligned. The default is Unaligned.
  3. //@param StrideType 可选参数,步长
  4. /*
  5. Map<typename MatrixType,
  6. int MapOptions,
  7. typename StrideType>
  8. */
  9. int i;
  10. //数组转矩阵
  11. double *aMat = new double[ 20];
  12. for(i = 0;i< 20;i++)
  13. {
  14. aMat[i] = rand()% 11;
  15. }
  16. //静态矩阵,编译时确定维数 Matrix<double,4,5>
  17. Eigen:Map<Matrix< double, 4, 5> > staMat(aMat);
  18. //输出
  19. for ( int i = 0; i < staMat.size(); i++)
  20. std:: cout << *(staMat.data() + i) << " ";
  21. std:: cout << std:: endl << std:: endl;
  22. //动态矩阵,运行时确定 MatrixXd
  23. Map<MatrixXd> dymMat(aMat, 4, 5);
  24. //输出,应该和上面一致
  25. for ( int i = 0; i < dymMat.size(); i++)
  26. std:: cout << *(dymMat.data() + i) << " ";
  27. std:: cout << std:: endl << std:: endl;
  28. //Matrix中的数据存在一维数组中,默认是行优先的格式,即一行行的存
  29. //data()返回Matrix中的指针
  30. dymMat.data();
  •  

矩阵基础操作

eigen重载了基础的+ - * / += -= = /= 可以表示标量和矩阵或者矩阵和矩阵


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. //单个取值,单个赋值
  7. double value00 = staMat( 0, 0);
  8. double value10 = staMat( 1, 0);
  9. staMat( 0, 0) = 100;
  10. std:: cout << value00 <<value10<< std:: endl;
  11. std:: cout <<staMat<< std:: endl<< std:: endl;
  12. //加减乘除示例 Matrix2d 等同于 Matrix<double,2,2>
  13. Matrix2d a;
  14. a << 1, 2,
  15. 3, 4;
  16. MatrixXd b(2,2);
  17. b << 2, 3,
  18. 1, 4;
  19. Matrix2d c = a + b;
  20. std:: cout<< c<< std:: endl<< std:: endl;
  21. c = a - b;
  22. std:: cout<<c<< std:: endl<< std:: endl;
  23. c = a * 2;
  24. std:: cout<<c<< std:: endl<< std:: endl;
  25. c = 2.5 * a;
  26. std:: cout<<c<< std:: endl<< std:: endl;
  27. c = a / 2;
  28. std:: cout<<c<< std:: endl<< std:: endl;
  29. c = a * b;
  30. std:: cout<<c<< std:: endl<< std:: endl;
  •  

点积和叉积


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. //点积、叉积(针对向量的)
  8. Vector3d v(1,2,3);
  9. Vector3d w(0,1,2);
  10. std:: cout<<v.dot(w)<< std:: endl<< std:: endl;
  11. std:: cout<<w.cross(v)<< std:: endl<< std:: endl;
  12. }
  13. */
  •  

转置、伴随、行列式、逆矩阵

小矩阵(4 * 4及以下)eigen会自动优化,默认采用LU分解,效率不高


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. Matrix2d c;
  8. c << 1, 2,
  9. 3, 4;
  10. //转置、伴随
  11. std:: cout<<c<< std:: endl<< std:: endl;
  12. std:: cout<< "转置\n"<<c.transpose()<< std:: endl<< std:: endl;
  13. std:: cout<< "伴随\n"<<c.adjoint()<< std:: endl<< std:: endl;
  14. //逆矩阵、行列式
  15. std:: cout << "行列式: " << c.determinant() << std:: endl;
  16. std:: cout << "逆矩阵\n" << c.inverse() << std:: endl;
  17. }
  •  

计算特征值和特征向量


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. //特征向量、特征值
  8. std:: cout << "Here is the matrix A:\n" << a << std:: endl;
  9. SelfAdjointEigenSolver<Matrix2d> eigensolver(a);
  10. if (eigensolver.info() != Success) abort();
  11. std:: cout << "特征值:\n" << eigensolver.eigenvalues() << std:: endl;
  12. std:: cout << "Here's a matrix whose columns are eigenvectors of A \n"
  13. << "corresponding to these eigenvalues:\n"
  14. << eigensolver.eigenvectors() << std:: endl;
  15. }
  •  

解线性方程


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. //线性方程求解 Ax =B;
  8. Matrix4d A;
  9. A << 2, -1, -1, 1,
  10. 1, 1, -2, 1,
  11. 4, -6, 2, -2,
  12. 3, 6, -9, 7;
  13. Vector4d B(2,4,4,9);
  14. Vector4d x = A.colPivHouseholderQr().solve(B);
  15. Vector4d x2 = A.llt().solve(B);
  16. Vector4d x3 = A.ldlt().solve(B);
  17. std:: cout << "The solution is:\n" << x << "\n\n"<<x2<< "\n\n"<<x3 << std:: endl;
  18. }
  •  

除了colPivHouseholderQr、LLT、LDLT,还有以下的函数可以求解线性方程组,请注意精度和速度: 解小矩阵(4*4)基本没有速度差别

最小二乘求解

最小二乘求解有两种方式,jacobiSvd或者colPivHouseholderQr,4*4以下的小矩阵速度没有区别,jacobiSvd可能更快,大矩阵最好用colPivHouseholderQr


    
    
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. MatrixXf A1 = MatrixXf::Random( 3, 2);
  8. std:: cout << "Here is the matrix A:\n" << A1 << std:: endl;
  9. VectorXf b1 = VectorXf::Random( 3);
  10. std:: cout << "Here is the right hand side b:\n" << b1 << std:: endl;
  11. //jacobiSvd 方式:Slow (but fast for small matrices)
  12. std:: cout << "The least-squares solution is:\n"
  13. << A1.jacobiSvd(ComputeThinU | ComputeThinV).solve(b1) << std:: endl;
  14. //colPivHouseholderQr方法:fast
  15. std:: cout << "The least-squares solution is:\n"
  16. << A1.colPivHouseholderQr().solve(b1) << std:: endl;
  17. }
  •  

稀疏矩阵

稀疏矩阵的头文件包括:

#include


    
    
  1. typedef Eigen::Triplet< double> T;
  2. std:: vector<T> tripletList;
  3. triplets.reserve(estimation_of_entries); //estimation_of_entries是预估的条目
  4. for(...)
  5. {
  6. tripletList.push_back(T(i,j,v_ij)); //第 i,j个有值的位置的值
  7. }
  8. SparseMatrixType mat(rows,cols);
  9. mat.setFromTriplets(tripletList.begin(), tripletList.end());
  10. // mat is ready to go!
  •  

2.直接将已知的非0值插入


    
    
  1. SparseMatrix<double> mat(rows,cols);
  2. mat.reserve(VectorXi::Constant(cols, 6));
  3. for(...)
  4. {
  5. // i,j 个非零值 v_ij != 0
  6. mat.insert(i,j) = v_ij;
  7. }
  8. mat.makeCompressed(); // optional
  •  

稀疏矩阵支持大部分一元和二元运算:

sm1.real() sm1.imag() -sm1 0.5*sm1 
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2) 
二元运算中,稀疏矩阵和普通矩阵可以混合使用

//dm表示普通矩阵 
dm2 = sm1 + dm1; 
也支持计算转置矩阵和伴随矩阵

参考以下链接

点击这里跳转查看更多

第三部分:

其他相关博客:

1、单独下载与安装:https://blog.csdn.net/augusdi/article/details/12907341

2、一篇较详细的教程:https://blog.csdn.net/wzaltzap/article/details/79501856

3、计算特征值特征向量:https://blog.csdn.net/wokaowokaowokao12345/article/details/47375427

            </div>

转载自:https://blog.csdn.net/r1254/article/details/47418871

以及https://blog.csdn.net/wokaowokaowokao12345/article/details/53397488

第一部分:

1.1前言

Eigen是一个高层次的C ++库,有效支持 得到的线性代数,矩阵和矢量运算,数值分析及其相关的算法。

1.2配置

关于Eigen库的配置只需要在属性表包含目录中添加Eigen路径即可。 
这里写图片描述

1.3例子

Example 1:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. void main()
  4. {
  5. Eigen:: MatrixXd m(2, 2); //声明一个MatrixXd类型的变量,它是2*2的矩阵,未初始化
  6. m( 0, 0) = 3; //将矩阵第1个元素初始化3
  7. m( 1, 0) = 2.5; //将矩阵第3个元素初始化3
  8. m( 0, 1) = -1;
  9. m( 1, 1) = m( 1, 0) + m( 0, 1);
  10. std:: cout << m << std:: endl;
  11. }
  •  

Eigen头文件定义了很多类型,但对于简单的应用程序,可能只使用MatrixXd类型。 这表示任意大小的矩阵(MatrixXd中的X),其中每个条目是双精度(MatrixXd中的d)。 Eigen / Dense头文件定义了MatrixXd类型和相关类型的所有成员函数。 在这个头文件中定义的所有类和函数都在特征名称空间中。

这里写图片描述

Example 2:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. MatrixXd m = MatrixXd::Random( 3, 3); //使用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. }
  •  

  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. Matrix3d m = Matrix3d::Random(); //使用Random随机初始化固定大小的3*3的矩阵
  8. m = (m + Matrix3d::Constant( 1.2)) * 50;
  9. cout << "m =" << endl << m << endl; Vector3d v(1,2,3);
  10. cout << "m * v =" << endl << m * v << endl;
  11. }
  •  

Matrix&Vector

Example 3:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  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. }
  •  

逗号初始化

Example 4:


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

通过Resize调整矩阵大小

矩阵的当前大小可以通过rows(),cols()和size()检索。 这些方法分别返回行数,列数和系数数。 通过resize()方法调整动态大小矩阵的大小。 
Example 5:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. MatrixXd m(2,5); //初始化大小2*5
  7. m.resize( 4, 3); //重新调整为4*3
  8. std:: cout << "The matrix m is of size " << m.rows() << "x" << m.cols() << std:: endl;
  9. std:: cout << "It has " << m.size() << " coefficients" << std:: endl;
  10. VectorXd v(2); v.resize( 5);
  11. std:: cout << "The vector v is of size " << v.size() << std:: endl;
  12. std:: cout << "As a matrix, v is of size " << v.rows() << "x" << v.cols() << std:: endl;
  13. }
  •  

通过赋值调整矩阵大小

Example 6:


  
  
  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;
  •  

Eigen + - * 等运算

Eigen通过通用的C ++算术运算符(例如+, - ,)或通过特殊方法(如dot(),cross()等)的重载提供矩阵/向量算术运算。对于Matrix类(矩阵和向量) 只被重载以支持线性代数运算。 例如,matrix1 matrix2表示矩阵矩阵乘积。 
Example 7:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d a; a << 1, 2, 3, 4;
  7. MatrixXd b(2,2);
  8. b << 2, 3, 1, 4;
  9. std:: cout << "a + b =\n" << a + b << std:: endl;
  10. std:: cout << "a - b =\n" << a - b << std:: endl;
  11. std:: cout << "Doing a += b;" << std:: endl;
  12. a += b;
  13. std:: cout << "Now a =\n" << a << std:: endl;
  14. Vector3d v(1,2,3);
  15. Vector3d w(1,0,0);
  16. std:: cout << "-v + w - v =\n" << -v + w - v << std:: endl;
  17. }
  •  

Example 8:


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d a;
  7. a << 1, 2, 3, 4;
  8. Vector3d v(1,2,3);
  9. std:: cout << "a * 2.5 =\n" << a * 2.5 << std:: endl;
  10. std:: cout << "0.1 * v =\n" << 0.1 * v << std:: endl;
  11. std:: cout << "Doing v *= 2;" << std:: endl; v *= 2;
  12. std:: cout << "Now v =\n" << v << std:: endl;
  13. }
  •  

矩阵转置、共轭和伴随矩阵


  
  
  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;
  •  

禁止如下操作:

a = a.transpose(); // !!! do NOT do this !!!
  
  
  •  

但是可以使用如下函数:

a.transposeInPlace();
  
  
  •  

此时a被其转置替换。


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2i a;
  7. a << 1, 2, 3, 4;
  8. std:: cout << "Here is the matrix a:\n" << a << std:: endl;
  9. a = a.transpose(); // !!! do NOT do this !!!
  10. std:: cout << "and the result of the aliasing effect:\n" << a << std:: endl;
  11. }
  •  

矩阵* 矩阵和矩阵* 向量操作


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. Matrix2d mat; mat << 1, 2, 3, 4;
  7. Vector2d u( -1, 1), v( 2, 0);
  8. std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
  9. std::cout << "Here is mat*u:\n" << mat*u << std::endl;
  10. std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
  11. std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
  12. std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
  13. std::cout << "Let's multiply mat by itself" << std::endl;
  14. mat = mat*mat; std::cout << "Now mat is mat:\n" << mat << std::endl;
  15. }
  •  

点乘和叉乘

对于点积和叉乘积,需要使用dot()和cross()方法。


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. Vector3d v(1,2,3);
  8. Vector3d w(0,1,2);
  9. cout << "Dot product: " << v.dot(w) << endl;
  10. double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
  11. cout << "Dot product via a matrix product: " << dp << endl;
  12. cout << "Cross product:\n" << v.cross(w) << endl;
  13. }
  •  

  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. int main()
  5. {
  6. Eigen::Matrix2d mat;
  7. mat << 1, 2, 3, 4;
  8. cout << "Here is mat.sum(): " << mat.sum() << endl;
  9. cout << "Here is mat.prod(): " << mat.prod() << endl;
  10. cout << "Here is mat.mean(): " << mat.mean() << endl;
  11. cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl;
  12. cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl;
  13. cout << "Here is mat.trace(): " << mat.trace() << endl;
  14. }
  •  

数组的运算(未完待续)
Eigen最小二乘估计

最小平方求解的最好方法是使用SVD分解。 Eigen提供一个作为JacobiSVD类,它的solve()是做最小二乘解。式子为Ax=b 
经过和Matlab对比。


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. MatrixXf A = MatrixXf::Random( 3, 2);
  8. cout << "Here is the matrix A:\n" << A << endl;
  9. VectorXf b = VectorXf::Random( 3);
  10. cout << "Here is the right hand side b:\n" << b << endl;
  11. cout << "The least-squares solution is:\n" << A.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
  12. }
  •  

这里写图片描述

第二部分:

矩阵、向量初始化


  
  
  1. #include <iostream>
  2. #include "Eigen/Dense"
  3. using namespace Eigen;
  4. int main()
  5. {
  6. MatrixXf m1(3,4); //动态矩阵,建立3行4列。
  7. MatrixXf m2(4,3); //4行3列,依此类推。
  8. MatrixXf m3(3,3);
  9. Vector3f v1; //若是静态数组,则不用指定行或者列
  10. /* 初始化 */
  11. Matrix3d m = Matrix3d::Random();
  12. m1 = MatrixXf::Zero( 3, 4); //用0矩阵初始化,要指定行列数
  13. m2 = MatrixXf::Zero( 4, 3);
  14. m3 = MatrixXf::Identity( 3, 3); //用单位矩阵初始化
  15. v1 = Vector3f::Zero(); //同理,若是静态的,不用指定行列数
  16. m1 << 1, 0, 0, 1, //也可以以这种方式初始化
  17. 1, 5, 0, 1,
  18. 0, 0, 9, 1;
  19. m2 << 1, 0, 0,
  20. 0, 4, 0,
  21. 0, 0, 7,
  22. 1, 1, 1;
  23. //向量初始化,与矩阵类似
  24. Vector3d v3(1,2,3);
  25. VectorXf vx(30);
  26. }
  •  

C++数组和矩阵转换

使用Map函数,可以实现Eigen的矩阵和c++中的数组直接转换,语法如下:


  
  
  1. //@param MatrixType 矩阵类型
  2. //@param MapOptions 可选参数,指的是指针是否对齐,Aligned, or Unaligned. The default is Unaligned.
  3. //@param StrideType 可选参数,步长
  4. /*
  5. Map<typename MatrixType,
  6. int MapOptions,
  7. typename StrideType>
  8. */
  9. int i;
  10. //数组转矩阵
  11. double *aMat = new double[ 20];
  12. for(i = 0;i< 20;i++)
  13. {
  14. aMat[i] = rand()% 11;
  15. }
  16. //静态矩阵,编译时确定维数 Matrix<double,4,5>
  17. Eigen:Map<Matrix< double, 4, 5> > staMat(aMat);
  18. //输出
  19. for ( int i = 0; i < staMat.size(); i++)
  20. std:: cout << *(staMat.data() + i) << " ";
  21. std:: cout << std:: endl << std:: endl;
  22. //动态矩阵,运行时确定 MatrixXd
  23. Map<MatrixXd> dymMat(aMat, 4, 5);
  24. //输出,应该和上面一致
  25. for ( int i = 0; i < dymMat.size(); i++)
  26. std:: cout << *(dymMat.data() + i) << " ";
  27. std:: cout << std:: endl << std:: endl;
  28. //Matrix中的数据存在一维数组中,默认是行优先的格式,即一行行的存
  29. //data()返回Matrix中的指针
  30. dymMat.data();
  •  

矩阵基础操作

eigen重载了基础的+ - * / += -= = /= 可以表示标量和矩阵或者矩阵和矩阵


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. int main()
  5. {
  6. //单个取值,单个赋值
  7. double value00 = staMat( 0, 0);
  8. double value10 = staMat( 1, 0);
  9. staMat( 0, 0) = 100;
  10. std:: cout << value00 <<value10<< std:: endl;
  11. std:: cout <<staMat<< std:: endl<< std:: endl;
  12. //加减乘除示例 Matrix2d 等同于 Matrix<double,2,2>
  13. Matrix2d a;
  14. a << 1, 2,
  15. 3, 4;
  16. MatrixXd b(2,2);
  17. b << 2, 3,
  18. 1, 4;
  19. Matrix2d c = a + b;
  20. std:: cout<< c<< std:: endl<< std:: endl;
  21. c = a - b;
  22. std:: cout<<c<< std:: endl<< std:: endl;
  23. c = a * 2;
  24. std:: cout<<c<< std:: endl<< std:: endl;
  25. c = 2.5 * a;
  26. std:: cout<<c<< std:: endl<< std:: endl;
  27. c = a / 2;
  28. std:: cout<<c<< std:: endl<< std:: endl;
  29. c = a * b;
  30. std:: cout<<c<< std:: endl<< std:: endl;
  •  

点积和叉积


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace Eigen;
  4. using namespace std;
  5. int main()
  6. {
  7. //点积、叉积(针对向量的)
  8. Vector3d v(1,2,3);
  9. Vector3d w(0,1,2);
  10. std:: cout<<v.dot(w)<< std:: endl<< std:: endl;
  11. std:: cout<<w.cross(v)<< std:: endl<< std:: endl;
  12. }
  13. */
  •  

转置、伴随、行列式、逆矩阵

小矩阵(4 * 4及以下)eigen会自动优化,默认采用LU分解,效率不高


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. Matrix2d c;
  8. c << 1, 2,
  9. 3, 4;
  10. //转置、伴随
  11. std:: cout<<c<< std:: endl<< std:: endl;
  12. std:: cout<< "转置\n"<<c.transpose()<< std:: endl<< std:: endl;
  13. std:: cout<< "伴随\n"<<c.adjoint()<< std:: endl<< std:: endl;
  14. //逆矩阵、行列式
  15. std:: cout << "行列式: " << c.determinant() << std:: endl;
  16. std:: cout << "逆矩阵\n" << c.inverse() << std:: endl;
  17. }
  •  

计算特征值和特征向量


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. //特征向量、特征值
  8. std:: cout << "Here is the matrix A:\n" << a << std:: endl;
  9. SelfAdjointEigenSolver<Matrix2d> eigensolver(a);
  10. if (eigensolver.info() != Success) abort();
  11. std:: cout << "特征值:\n" << eigensolver.eigenvalues() << std:: endl;
  12. std:: cout << "Here's a matrix whose columns are eigenvectors of A \n"
  13. << "corresponding to these eigenvalues:\n"
  14. << eigensolver.eigenvectors() << std:: endl;
  15. }
  •  

解线性方程


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. //线性方程求解 Ax =B;
  8. Matrix4d A;
  9. A << 2, -1, -1, 1,
  10. 1, 1, -2, 1,
  11. 4, -6, 2, -2,
  12. 3, 6, -9, 7;
  13. Vector4d B(2,4,4,9);
  14. Vector4d x = A.colPivHouseholderQr().solve(B);
  15. Vector4d x2 = A.llt().solve(B);
  16. Vector4d x3 = A.ldlt().solve(B);
  17. std:: cout << "The solution is:\n" << x << "\n\n"<<x2<< "\n\n"<<x3 << std:: endl;
  18. }
  •  

除了colPivHouseholderQr、LLT、LDLT,还有以下的函数可以求解线性方程组,请注意精度和速度: 解小矩阵(4*4)基本没有速度差别

最小二乘求解

最小二乘求解有两种方式,jacobiSvd或者colPivHouseholderQr,4*4以下的小矩阵速度没有区别,jacobiSvd可能更快,大矩阵最好用colPivHouseholderQr


  
  
  1. #include <iostream>
  2. #include <Eigen/Dense>
  3. using namespace std;
  4. using namespace Eigen;
  5. int main()
  6. {
  7. MatrixXf A1 = MatrixXf::Random( 3, 2);
  8. std:: cout << "Here is the matrix A:\n" << A1 << std:: endl;
  9. VectorXf b1 = VectorXf::Random( 3);
  10. std:: cout << "Here is the right hand side b:\n" << b1 << std:: endl;
  11. //jacobiSvd 方式:Slow (but fast for small matrices)
  12. std:: cout << "The least-squares solution is:\n"
  13. << A1.jacobiSvd(ComputeThinU | ComputeThinV).solve(b1) << std:: endl;
  14. //colPivHouseholderQr方法:fast
  15. std:: cout << "The least-squares solution is:\n"
  16. << A1.colPivHouseholderQr().solve(b1) << std:: endl;
  17. }
  •  

稀疏矩阵

稀疏矩阵的头文件包括:

#include


  
  
  1. typedef Eigen::Triplet< double> T;
  2. std:: vector<T> tripletList;
  3. triplets.reserve(estimation_of_entries); //estimation_of_entries是预估的条目
  4. for(...)
  5. {
  6. tripletList.push_back(T(i,j,v_ij)); //第 i,j个有值的位置的值
  7. }
  8. SparseMatrixType mat(rows,cols);
  9. mat.setFromTriplets(tripletList.begin(), tripletList.end());
  10. // mat is ready to go!
  •  

2.直接将已知的非0值插入


  
  
  1. SparseMatrix<double> mat(rows,cols);
  2. mat.reserve(VectorXi::Constant(cols, 6));
  3. for(...)
  4. {
  5. // i,j 个非零值 v_ij != 0
  6. mat.insert(i,j) = v_ij;
  7. }
  8. mat.makeCompressed(); // optional
  •  

稀疏矩阵支持大部分一元和二元运算:

sm1.real() sm1.imag() -sm1 0.5*sm1 
sm1+sm2 sm1-sm2 sm1.cwiseProduct(sm2) 
二元运算中,稀疏矩阵和普通矩阵可以混合使用

//dm表示普通矩阵 
dm2 = sm1 + dm1; 
也支持计算转置矩阵和伴随矩阵

参考以下链接

点击这里跳转查看更多

第三部分:

其他相关博客:

1、单独下载与安装:https://blog.csdn.net/augusdi/article/details/12907341

2、一篇较详细的教程:https://blog.csdn.net/wzaltzap/article/details/79501856

3、计算特征值特征向量:https://blog.csdn.net/wokaowokaowokao12345/article/details/47375427

            </div>

猜你喜欢

转载自blog.csdn.net/weixin_41735501/article/details/81544742
今日推荐