Eigen库完全教程——从入门到入魂

Eigen库完全教程——从入门到入魂1 eigen 库介绍 eigen 库是 C 中的线性代数库 实现了线性代数以及矩阵分析中所有计算方法 既然已经要学 eigen 库了 想必 线性代数的基本知识肯定是有的 如果你是做三维重建的 那么这个库必学 另外 eigen 库内部实现的操作基本都是高度优化的

大家好,我是讯享网,很高兴认识大家。

1.eigen库介绍

eigen库是C++中的线性代数库,实现了线性代数以及矩阵分析中所有计算方法。既然已经要学eigen库了,想必,线性代数的基本知识肯定是有的。如果你是做三维重建的,那么这个库必学。
另外,eigen库内部实现的操作基本都是高度优化的,计算顺序可能并不像我们平时计算那样从左到右,一般情况下,我们是不需要去管这个的。
eigen官方库使用官方教程链接: link

2.matrix对象创建

只有一个模板类Matrix,其他的所有数据类型3阶矩阵、2维向量等等都是由这个类模板定义的。如typedef Matrix<int,2,1> Vector2i;typedef Matrix<float,3,3> Matrix3f;

 //固定大小的矩阵 Eigen::Matrix<int, 2, 2> mat1; Eigen::Matrix2i mat2; cout << "mat1:"<<endl<<mat1 << endl; cout << "mat2:" << endl<<mat2 << endl; //mat不支持构造时初始化,vec是可以构造时初始化 mat2 << 1, 2, 3, 4; cout << "输入值后,mat2:" << endl << mat2 << endl; Eigen::Vector2f vec2f(99.9, 88.8); cout << "输入值后,vec2f:" << endl << vec2f << endl; //如果支持C++11特性,则mat和vec都可以用列表初始化 Eigen::MatrixXi dymat{ 
   { 
   1, 2, 3}, { 
    4,5,6 }}; cout << "dymat:" << endl << dymat << endl; 

讯享网

运行结果:
在这里插入图片描述
讯享网

矩阵元素的访问

讯享网#include <iostream> #include <Eigen/Dense> int main() { 
    Eigen::MatrixXd m(2,2); m(0,0) = 3; m(1,0) = 2.5; m(0,1) = -1; m(1,1) = m(1,0) + m(0,1); std::cout << "Here is the matrix m:\n" << m << std::endl; Eigen::VectorXd v(2); v(0) = 4; v(1) = v(0) - 1; std::cout << "Here is the vector v:\n" << v << std::endl; } 

动态矩阵–即矩阵维度是不确定的

用Eigen::MatrixXi来定义(其实是Eigen::Matrix<int,dynamic,dynamic>)。动态矩阵时可以改变大小的resize函数。

 //如果支持C++11特性,则mat和vec都可以用列表初始化 Eigen::MatrixXi dymat{ 
   { 
   1, 2, 3}, { 
    4,5,6 }}; cout << "dymat:" << endl << dymat << endl; cout << "行数:"<<dymat.rows() << endl; dymat.resize(3, 2); cout << "dymat:" << endl << dymat << endl; cout << "行数:" << dymat.rows() << endl; 

注意:Eigen中矩阵的元素存储默认是列主序,即dymat在内存中是 1,4,2,5,3,6
在这里插入图片描述

3.矩阵四则运算

eigen库通过运算符重载来实现类似于普通常数的四则运算,当然也有一些函数方法。注意: Eigen库不支持数据类型的自动提升,所以执行四则运算的矩阵必须是相同数据类型,可以使用cast()成员函数进行数据类型强转。

加减

讯享网 Eigen::Matrix2d a; a << 1, 2, 3, 4; Eigen::MatrixXd b(2, 2); b << 2, 3, 1, 4; std::cout << "a + b =\n" << a + b << std::endl; std::cout << "a - b =\n" << a - b << std::endl; std::cout << "Doing a += b;" << std::endl; a += b; std::cout << "Now a =\n" << a << std::endl; Eigen::Vector3d v(1, 2, 3); Eigen::Vector3d w(1, 0, 0); std::cout << "-v + w - v =\n" << -v + w - v << std::endl; 

在这里插入图片描述

标量乘除

 Eigen::Matrix2d a{ 
   { 
   1, 2}, { 
    3, 4 }}; cout << a << endl; cout << "" << endl; auto a1 = a * 2; auto a2 = a / 2; cout << a1 << endl; cout << "" << endl; cout << a2 << endl; 

在这里插入图片描述

矩阵乘除

讯享网 Eigen::Matrix2d a{ 
   { 
   1, 2}, { 
    3, 4 }}; Eigen::Matrix2d b = a.transpose(); cout << "a:" << endl << a << endl; cout << "b:" << endl << b << endl; cout << "a*b:" << endl << a * b << endl; Eigen::Vector2d c(1, 1); cout << "a * b * c" << endl << a * b * c << endl; 

在这里插入图片描述

内积和外积–dot、cross

 Eigen::Vector3d a(1, 1,1); Eigen::Vector3d b(3, 4,5); cout << "内积:" << a.dot(b) << endl; cout << "内积另一种计算:" << a.transpose()*b << endl; cout << "叉乘:" <<endl<< a.cross(b) << endl; 

在这里插入图片描述

4. Array类实现逐元素的操作。类似于numpy中的广播机制。

只要记住是逐元素操作就行,其它的所有操作都跟Matrix差不多。

