当前位置:   article > 正文

Eigen C++_eigen::matrixxf

eigen::matrixxf

Eigen

Matrix

Eigen 中所有的矩阵和向量都是 Matrix 类。Matrix 模板类需要指定三个量:Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>。其中,Scalar 是类型;RowsAtCompileTimeColsAtCompileTime 时所在的行数和列数。后三个参数是 <Options, MaxRowAtCompileTime, MaxColsAtCompileTime>Options 可以选为 RowMajor 变为行主格式。

当矩阵的行或者列为1时即是向量Eigen::Dynamic 是该维度为动态。构造 Matrix 时,可以指动态矩阵的大小。eg.

Eigen::MatrixXf a(10, 15); // 形状为 10, 15 的动态矩阵
  • 1

所有的矩阵都默认是列主存储格式。在 Eigen 的操作中,列主和行主矩阵可以混合运算,相互赋值,不受影响。但是 Eigen 默认支持列主矩阵,对列主阵的运算会更快,更安全。

矩阵初始化

  • 使用 C++11 方式初始化
// Initialize Vector
Matrix<int, 5, 1> b {1, 2, 3, 4, 5};   // A row-vector containing the elements {1, 2, 3, 4, 5}

// Initialize Matrix
Matrix<double, 2, 3> b {
      {2, 3, 4}, // First Row
      {5, 6, 7}, // Second Row
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 矩阵和向量都可以使用逗号初始化。左值可以是矩阵和矩阵块,右值可以是数字,向量,矩阵。
Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
  • 1
  • 2
  • 3
  • 4

Additional Notes

Vector 可以由 Eigen::all 初始化。即

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

Eigen::Vector3f vec3 = m(Eigen::all, 1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

矩阵索引

  • 括号() 索引。可以作为左值和右值。
// Simple Example
MatrixXd m(2,2);
m(0,0) = 3;

VectorXd v(2);
v(0) = 4;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

索引方式分为四种:

  1. 传入两个整数。
  2. 传入 Eigen:all 代表所有元素。(类似于 numpy 中的 :)。
// 第二列加到第一列上 -- 相当于 m[:, 0] += m[:, 1]
m(Eigen:all, 0) += m(Eigen:all, 1);
  • 1
  • 2
  1. Eigen vector/array, expressions, std::vector, std::array, 和最简单的 C arrays(即 int[N]).
  2. Eigen::seq, Eigen::seqN, or Eigen::lastN functions;见页面
  3. 使用 Map Slice,见 Map 章节。

矩阵操作

  • Resize
    使用 .resize(row, col) 变形矩阵。变形时,原矩阵对象会析构,矩阵内的值会改变。尤其是当前后大小不同时,变形后矩阵值会初始化为0。使用 conservativeResize() 保持矩阵内的值不变。
  • Copy & Assignment
    拷贝矩阵时,会自动将左值调整为右值的大小并赋值。

Array

Eigen 中的矩阵定义的运算法则为线性代数中的运算法则。如果需要做额外的运算,比如对应元素相乘,则需要用到 Array 类。 Array 类的初始化和 Matrix 类相同。

可以使用 .array().matrix() 在两者间转换。但是 Array 和 Matrix 不能相运算。

分块操作

从 (i, j) 开始,大小为 (p, q) 的块:动态 .block(i, j, p, q) ;静态 .block<p, q>(i, j)。Matrix 和 Array 都可以使用。分块对象可以作为左值和右值。

Eigen::MatrixXf m(4, 4);
Eigen::Matrix2f s;
s << 1, 1, 1, 1;
m.block(0, 0, 2, 2) = s; // 作为左值
  • 1
  • 2
  • 3
  • 4

.col(j).row(i) 将单独行、列作为块(与上相同)。对于向量,采用 .head(n) / .tail(n) / .segment(n) 分块。

特殊初始化

每个类下都有静态函数初始化。(类似于 np.zerosnp.ones

Eigen::MatrixXd m = Eigen::MatrixXd::Random(3, 3);
Eigen::MatrixXd m = Eigen::MatrixXd::Zeros(3, 3);
Eigen::MatrixXd m = Eigen::MatrixXd::Constant(3, 3, 1);
  • 1
  • 2
  • 3

矩阵或者矩阵块可以使用 setIdentity / setZero / setLinspaced 设置矩阵值。

Reducion & Partial Reduction

  • Reduction
名称作用
.sum()求和
.prod()累乘
.mean()求均值
.minCoeff()求最小值
.maxCoeff()求最大值
.trace()求迹
.norm()范数
.lpNorm<p>()p 范数
.count()所有非零值个数

.maxCoeff().minCoeff() 可以传入指针,得到最大值所在的位置。

Eigen::Matrix2d m;
m << 1, 2, 3, 4;
double min;
float x, y;
min = m.minCoeff(&x, &y);
  • 1
  • 2
  • 3
  • 4
  • 5
  • Partial Reduction
    采用 .colwise().rowwise() 对单独的行和列操作。这些可以和之前的 Reduction 操作结合。
Eigen::Matrix2d m;
m << 1, 2, 3, 4;
m.colwise().sum(); // 对列求和,类似于 np.sum(m, axis=0)
  • 1
  • 2
  • 3

Map

复用内存,避免重新分配内存。

Map 声明:Map<Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> > ,只需要传入一个 Matrix 即可。构造函数要传入指针和矩阵大小:Map<MatrixXf> mf(pf, 3, 3)。Map 和其他 Eigen 类型使用方法相同。

Slice using Map

介绍 Stride 类。

template<int _OuterStrideAtCompileTime, int _InnerStrideAtCompileTime>
class Eigen::Stride< _OuterStrideAtCompileTime, _InnerStrideAtCompileTime >
  • 1
  • 2

InnerStride 表示行主矩阵每行(或者列主矩阵每列)中两个相邻元素的距离。OuterStride 表示行主矩阵中相邻两行间相隔元素数

在 (4, 4) 连续矩阵中,Innerstride 是 1,outerstride 是 4。

在声明 Map 时可以传入 Stride 切片。

Eigen::MatrixXf m(8, 8);
m = Eigen::MatrixXf::Random(8, 8);
// m[::2, ::2] 间隔一行一列索引
Eigen::Map<Eigen::MatrixXf, 0, Eigen::Stride<Eigen::Dynamic, 2>> map(m.data(), (m.rows() + 1) / 2, (m.cols() + 1) / 2, Eigen::Stride<Eigen::Dynamic, 2>(m.outerstride() * 2, 2));
  • 1
  • 2
  • 3
  • 4

Alias

Alias 指表达式中的元素同时出现在赋值符号的左右两侧,而且赋值顺序会影响最后的结果。Eigen 采用 Lazy Evaluation,并不会构造临时对象全部完成右值所有计算后再赋给左值。解决方法是使用 .eval() 完成右侧运算后再赋给左值。

// alias issue
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2);

// use .eval() to resolve
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2).eval();
  • 1
  • 2
  • 3
  • 4
  • 5

或者采用 Inplace 操作

mat.transposeInplace();
  • 1

所有的矩阵乘法都不受 Alias 影响。如果运算中并没有重叠的元素,也不会有 Alias 运算。

Geometry

Eigen 中的几何变换模块,需要添加头文件 #include <Eigen/Geometry>

几何模块中基类 Eigen::Transform, 可以由此构建任何变换矩阵:

// -- Recommand
Transform t(AngleAxis(angle, axis));

Transform t;
t = AngleAxis(angle, axis);

// -- DO NOT DO THIS
Transform t = AngleAxis(angle,axis);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/79259
推荐阅读
相关标签
  

闽ICP备14008679号