Matrix基本使用 Eigen概述 - Go吧LpengSu | Blog (yueyuebird-su.github.io)
Eigen 学习笔记(一)_逐梦者-CSDN博客_eigen
Eigen中Matrix 与Vector相似
1 2 3 4 5 6 7 Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options = 0 , int MaxRowsAtCompileTime = RowsAtCompileTime, int MaxColsAtCompileTime = ColsAtCompileTime>
基本运算 支持相同维数矩阵加减
支持乘除标量数
乘法(*)是矩阵乘法,不是对应元素相乘
基本方法 求转置、共轭矩阵、伴随矩阵 1 2 3 4 5 6 7 8 9 m.transpose (); m.conjugate (); m.adjoint (); 注意: 不能是 m=m.transpose (); 所以必须是: b=a.transpose ();
其他用法
1 2 3 4 5 6 7 8 9 10 Eigen::Matrix2d mat; mat << 1 , 2 , 3 , 4 ; cout << "Here is mat.sum(): " << mat.sum () << endl; cout << "Here is mat.prod(): " << mat.prod () << endl; cout << "Here is mat.mean(): " << mat.mean () << endl; cout << "Here is mat.minCoeff(): " << mat.minCoeff () << endl; cout << "Here is mat.maxCoeff(): " << mat.maxCoeff () << endl; cout << "Here is mat.trace(): " << mat.trace () << endl;
1 2 3 4 5 6 Here is mat.sum(): 10 Here is mat.prod(): 24 Here is mat.mean(): 2.5 Here is mat.minCoeff(): 1 Here is mat.maxCoeff(): 4 Here is mat.trace(): 5
Eigen: Eigen::MatrixBase< Derived > Class Template Reference
访问元素 1 2 3 4 5 6 7 8 MatrixXf m (2 , 2 ) ;m = MatrixXf::Random (2 , 2 ); cout << m (1 , 1 ) << endl; cout << m[0 ][0 ] << endl; VectorXd v (3 ) ;v = Vector3d::Random (3 ); cout << v[0 ]; cout << v (1 );
1 2 3 4 5 6 Matrix3f m = Matrix3f::Random (); std::ptrdiff_t i, j; float minOfM = m.minCoeff (&i,&j); cout << "Here is the matrix m:\n" << m << endl; cout << "Its minimum coefficient (" << minOfM << ") is at position (" << i << "," << j << ")\n\n" ;
另外,Eigen提供了MatrixXf::Index ,
1 MatrixXf::Index rownum,colnum;//可以存储行列号
Array(数组)使用
如果你需要做线性代数运算,如矩阵乘法,那么你应该使用矩阵;如果需要进行系数方面的操作,那么应该使用数组。
1 2 3 4 Array<float ,3 ,3 >a,b; ``` a*b;
1 2 3 //array与Matrix不能混用,需要转换类型 .array(); .matrix();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int main () { MatrixXf m (2 ,2 ) ; MatrixXf n (2 ,2 ) ; MatrixXf result (2 ,2 ) ; m << 1 ,2 , 3 ,4 ; n << 5 ,6 , 7 ,8 ; result = m * n; cout << "-- Matrix m*n: --" << endl << result << endl << endl; result = m.array () * n.array (); cout << "-- Array m*n: --" << endl << result << endl << endl; result = m.cwiseProduct (n); cout << "-- With cwiseProduct: --" << endl << result << endl << endl; result = m.array () + 4 ; cout << "-- Array m + 4: --" << endl << result << endl << endl; }
block分块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int main () { Eigen::MatrixXf m (4 ,4 ) ,a (2 ,2 ) ; m << 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ,10 ,11 ,12 , 13 ,14 ,15 ,16 ; cout << "Block in the middle" << endl; cout << m.block<2 ,2 >(1 ,1 ) << endl << endl; for (int i = 1 ; i <= 3 ; ++i) { cout << "Block of size " << i << "x" << i << endl; cout << m.block (0 ,0 ,i,i) << endl << endl; } m.block<2 ,2 >(1 ,1 )=a; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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
1 2 3 4 5 void testblock () { Matrix<float , 2 , 2 > m; m = Matrix<float , 2 , 2 >::Constant (12 ); cout << m << endl; }
1 2 m.col (2 ) += 3 * m.col (0 );
对于Vector 1 2 3 4 5 6 7 8 9 int main () { Eigen::ArrayXf v (6 ) ; v << 1 , 2 , 3 , 4 , 5 , 6 ; cout << "v.head(3) =" << endl << v.head (3 ) << endl << endl; cout << "v.tail<3>() = " << endl << v.tail<3 >() << endl << endl; v.segment (1 ,4 ) *= 2 ; cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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
赋值方法 1.“<<”+逗号赋值法 前提:==待赋值矩阵必须大小确定==
1 2 3 4 5 6 7 8 9 10 11 RowVectorXd vec1 (3 ) ;vec1 << 1 , 2 , 3 ; std::cout << "vec1 = " << vec1 << std::endl; RowVectorXd vec2 (4 ) ;vec2 << 1 , 4 , 9 , 16 ; std::cout << "vec2 = " << vec2 << std::endl; RowVectorXd joined (7 ) ;joined << vec1, vec2; std::cout << "joined = " << joined << std::endl;
2.特殊赋值
1 2 3 4 Array33f::Zero (); MatrixXf::Ones (3 ,2 ); MatrixXf::Constant (5 ,2 ,1.58 ); MatrixXf mat = MatrixXf::Random (2 , 3 );
1 2 3 4 5 6 7 ArrayXXf table (10 , 4 ) ;table.col (0 ) = ArrayXf::LinSpaced (10 , 0 , 90 ); table.col (1 ) = M_PI / 180 * table.col (0 ); table.col (2 ) = table.col (1 ).sin (); table.col (3 ) = table.col (1 ).cos (); std::cout << " Degrees Radians Sine Cosine\n" ; std::cout << table << std::endl;
Reductions, visitors and broadcasting 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int main () { VectorXf v (2 ) ; MatrixXf m (2 ,2 ) , n (2 ,2 ) ; v << -1 , 2 ; m << 1 ,-2 , -3 ,4 ; cout << "v.squaredNorm() = " << v.squaredNorm () << endl; cout << "v.norm() = " << v.norm () << endl; cout << "v.lpNorm<1>() = " << v.lpNorm<1 >() << endl; cout << "v.lpNorm<Infinity>() = " << v.lpNorm<Infinity>() << endl; cout << endl; cout << "m.squaredNorm() = " << m.squaredNorm () << endl; cout << "m.norm() = " << m.norm () << endl; cout << "m.lpNorm<1>() = " << m.lpNorm<1 >() << endl; cout << "m.lpNorm<Infinity>() = " << m.lpNorm<Infinity>() << endl; }
1 2 3 4 5 6 7 8 9 void test03 () { ArrayXXf a (2 , 2 ) ; a << 1 , 2 , 3 , 4 ; cout << "(a > 0).all() = " << (a > 0 ).all () << endl; cout << "(a > 0).any() = " << (a > 0 ).any () << endl; cout << "(a > 0).count() = " << (a > 0 ).count () << endl; cout << endl; }
colwise() and broadcasting 1 2 3 4 5 6 7 8 9 10 void test04 () { Eigen::MatrixXf mat (2 , 4 ) ; mat << 1 , 2 , 6 , 9 , 3 , 1 , 7 , 2 ; std::cout << "Column's maximum: " << std::endl << mat.colwise ().maxCoeff () << std::endl; }
colwise还可以实现如下功能
1 2 3 4 5 6 7 8 9 10 11 12 13 Eigen::MatrixXf mat (2 ,4 ) ;Eigen::VectorXf v (2 ) ; mat << 1 , 2 , 6 , 9 , 3 , 1 , 7 , 2 ; v << 0 , 1 ; mat.colwise () += v;
col-wise同理
需要注意的是:“+”后面的那个必须是Vector,否则程序报错
broadcasting与其他操作可以结合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int main () { Eigen::MatrixXf m (2 ,4 ) ; Eigen::VectorXf v (2 ) ; m << 1 , 23 , 6 , 9 , 3 , 11 , 7 , 2 ; v << 2 , 3 ; MatrixXf::Index index; (m.colwise () - v).colwise ().squaredNorm ().minCoeff (&index); cout << "Nearest neighbour is column " << index << ":" << endl; cout << m.col (index) << endl; }
Map Map中提供了Eigen与C++基本数组转换的方法,即通过指针与所占内存空间进行转换
1 2 3 4 5 6 7 void testMap02 () { int data[] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; Map<RowVectorXi> v (data, 4 ) ; cout << "The mapped vector v is: " << v << "\n" ; new (&v) Map<RowVectorXi>(data + 4 , 5 ); cout << "Now v is: " << v << "\n" ; }
目前还不知道如何将Map与std::vector直接转换
矩阵内部重叠问题 Eigen中用aliasing描述这一问题
1.在以下例子中重叠没有问题:
1 mat.bottomRightCorner (2 ,2 ) = mat.topLeftCorner (2 ,2 );
2.但是当a = a.transpose();
时就会因为重叠出现非编译错误
所以如何解决aliasing问题?
我们可以使用eval()函数:
1 a = a.transpose ().eval ();
当然对于转置,Eigen提供了:
其他常用方法的重叠解决方法
总结 1.alias对于标量计算、array和Matrrix加法是没有威胁的
2.当你使用矩阵乘法时,他默认会发生重叠。当你肯定重叠不会产生影响时,则可以使用noalias()
1 2 3 4 5 6 7 8 9 10 11 MatrixXf matA (2 ,2 ) , matB (2 ,2 ) ; matA << 2 , 0 , 0 , 2 ; matB = matA * matA; cout << matB << endl << endl; matB.noalias () = matA * matA; cout << matB;
3.其他情况下,Eigen都默认不会重叠,所以需要判断,视情况加.eval();
4.从版本3.3之后,对于矩阵乘法,如果矩阵shape改变并且乘积结果不是直接赋值给左边,则也默认不会重叠!!
1 2 3 4 5 6 7 MatrixXf A (2 ,2 ) , B (3 ,2 ) ;B << 2 , 0 , 0 , 3 , 1 , 1 ; A << 2 , 0 , 0 , -2 ; A = (B * A).cwiseAbs (); A = (B * A).eval ().cwiseAbs (); cout << A;
ColMajor&RowMajor 1 2 3 4 5 6 7 void ColRowMajor () { Matrix<int , 3 , 3 , ColMajor> m; m << 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ; for (int i = 0 ; i < 9 ; i++) { cout << *(m.data () + i) << endl; } }
如何选择:一般选择行存储,则按行遍历更快;Eigen默认是列,里面很多算法都是列优先,所以我们在选择时最好还是按照列优先
线性代数和分解
上表都是矩阵分解的方法,第一列是类名,第二列是类成员函数。这些类都有solve函数以及inverse函数
1 2 3 ColPivHouseholderQR<Matrix3f> dec (A) ;Vector3f x = dec.solve (b);
1 2 3 4 HouseholderQR<MatrixXf> qr (50 ,50 ) ;MatrixXf A = MatrixXf::Random (50 ,50 ); qr.compute (A); qr.inverse ();
//一般用以下方法求解
1 Matrix2f x = A.ldlt ().solve (b);
一般用以下方法求$A^{-1}$
1 A.colPivHouseholderQr().inverse();
检验显示:m.colPivHouseholderQr().inverse()
求解逆矩阵比m.inverse()
更准确
特征值 特征向量 1 2 3 4 5 6 7 8 9 10 11 void eigenvalues () { Matrix2f A; A << 1 , 2 , 2 , 3 ; cout << "Here is the matrix A:\n" << A << endl; SelfAdjointEigenSolver<Matrix2f> eigensolver (A) ; if (eigensolver.info () != Success) abort (); cout << "The eigenvalues of A are:\n" << eigensolver.eigenvalues () << endl; cout << "Here's a matrix whose columns are eigenvectors of A \n" << "corresponding to these eigenvalues:\n" << eigensolver.eigenvectors () << endl; }
注意:此时的特征值 特征向量不是从大到小排列
1 2 3 EigenSolver<MatrixXf> solver (covMat) ;featureValue = solver.pseudoEigenvalueMatrix ().diagonal (); featureVector = solver.pseudoEigenvectors ();
稀疏矩阵 稀疏矩阵(Sparse Martix)需要include以下头文件
几何模块 1 #include <Eigen/Geometry>
AlignedBox 这一模块用于包围盒操作
1 Eigen::AlignedBox< Scalar, AmbientDim >
简单实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void testAlignedBox () { AlignedBox2d myAlignedBox; Vector2d m; m << 1 , 0.5 ; myAlignedBox.extend (m); m << 2 , 2 ; myAlignedBox.extend (m); cout <<"max():" <<myAlignedBox.max () << endl; m << 3 , 4 ; cout << "exteriorDistance():" << myAlignedBox.exteriorDistance (m) << "squaredExteriorDistance():" << myAlignedBox.squaredExteriorDistance (m) << endl; AlignedBox2d myAlignedBox2,myalignedBox3; Vector2d b; b << 0.5 , 0.5 ; myAlignedBox2.extend (b); b << 1.5 , 1.5 ; myAlignedBox2.extend (b); myalignedBox3 = myAlignedBox2.intersection (myAlignedBox); cout << myalignedBox3.BottomLeft << endl; b << 1.25 , 1 ; cout <<"contains (0 or 1):" << myalignedBox3.contains (b) << endl; cout << "diagonal():" << myalignedBox3.diagonal () << endl; cout << "random sample:" << myAlignedBox.sample () << endl; cout << "sizes():" << myalignedBox3.sizes () << endl; }
cornerType:
transform和translate稍后再看
AngleAxis 注意:AngleAxis运用时:Axis的轴需要归一化
首先,Eigen在MatrixBase中定义了
UnitX(); UnitY(); UnitZ(); UnitW(); 作为默认的四个轴
例如:Vector3d::UnitX();
必须是固定大小的
附录 将特征值特征向量按特征值大小排列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 using eigMatrix = Eigen::Matrix<float , Eigen::Dynamic, Eigen::Dynamic>;using eigVector = Eigen::Matrix<float , Eigen::Dynamic, 1 >;using stdTupleEigen = std::tuple<float , eigMatrix>;using stdVectorTuple = std::vector<stdTupleEigen>;void sortEigenVectorByValues (eigVector& eigenValues, eigMatrix& eigenVectors) { stdVectorTuple eigenValueAndVector; int size = static_cast <int >(eigenValues.size ()); eigenValueAndVector.reserve (size); for (int i = 0 ; i < size; ++i) eigenValueAndVector.push_back (stdTupleEigen (eigenValues[i], eigenVectors.col (i))); std::sort (eigenValueAndVector.begin (), eigenValueAndVector.end (), [&](const stdTupleEigen& a, const stdTupleEigen& b) -> bool { return std::get<0 >(a) > std::get<0 >(b); }); for (int i = 0 ; i < size; ++i) { eigenValues[i] = std::get<0 >(eigenValueAndVector[i]); eigenVectors.col (i).swap (std::get<1 >(eigenValueAndVector[i])); } }