zoukankan      html  css  js  c++  java
  • Eigen介绍 C++矩阵运算库

    Eigen常规矩阵定义

    1.使用

    Eigen的使用在官网上有详细的介绍,这里对我学习过程中用到的基本操作进行介绍。首先是矩阵的定义。
    在矩阵类的模板参数共有6个。一般情况下我们只需要关注前三个参数即可。前三个模板参数如下所示:

    Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>
    1. Scalar参数为矩阵元素的类型,该参数可以是int,float,double等。
    2. RowsAtCompileTime和ColsAtCompileTime是矩阵的行数和列数。

    Matrix<float,4,4> M44是定义一个4×4的矩阵,矩阵元素以float类型存储。直接使用矩阵模板定义一个矩阵往往会觉得麻烦,Eigen提供了一些基本矩阵的别名定义,如typedef Matrix<float,4,4> Matrix4f.下面是一些内置的别名定义.来源于官方手册:

     1 typedef Matrix< std::complex<double> , 2 , 2 > Matrix2cd
     2 typedef Matrix< std::complex<float> , 2 , 2 > Matrix2cf
     3 typedef Matrix< double , 2 , 2 > Matrix2d
     4 typedef Matrix< float , 2 , 2 > Matrix2f
     5 typedef Matrix< int , 2 , 2 > Matrix2i
     6 typedef Matrix< std::complex<double> , 3 , 3 > Matrix3cd
     7 typedef Matrix< std::complex<float> , 3 , 3 > Matrix3cf
     8 typedef Matrix< double , 3 , 3 > Matrix3d
     9 typedef Matrix< float , 3 , 3 > Matrix3f
    10 typedef Matrix< int , 3 , 3 > Matrix3i
    11 typedef Matrix< std::complex<double> , 4 , 4 > Matrix4cd
    12 typedef Matrix< std::complex<float> , 4 , 4 > Matrix4cf
    13 typedef Matrix< double , 4 , 4 > Matrix4d
    14 typedef Matrix< float , 4 , 4 > Matrix4f
    15 typedef Matrix< int , 4 , 4 > Matrix4i
    16 typedef Matrix< std::complex<double> , Dynamic , Dynamic > MatrixXcd
    17 typedef Matrix< std::complex<float> , Dynamic , Dynamic > MatrixXcf
    18 typedef Matrix< double , Dynamic , Dynamic > MatrixXd
    19 typedef Matrix< float , Dynamic , Dynamic > MatrixXf
    20 typedef Matrix< int , Dynamic , Dynamic > MatrixXi
    21 typedef Matrix< std::complex<double> , 1, 2 > RowVector2cd
    22 typedef Matrix< std::complex<float> , 1, 2 > RowVector2cf
    23 typedef Matrix< double , 1, 2 > RowVector2d
    24 typedef Matrix< float , 1, 2 > RowVector2f
    25 typedef Matrix< int , 1, 2 > RowVector2i
    26 typedef Matrix< std::complex<double> , 1, 3 > RowVector3cd
    27 typedef Matrix< std::complex<float> , 1, 3 > RowVector3cf
    28 typedef Matrix< double , 1, 3 > RowVector3d
    29 typedef Matrix< float , 1, 3 > RowVector3f
    30 typedef Matrix< int , 1, 3 > RowVector3i
    31 typedef Matrix< std::complex<double> , 1, 4 > RowVector4cd
    32 typedef Matrix< std::complex<float> , 1, 4 > RowVector4cf
    33 typedef Matrix< double , 1, 4 > RowVector4d
    34 typedef Matrix< float , 1, 4 > RowVector4f
    35 typedef Matrix< int , 1, 4 > RowVector4i
    36 typedef Matrix< std::complex<double> , 1, Dynamic > RowVectorXcd
    37 typedef Matrix< std::complex<float> , 1, Dynamic > RowVectorXcf
    38 typedef Matrix< double , 1, Dynamic > RowVectorXd
    39 typedef Matrix< float , 1, Dynamic > RowVectorXf
    40 typedef Matrix< int , 1, Dynamic > RowVectorXi
    41 typedef Matrix< std::complex<double> , 2 , 1> Vector2cd
    42 typedef Matrix< std::complex<float> , 2 , 1> Vector2cf
    43 typedef Matrix< double , 2 , 1> Vector2d
    44 typedef Matrix< float , 2 , 1> Vector2f
    45 typedef Matrix< int , 2 , 1> Vector2i
    46 typedef Matrix< std::complex<double> , 3 , 1> Vector3cd
    47 typedef Matrix< std::complex<float> , 3 , 1> Vector3cf
    48 typedef Matrix< double , 3 , 1> Vector3d
    49 typedef Matrix< float , 3 , 1> Vector3f
    50 typedef Matrix< int , 3 , 1> Vector3i
    51 typedef Matrix< std::complex<double> , 4 , 1> Vector4cd
    52 typedef Matrix< std::complex<float> , 4 , 1> Vector4cf
    53 typedef Matrix< double , 4 , 1> Vector4d
    54 typedef Matrix< float , 4 , 1> Vector4f
    55 typedef Matrix< int , 4 , 1> Vector4i
    56 typedef Matrix< std::complex<double> , Dynamic , 1> VectorXcd
    57 typedef Matrix< std::complex<float> , Dynamic , 1> VectorXcf
    58 typedef Matrix< double , Dynamic , 1> VectorXd
    59 typedef Matrix< float , Dynamic , 1> VectorXf
    60 typedef Matrix< int , Dynamic , 1> VectorXi

    2 向量

    向量被作为一种特殊的矩阵进行处理,即要么行为一要么列为一。除非显式的说明为行向量,否则这里将向量默认为列向量。请看下面两个别名定义:

    1 typedef Matrix<float,3,1> Vector3f;
    2 typedef Matrix<int,1,2> RowVector2i;

    3 矩阵的动态空间分配

    很多时候在程序的编译阶段也许我们并不知道矩阵具体的行列数,这时候使用动态控件分配就显得很必要了。当我们给矩阵模板中参数RowsAtCompileTime或者ColsAtCompileTime参数指定为Dynamic时,表示该矩阵对应行或列为一个动态分配的值。下面是两个动态矩阵的别名定义:

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

    4 矩阵的构建

    经过上面的介绍以后,我们应该能定义一些基本的矩阵了。如:

    1 Matrix3f a;   //定义一个float类型3×3固定矩阵a
    2 MatrixXf b;   //定义一个float类型动态矩阵b(0×0)
    3 Matrix<int,Dynamic,3> b;  //定义一个int类型动态矩阵(0×3)

    对应动态矩阵,我们也可以在构造的时候给出矩阵所占用的空间,比如:

    1 MatrixXf a(10,15);  //定义float类型10×15动态矩阵
    2 VectorXf b(30); //定义float类型30×1动态矩阵(列向量)

    为了保持一致性,我们也可以使用上面构造函数的形式定义一个固定的矩阵,即Matrix3f a(3,3)也是允许的。

    上面矩阵在构造的过程中并没有初始化,Eigen还为一些小的(列)向量提供了可以初始化的构造函数。如:

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

    5 矩阵元素的访问

    Eigen提供了矩阵元素的访问形式和matlab中矩阵的访问形式非常相似,最大的不同是matlab中元素从1开始,而Eigen的矩阵中元素是从0开始访问。对于矩阵,第一个参数为行索引,第二个参数为列索引。而对于向量只需要给出一个索引即可。

     1 #include <iostream>
     2 #include "EigenCore"
     3 
     4 //import most common Eigen types
     5 using namespace Eigen;
     6 
     7 int main()
     8 {
     9     MatrixXd m(2,2);
    10     m(0,0) = 3;
    11     m(1,0) = 2.5;
    12     m(0,1) = -1;
    13     m(1,1) = m(1,0) + m(0,1);
    14     
    15     std::cout<<"Hear is the matrix m:
    "<<m<<std::endl;
    16     VectorXd v(2);
    17     v(0) = 4;
    18     v(1) = v(0) - 1;
    19     std::cout<<"Here is the vector v:
    "<<v<<std::endl;
    20 }

    输出结果如下:

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

    m(index)这种访问形式并不仅限于向量之中,对于矩阵也可以这样访问。这一点和matlab相同,我们知道在matlab中定义一个矩阵a(3,4),如果我访问a(5)相当于访问a(2,2),这是因为在matlab中矩阵是按列存储的。这里比较灵活,默认矩阵元素也是按列存储的,但是我们也可以通过矩阵模板构造参数Options=RowMajor改变存储方式(这个参数是我们还没有提到的矩阵构造参数的第4个参数)。

    6 一般初始化方法

    对于矩阵的初始化,我们可以采用下面的方法方便且直观的进行:

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

    7 矩阵的大小

    Eigen提供了rows(),cols(),size()方法来获取矩阵的大小,同时也同了resize()方法从新改变动态数组的大小。

     1 #include <iostream>
     2 #include "EigenCore"
     3 
     4 using namespace Eigen;
     5 
     6 int main()
     7 {
     8     MatrixXd m(2,5);
     9     m<<1,2,3,4,5,
    10        6,7,8,9,10;
    11     m.resize(4,3);
    12     std::cout<<"The matrix m is:
    "<<m<<std::endl;
    13     std::cout<<"The matrix m is of size "
    14              <<m.rows()<<"x"<<m.cols()<<std::endl;
    15     std::cout<<"It has "<<m.size()<<" coefficients"<<std::endl;
    16     VectorXd v(2);
    17     v<<1,2;
    18     v.resize(5);
    19     std::cout<<"The vector v is:
    "<<v<<std::endl;
    20     std::cout<<"The vector v is of size "<<v.size()<<std::endl;
    21     std::cout<<"As a matrix,v is of size "<<v.rows()
    22              <<"x"<<v.cols()<<std::endl;
    23 }

    输出结果如下:

    The matrix m is:
               1            3            5
               6            8           10
               2            4            9.58787e-315
               7            9            1.17493e-309
    The matrix m is of size 4x3
    It has 12 coefficients
    The vector v is:
               1
               2
    1.17477e-309
     7.0868e-304
               0
    The vector v is of size 5
    As a matrix,v is of size 5x1

    可以看到我们可以把矩阵任意的resize,但是resize后矩阵的元素会改变,如果resize后的矩阵比之前的大会出现一些未初始化的元素。如果被resize的矩阵按列存储(默认),那么resize命令和matlab中的reshape执行结果相同,只是matlab要求reshape的矩阵前后元素必须相同,也就是不允许resize后不能出现未初始化的元素。
    对于固定大小的矩阵虽然也支持resize命令,但是resize后的大小只能是它本身的大小,否则就会报错。因为resize前后如果矩阵大小一样,就不会执行resize。如果我们不想在resize后改变矩阵的对应元素,那么可以使用conservativeResize()方法。对应上面程序中的m矩阵我们调用m.conservativeResize(4,3)后得到结果如下。其中因为行数增加了,增加的行会以未初始化的形式出现。

    The matrix m is:
               1            2            3
               6            7            8
    9.58787e-315   2.122e-314 1.52909e+249
               0            0 2.47039e+249

    http://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html

    8 赋值和大小变换

    在Eigen中使用=可以直接将一个矩阵复制给另外一个矩阵,如果被复制的和赋值矩阵大小不一致,会自动对被复制矩阵执行resize函数。当然如果被复制的矩阵为固定矩阵当然就不会执行resize函数。当然也可以通过一些设置取消这个自动resize的过程。

     1 using namespace Eigen;
     2 
     3 int main()
     4 {
     5     MatrixXf a(2,2);
     6     MatrixXf b(3,3);
     7     b<<1,2,3,
     8        4,5,6,
     9        7,8,9;
    10     a = b;
    11     std::cout<<a<<std::endl;
    12 }

    输出结果:

    1 2 3
    4 5 6
    7 8 9

    9 固定矩阵和动态矩阵

    什么时候使用固定矩阵什么时候使用动态矩阵呢?简单的说:当矩阵尺寸比较小时使用固定矩阵(一般小于16),当矩阵尺寸较大时使用动态矩阵(一般大于32)。使用固定矩阵有更好的表现,它可以避免重复的动态内存分配,固定矩阵实际上是一个array。即Matrix4f mymatrix;事实上是float mymatrix[16];。所以这个是真的不花费任何运行时间。相反动态矩阵的建立需要在
    heap中分配空间。即MatrixXf mymatrix(rows,colums);实际上是float *mymatrix = new float[rows*colums];.此外动态矩阵还要保存行和列的值。
    当然固定矩阵也存在着显而易见的弊端。当数组的大小过大时,固定数组的速度优势就不那么明显了,相反过大的固定数组有可能造成stack的溢出。这时候动态矩阵的灵活性就显得十分重要了。

    10 其他模板参数

    最开始我们已经提到了建立一个矩阵一共有6个模板参数,其中有3个我们还没有提到(其实第三个参数已经提到过了)。

    1 Matrix<typename Scalar,
    2              int RowsAtCompileTime,
    3              int ColsAtCompileTime,
    4              int Options=0,
    5              int MaxRowsAtCompileTime = RowsAtCompileTime,
    6              int MaxColsAtCompileTime = ColsAtCompileTime>
    1. Options:这个参数决定了矩阵在存储过程中实际是按行还是按列存储。这个存储方式在前面我们提到的矩阵变换时必须要注意。默认是按列存储,我们可以显示的使用Options=RowMajor让矩阵实际按行存储。如Matrix<float,2,3,RowMajor> a;.
    2. MaxRowsAtCompileTime和MaxColsAtCompileTime:这两个值是设定动态矩阵在分配空间时最大的行数和列数。如Matrix<float,Dynamic,Dynamic,0,3,4>;.

    11 常规的矩阵typedef

    我们前面给出了一些常用的矩阵typedef.其实可以总结如下:

    1. MatrixNt对应的是Matrix
    2. VectorNt对应的是Matrix
    3. RowVectorNt对应的是Matrix

    其中:

    1. N可以是2,3,4或者X(表示Dynamic).
    2. t可以是i(int),f(float),d(double),cf(complex
  • 相关阅读:
    jq focus 在火狐(Firefox)下无效
    将自己的项目上传到github保管
    $(window).height(),在火狐下面获取的高度并不是可视区域的高度
    [转载]跨域iframe高度自适应
    用css改变默认的checkbox样式
    js,jq新增元素 ,on绑定事件无效
    xshell配色Solarized Dark
    记一次给公司服务器装第二块硬盘的经历
    【shell编程基础3】shell编程的组合应用之二:管道及其命令
    【shell编程基础2】shell组合应用之一:重定向和逻辑
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14239542.html
Copyright © 2011-2022 走看看