讯享网 Eigen::Array<int, 2, 3> a{ 
   { 
   -1, -2, -1}, { 
    6,6,6 }}; Eigen::Array<int, 2, 3> b{ 
   { 
   2, 2, 2}, { 
    2,3,2 }}; cout << "a:" << endl << a << endl; cout << "b:" << endl << b << endl; cout << "a+1:" << endl << a + 1 << endl; cout << "a+b:" << endl << a + b << endl; cout << "a*b:" << endl << a * b << endl; cout << "a的绝对值:" << a.abs() << endl; cout << "b的平方根:" << b.sqrt() << endl; cout << "返回a和b中对应元素位置最大的元素组成的array:" << endl << a.max(b) << endl; 

在这里插入图片描述

5.矩阵块操作–block、()重载

 Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //block方法返回值做右值 auto t = m.block<2, 2>(1, 1); cout << t << endl; //左值 m.block(1, 1, 2, 2) = Eigen::Array22f::Constant(0.5); cout << "m:\n" << m << endl; 

在这里插入图片描述
注意: 块操作结果是可以作为左值的,即block函数返回的是引用。
取块的其他操作:

讯享网 Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //block方法返回值做右值 auto t = m.block<2, 2>(1, 1); cout << t << endl; //左值 m.block(1, 1, 2, 2) = Eigen::Array22f::Constant(0.5); cout << "m:\n" << m << endl << endl; //取第2行 cout << "第2行:" << m.row(1) << endl; //左上角2*3,并+1 m.topLeftCorner(2, 3) = m.topLeftCorner(2, 3).array() + 1; cout << endl << "左上角+1后:\n" << m << endl; 

在这里插入图片描述

6.切片-seq,seqN,lastN,all,其它数组

切片和块操作差不多,都支持左值和右值计算。不同的是,切片更灵活,切片得到的矩阵布局跟切片时输入的行列顺序一样。

 Eigen::MatrixXf m(4, 4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16; //matrix的切片 //用seq()生成数组 cout << m(Eigen::seq(1, 2),Eigen::seq(0,1) ) << endl; cout << "" << endl; //用seqN()生成间隔数组 cout << m(Eigen::seqN(0, 2, 2), Eigen::last) << endl; cout << "" << endl; //用一般的可遍历容器生成数组 int col[2] = { 
    0,1 }; cout << m(vector<int>{ 
   1, 2, 3}, col) << endl; cout << "" << endl; //用lastN生成后面的数组 cout << m(Eigen::lastN(2), Eigen::all) << endl; cout << "" << endl; 

在这里插入图片描述

讯享网 cout <<"m:\n"<< m << endl; cout << "" << endl; //逆序切片 cout << m(Eigen::seq(Eigen::last, 1, -1), vector<int>{ 
   1, 2}) << endl; //任意行列切片 cout << "" << endl; Eigen::Array3i ainx{ 
   1, 3, 2}; cout << m(vector<int>{ 
   2, 1, 2}, ainx) << endl; 

在这里插入图片描述

7.初始化的其它方法–用matrix初始化

 //用matrix来初始化,实现堆叠 MatrixXi mat1(2, 2); mat1 << 1, 2, 3, 4; MatrixXi mat2(2, 3); mat2 << 1, 1, 1, 2, 2, 2; cout << "mat1:\n" << mat1 << endl; cout << "mat2:\n" << mat2 << endl; MatrixXi mat3(2, 5); mat3 << mat1, mat2; cout << "mat3:\n" << mat3 << endl; MatrixXi mat4(5, 5); mat4.row(0) << mat3.row(1); mat4.row(1).head(4) << 4, 4, 4, 4; mat4.row(1).tail(1) << 100; mat4.block(2, 0, 3, 5) << mat3, mat3.row(0); cout << "mat4:\n" << mat4 << endl; 

在这里插入图片描述

8.常见的一些基本矩阵幅值

零矩阵、单位阵、常矩阵、随机矩阵

讯享网 //零矩阵 MatrixXi mat1 = MatrixXi::Zero(2, 3); cout << "mat1:\n" << mat1 << endl; Matrix3i mat2 = Matrix3i::Zero(); cout << "mat2:\n" << mat2 << endl; //常数矩阵 MatrixXf mat3 = MatrixXf::Constant(2, 3, 6.6); cout << "mat3:\n" << mat3 << endl; //随机矩阵 RowVectorXf vec1 = RowVector3f::Random();//-1~1随机浮点数 cout << "vec1:\n" << vec1 << endl; //单位阵 MatrixXi mat4 = Matrix3i::Identity(); cout << "mat4:\n" << mat4 << endl; 

在这里插入图片描述
分块的常见矩阵赋值or原地赋值操作

 const int size = 6; MatrixXd mat1(size, size); mat1.topLeftCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2); mat1.topRightCorner(size / 2, size / 2) = MatrixXd::Identity(size / 2, size / 2); mat1.bottomLeftCorner(size / 2, size / 2) = MatrixXd::Identity(size / 2, size / 2); mat1.bottomRightCorner(size / 2, size / 2) = MatrixXd::Zero(size / 2, size / 2); std::cout << mat1 << std::endl << std::endl; MatrixXd mat2(size, size); mat2.topLeftCorner(size / 2, size / 2).setZero(); mat2.topRightCorner(size / 2, size / 2).setIdentity(); mat2.bottomLeftCorner(size / 2, size / 2).setIdentity(); mat2.bottomRightCorner(size / 2, size / 2).setZero(); std::cout << mat2 << std::endl << std::endl; MatrixXd mat3(size, size); mat3 << MatrixXd::Zero(size / 2, size / 2), MatrixXd::Identity(size / 2, size / 2), MatrixXd::Identity(size / 2, size / 2), MatrixXd::Zero(size / 2, size / 2); std::cout << mat3 << std::endl; 

在这里插入图片描述

小讯
上一篇 2025-03-04 14:32
下一篇 2025-03-06 18:55

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/41834.html