赞
踩
Eigen就是一个线性代数的C++库。它对矩阵(MatrixMatrix)和向量(VectorVector)等相关线性代数的运算操作进行了比较系统的实现。
1. 定义
矩阵模板函数共包含六个参数
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
举例:
- Eigen::Matrix<int, 3, 4> mat1; // 3x4 的 int 类型的矩阵 mat1
- Eigen::Matrix<double, 3, Dynamic> mat2; // 3x? 的 double 类型的矩阵 mat2
- Eigen::Matrix<float, Dynamic, 4> mat3; // ?x4 的 float 类型的矩阵 mat3
- Eigen::Matrix<long, Dynamic, Dynamic> mat4; // ?x? 的 long 类型的矩阵 mat4
动态矩阵:在 Eigen 中可以用 Dynamic 表示行或者列数未知,所以在定义一个矩阵时并不能确定矩阵的大小,只有在运行时才可以确定大小,然后进行动态分配。
静态矩阵:在定义时便明确给定了行数以及列数,在编译时就可以分配好内存。
2. 类型
在 EigenEigen 中 typedef 了很多矩阵的类型,通常命名为 Matrix前缀加一个长度为 1∼4 的字符串 S 的命名——MatrixS。
其中 S 可以用来判断该矩阵类型,数字 n 表示 n ∗ n,n 的范围是2∼4,字母 d、f、i、cd、f、i、c 表示 double、float、int、complexdouble、float、int、complex,另外 X 表示行或者列数未知的矩阵。
举例:
- typedef Matrix<std::complex<double>, 2, 2> Eigen::Matrix2cd; // 2x2 的 cd 类型的矩阵
- typedef Matrix<double, 2, 2> Eigen::Matrix2d; // 2x2 的 d 类型的矩阵
- typedef Matrix<std::complex<double>, 2, Dynamic> Eigen::Matrix2Xcd; // 2x? 的 cd 类型的矩阵
- typedef Matrix<std::complex<float>, Dynamic, 2> Eigen::MatrixX2cf; // ?x2 的 cf 类型的矩阵
- typedef Matrix<std::complex<double>, Dynamic, Dynamic> Eigen::MatrixXcd;// ?x? 的 cd 类型的矩阵
- typedef Matrix<int, Dynamic, Dynamic> Eigen::MatrixXi; // ?x? 的 i 类型的矩阵
3. 赋值与访问
(1)Eigen::Matrix 使用 ()访问赋值数据,矩阵之间通过 = 来进行赋值(拷贝)。
举例:
- x = mat(a, b); // 获取到矩阵 mat 的 a 行 b 列的元素并赋值给 x
- mat(b, a) = x; // 将 x 赋值给矩阵 mat 的 b 行 a 列
- mat1 = mat2; // 将矩阵 mat2 赋值(拷贝)给矩阵 mat1
注意:
通过 = 进行矩阵之间的拷贝时,如果左右两侧矩阵尺寸不一样并且左侧矩阵为动态矩阵,那么会将左侧矩阵的尺寸修改为与右侧一致。
(2)在 Eigen 中重载了 << 可以用来赋值矩阵,也可以用来 cout 输出矩阵。
- MatrixXf m(4, 4); // 定义一个 4x4 的 float 类型的动态矩阵
- m << 1, 2, 3, 4,
- 5, 6, 7, 8,
- 9, 10, 11, 12,
- 13, 14, 15, 16;// 赋值
- std::cout << m; // 输出 m
(3)Eigen 矩阵可以进行分块操作,通过成员函数 block() 获取某一部分矩阵。
- mat = mat1.block(i, j, p, q); // 从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵
- mat = mat1.block<p, q>(i, j); // 从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵(动态矩阵)
(4)Eigen 矩阵可以使用成员函数 row()、col() 来获取某一行或者某一列。
- mat = mat1.row(i); // 获取 mat1 的第 i 行
- mat = mat1.col(j); // 获取 mat1 的第 j 列
(5)Eigen 提供了从边角开始提取子矩阵的方法。
描述 | 动态矩阵 | 静态矩阵 |
左上角 pxq | mat.topLeftCorner(p,q) | mat.topLeftCorner<p,q>() |
左下角 pxq | mat.bottomLeftCorner(p,q) | mat.bottomLeftCorner<p,q>() |
右上角 pxq | mat.topRightCorner(p,q) | mat.topRightCorner<p,q>() |
右下角 pxq | mat.bottomRightCorner(p,q) | mat.bottomRightCorner<p,q>() |
前 p 行 | mat.topRows(p) | mat.topRows<p>() |
后 p 行 | mat.bottomRows(p) | mat.bottomRows<p>() |
前 q 列 | mat.leftCols(q) | mat.leftCols<q>() |
后 q 列 | mat.rightCols(q) | mat.rightCols<q>() |
(6)Eigen 矩阵还可以使用成员函数 fill() 进行统一赋值。
mat.fill(n); // 将 mat 的所有元素均赋值为 n
4. 运算
(1)Eigen 重载了 +、−(减)、∗、/、−(负)、+=、−=、∗=、/=+、−(减)、∗、/、−(负)、+=、−=、∗=、/=。
举例:
- mat = mat1 + mat2; // +
- mat = mat1 - mat2; // -(减)
- mat = mat1 * mat2; // *
- mat = mat1 * n; // *
- mat = mat1 / n; // /
- mat = -mat1; // -(负)
- mat += mat1; // +=
- mat -= mat1; // -=
- mat *= mat1; // *=
- mat *= n; // *=
- mat /= n; // /=
(2)对于 MatrixMatrix 的转置矩阵、共轭矩阵、伴随矩阵、对角矩阵可以通过成员函数 transpose()、conjugate()、adjoint()、diagonal()来获得。如果想要在原矩阵上进行转换,则需要通过成员函数 transposeInPlace()、conjugateInPlace()、adjointInPlace()。
举例:
- mat = mat1.transpose(); // 获取 mat1 的转置矩阵
- mat = mat1.conjugate(); // 获取 mat1 的共轭矩阵
- mat = mat1.adjoint(); // 获取 mat1 的伴随矩阵
- mat = mat1.diagonal(); // 获取 mat1 的对角矩阵
- mat1.transposeInPlace();// mat1 转换为对应的转置矩阵
- mat1.conjugateInPlace();// mat1 转换为对应的共轭矩阵
- mat1.adjointInPlace(); // mat1 转换为对应的伴随矩阵
- mat1.diagonalInPlace(); // mat1 转换为对应的对角矩阵
- mat1.transpose().colwise().reverse(); // mat1 Rot90
(3)特殊矩阵
- mat = MatrixXd::Identity(rows, cols); // 生成 rows x cols 的单位阵
- mat.setIdentity(rows, cols); // 将 mat 设置为 rows x cols 的单位阵
- mat = MatrixXd::Zero(rows, cols); // 生成 rows x cols 的零矩阵
- mat.setZero(rows, cols); // 将 mat 设置为 rows x cols 的零矩阵
- mat = MatrixXd::Ones(rows, cols); // 生成 rows x cols 的壹矩阵
- mat.setOnes(rows, cols); // 将 mat 设置为 rows x cols 的壹矩阵
- mat = MatrixXd::Random(rows, cols); // 生成 rows x cols 的随机矩阵
- mat.setRandom(rows, cols); // 将 mat 设置为 rows x cols 的随机矩阵
(4)其它
当前矩阵的行数、列数、大小可以通过成员函数 rows()、cols()、size()来获取。
- rows = mat.rows(); // 获取行数
- cols = mat.cols(); // 获取列数
- size = mat.size(); // 获取大小
动态矩阵可以通过成员函数 resize() 来进行修改大小,静态矩阵是不可以 resize() 的,并且动态矩阵 resize() 后元素不能保证不变。
mat.resize(rows, cols); // 将动态矩阵 mat 大小尺寸修改为 rows x cols
1. 类型与存储
类似于矩阵的类型,不过前缀从 Matrix 改成 Vector。
举例:
- typedef Matrix<std::complex<float>, 2, 1> Eigen::Vector2cf; // cf 类型的 2 向量
- typedef Matrix<int, 2, 1> Eigen::Vector2i; // i 类型的 2 向量
- typedef Matrix<double, 4, 1> Eigen::Vector4d; // d 类型的 4 向量
- typedef Matrix<float, Dynamic, 1> Eigen::VectorXf; // f 类型的 ? 向量
上述的 Vector 默认的都是列向量,如果是行向量,在命名上则需要加上 Row 前缀。
举例:
- typedef Matrix<float, 1, 2> Eigen::RowVector2f; // f 类型的 2 向量(行向量)
- typedef Matrix<std::complex<double>, 1, 4> Eigen::RowVector4cd; // cd 类型的 4 向量(行向量)
动态向量:不指定向量的尺寸,只有在运行时才会分配对应的内存;
静态向量:一开始就定义好了大小,在编译时分配好内存。
2. 访问与赋值
(1)类似于 Matrix 的操作,不过向量也可以使用 [],另外向量对前四个元素的访问与赋值还可以通过成员函数 x()、y()、z()、w()来操作。
举例:
- x = vec(n); // 获取向量 vec 的第 n 个元素并赋值给 x
- x = vec[n];
- x = vec.x(); // 获取向量 vec 的第一个元素并赋值给 x
- y = vec.y(); // 获取向量 vec 的第二个元素并赋值给 y
- z = vec.z(); // 获取向量 vec 的第三个元素并赋值给 z
- w = vec.w(); // 获取向量 vec 的第四个元素并赋值给 w
- vec(n) = x; // 将 x 赋值给 vec 的第 n 个元素
(2)Eigen 向量也提供了一些分块操作来获取子向量。
描述 | 静态向量 | 动态向量 |
前 n 个元素 | vec.head(n) | vec.head<n>() |
后 n 个元素 | vec.tail(n) | vec.tail<n>() |
从 i 开始取 n 个元素 | vec.segment(i,n) | vec.segment<n>(i) |
3. 运算
(1)Eigen 向量提供了 norm()、squareNorm()、dot()、cross()等成员函数。
举例:
- x.norm() // norm(x) Note that norm(R) doesn't work in Eigen.
- x.squaredNorm()
- x.dot(y) // dot(x, y)
- x.cross(y) // cross(x, y) Requires #include <Eigen/Geometry>
(2)获取尺寸
size = vec.size(); // 获取 vec 的尺寸
参考文章
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。