• Eigen教程(2)


    整理下Eigen库的教程,参考:http://eigen.tuxfamily.org/dox/index.html

    Matrix类

    在Eigen,所有的矩阵和向量都是Matrix模板类的对象,Vector只是一种特殊的矩阵(一行或者一列)。

    Matrix有6个模板参数,主要使用前三个参数,剩下的有默认值。

    Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
    

    Scalar是表示元素的类型,RowsAtCompileTime为矩阵的行,ColsAtCompileTime为矩阵的列。

    库中提供了一些类型便于使用,比如:

    typedef Matrix<float, 4, 4> Matrix4f;
    

    Vectors向量

    列向量

    typedef Matrix<float, 3, 1> Vector3f;
    

    行向量

    typedef Matrix<int, 1, 2> RowVector2i;
    

    Dynamic

    Eigen不只限于已知大小(编译阶段)的矩阵,有些矩阵的尺寸是运行时确定的,于是引入了一个特殊的标识符:Dynamic

    typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
    typedef Matrix<int, Dynamic, 1> VectorXi;
    Matrix<float, 3, Dynamic>
    

    构造函数

    默认的构造函数不执行任何空间分配,也不初始化矩阵的元素。

    Matrix3f a;
    MatrixXf b;
    

    这里,a是一个3*3的矩阵,分配了float[9]的空间,但未初始化内部元素;b是一个动态大小的矩阵,定义是未分配空间(0*0)。

    指定大小的矩阵,只是分配相应大小的空间,未初始化元素。

    MatrixXf a(10,15);
    VectorXf b(30);
    

    这里,a是一个10*15的动态大小的矩阵,分配了空间但未初始化元素;b是一个30大小的向量,同样分配空间未初始化元素。

    为了对固定大小和动态大小的矩阵提供统一的API,对指定大小的Matrix传递sizes也是合法的(传递也被忽略)。

    Matrix3f a(3,3);
    

    可以用构造函数提供4以内尺寸的vector的初始化。

    Vector2d a(5.0, 6.0);
    Vector3d b(5.0, 6.0, 7.0);
    Vector4d c(5.0, 6.0, 7.0, 8.0);
    

    获取元素

    通过中括号获取元素,对于矩阵是:(行,列);对于向量,只是传递它的索引,以0为起始。

    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    int main()
    {
      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:
    " << m << std::endl;
      VectorXd v(2);
      v(0) = 4;
      v(1) = v(0) - 1;
      std::cout << "Here is the vector v:
    " << v << std::endl;
    }
    

    输出

    Here is the matrix m:
      3  -1
    2.5 1.5
    Here is the vector v:
    4
    3
    

    m(index)也可以用于获取矩阵元素,但取决于matrix的存储顺序,默认是按列存储的,当然也可以改为按行。

    []操作符可以用于向量元素的获取,但是不能用于matrix,因为C++中[]不能传递超过一个参数。

    逗号初始化

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

    resizing

    matrix的大小可以通过rows()、cols()、size()获取,resize()可以重新调整动态matrix的大小。

    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    int main()
    {
      MatrixXd m(2,5);
      m.resize(4,3);
      std::cout << "The matrix m is of size "
                << m.rows() << "x" << m.cols() << std::endl;
      std::cout << "It has " << m.size() << " coefficients" << std::endl;
      VectorXd v(2);
      v.resize(5);
      std::cout << "The vector v is of size " << v.size() << std::endl;
      std::cout << "As a matrix, v is of size "
                << v.rows() << "x" << v.cols() << std::endl;
    }
    

    输出:

    The matrix m is of size 4x3
    It has 12 coefficients
    The vector v is of size 5
    As a matrix, v is of size 5x1
    

    如果matrix的实际大小不改变,resize函数不做任何操作。resize操作会执行析构函数:元素的值会被改变,如果不想改变执行 conservativeResize()。

    为了统一API,所有的操作可用于指定大小的matrix,当然,实际中它不会改变大小。尝试去改变一个固定大小的matrix到一个不同的值,会出发警告失败。只有如下是合法的。

    #include <iostream>
    #include <Eigen/Dense>
    using namespace Eigen;
    int main()
    {
      Matrix4d m;
      m.resize(4,4); // no operation
      std::cout << "The matrix m is of size "
                << m.rows() << "x" << m.cols() << std::endl;
    }
    

    assignment 和 resizing

    assignment(分配)是复制一个矩阵到另外一个,操作符=。Eigen会自动resize左变量大小等于右变量大小,比如:

    MatrixXf a(2,2);
    std::cout << "a is of size " << a.rows() << "x" << a.cols() << std::endl;
    MatrixXf b(3,3);
    a = b;
    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
    

    当然,如果左边量是固定大小的,上面的resizing是不允许的。

    固定尺寸 vs 动态尺寸

    实际中,应该使用固定尺寸还是动态尺寸,简单的答案是:小的尺寸用固定的,大的尺寸用动态的。使用固定尺寸可以避免动态内存的开辟,固定尺寸只是一个普通数组。

    Matrix4f mymatrix; 等价于 float mymatrix[16];

    MatrixXf mymatrix(rows,columns); 等价于 float *mymatrix = new float[rows*columns];

    使用固定尺寸(<=4*4)需要编译前知道矩阵大小,而且对于足够大的尺寸,如大于32,固定尺寸的收益可以忽略不计,而且可能导致栈崩溃。而且基于环境,Eigen会对动态尺寸做优化(类似于std::vector)

    其他模板参数

    上面只讨论了前三个参数,完整的模板参数如下:

    Matrix<typename Scalar,
           int RowsAtCompileTime,
           int ColsAtCompileTime,
           int Options = 0,
           int MaxRowsAtCompileTime = RowsAtCompileTime,
           int MaxColsAtCompileTime = ColsAtCompileTime>
    
    

    Options是一个比特标志位,这里,我们只介绍一种RowMajor,它表明matrix使用按行存储,默认是按列存储。Matrix<float, 3, 3, RowMajor>

    MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。主要是避免动态内存分配,使用数组。

    Matrix<float, Dynamic, Dynamic, 0, 3, 4> 等价于 float [12]

    一些方便的定义

    Eigen定义了一些类型

    • MatrixNt = Matrix<type, N, N> 特殊地有 MatrxXi = Matrix<int, Dynamic, Dynamic>
    • VectorNt = Matrix<type, N, 1> 比如 Vector2f = Matrix<float, 2, 1>
    • RowVectorNt = Matrix<type, 1, N> 比如 RowVector3d = Matrix<double, 1, 3>

    N可以是2,3,4或X(Dynamic)

    t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。

  • 相关阅读:
    Mybatis的XML中数字不为空的判断
    初步使用VUE
    Vue中实现菜单下拉、收起的动画效果
    Docker For Windows时间不对的问题
    freemarker使用自定义的模板加载器通过redis加载模板
    .net core 打印请求和响应的内容
    codedecision P1113 同颜色询问 题解 线段树动态开点
    洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
    洛谷P3150 pb的游戏(1)题解 博弈论入门
    codedecision P1112 区间连续段 题解 线段树
  • 原文地址:https://www.cnblogs.com/houkai/p/6347648.html
Copyright © 2020-2023  润新知