Eigen高阶操作总结 — 子矩阵、块操作

鉴于中文资料中Eigen资料鱼目混珠,纷乱庞杂。现参考Eigen官网,整理常用Eigen矩阵操作。
基于版本:/usr/include/eigen3/Eigen/src/Core/util/Macros.h显示的3.2.92
Eigen有2中矩阵结构:Dense和Sparse。Dense矩阵存储读写为正常处理,Sparse由于其特殊的存储格式和操作,处理不一样。以下介绍Dense矩阵的块操作处理。

1. 矩阵块操作

1.1 定义

Eigen中的矩阵块操作使用 .block() 指令,有2中版本:

意义 动态size (dynamic-size) 固定size (fixed-size block)
(i,j) 开始,大小为 (p,q) 矩阵块 matrix.block(i,j,p,q); matrix.block<p,q>(i,j);

适用于固定尺寸、动态尺寸、array取值,其中固定尺寸读取稍快些。

1.2 栗子

Eg1:

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  cout << "Block in the middle" << endl;
  cout << m.block<2,2>(1,1) << endl << endl;
  for (int i = 1; i <= 3; ++i)
  {
    cout << "Block of size " << i << "x" << i << endl;
    cout << m.block(0,0,i,i) << endl << endl;
  }
}

Output:

Block in the middle
 6  7
10 11

Block of size 1x1
1

Block of size 2x2
1 2
5 6

Block of size 3x3
 1  2  3
 5  6  7
 9 10 11

Eg2: block赋值

#include <Eigen/Dense>
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
  Array22f m;
  m << 1,2,
       3,4;
  Array44f a = Array44f::Constant(0.6);
  cout << "Here is the array a:" << endl << a << endl << endl;
  a.block<2,2>(1,1) = m;
  cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl;
  a.block(0,0,2,3) = a.block(2,1,2,3);
  cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:" << endl << a << endl << endl;
}

Output:

Here is the array a:
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6

Here is now a with m copied into its central 2x2 block:
0.6 0.6 0.6 0.6
0.6   1   2 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6

Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:
  3   4 0.6 0.6
0.6 0.6 0.6 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6

2. 矩阵行列操作

2.1 定义

按行、列读取变化,使用指令 .col() and .row()

2.2 栗子

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::MatrixXf m(3,3);
  m << 1,2,3,
       4,5,6,
       7,8,9;
  cout << "Here is the matrix m:" << endl << m << endl;
  cout << "2nd Row: " << m.row(1) << endl;
  m.col(2) += 3 * m.col(0);
  cout << "After adding 3 times the first column into the third column, the matrix m is:\n";
  cout << m << endl;
}

OutPut:

Here is the matrix m:
1 2 3
4 5 6
7 8 9
2nd Row: 4 5 6
After adding 3 times the first column into the third column, the matrix m is:
 1  2  6
 4  5 18
 7  8 30

3. 矩阵Corner操作

3.1 定义

Eigen特别地提供了矩阵的一角,或者是数列的某一端的块操作

意义 动态size (dynamic-size) 固定size (fixed-size block)
左上 matrix.topLeftCorner(p,q); matrix.topLeftCorner<p,q>();
左下 matrix.bottomLeftCorner(p,q); matrix.bottomLeftCorner<p,q>();
右上 matrix.topRightCorner(p,q); matrix.topRightCorner<p,q>();
右下 matrix.bottomRightCorner(p,q); matrix.bottomRightCorner<p,q>();
前q行块 matrix.topRows(q); matrix.topRows<q>();
后q行块 matrix.bottomRows(q); matrix.bottomRows<q>();
前p列块 matrix.leftCols(p); matrix.leftCols<p>();
后q列块 matrix.rightCols(q); matrix.rightCols<q>();

3.2 栗子

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::Matrix4f m;
  m << 1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10,11,12,
       13,14,15,16;
  cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;
  cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;
  m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose();
  cout << "After assignment, m = " << endl << m << endl;
}

Output:

m.leftCols(2) =
 1  2
 5  6
 9 10
13 14

m.bottomRows<2>() =
 9 10 11 12
13 14 15 16

After assignment, m = 
 8 12 16  4
 5  6  7  8
 9 10 11 12
13 14 15 16

4. 矩阵Vector操作

4.1 定义

意义 动态size (dynamic-size) 固定size (fixed-size block)
前n元素块 vector.head(n); vector.head<n>();
后n元素块 vector.tail(n); vector.tail<n>();
从i位置开始的n元素块 vector.segment(i,n); vector.segment<n>(i);

4.2 栗子

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;
  cout << "v.head(3) =" << endl << v.head(3) << endl << endl;
  cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl;
  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}

Output

v.head(3) =
1
2
3

v.tail<3>() = 
4
5
6

after 'v.segment(1,4) *= 2', v =
 1
 4
 6
 8
10
 6

Ref:
http://eigen.tuxfamily.org/dox-3.2/group__TutorialBlockOperations.html
http://eigen.tuxfamily.org/dox-3.2/
本文基于版本 Eigen 3.2.10

发布了5 篇原创文章 · 获赞 6 · 访问量 6085

猜你喜欢

转载自blog.csdn.net/mmLxfz/article/details/90444825