六、矩阵的块操作(block)
1.块操作的定义
在Eigen库中,可以使用函数 .block() 来提取矩阵中的某一个区域, .block() 有两种形式,两种形式的功能是等价的。在Eigen库中,索引是从0开始的。
定义一个从元素(i, j)为起点,大小为(p, q)的块:
使用动态尺寸的block进行构建: .block(i, j, p, q)
使用固定尺寸的block进行构建: .block< p,q >(i, j)
以下代码详细地使用了两种块的方式进行block操作:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main() {
Eigen::MatrixXf m(4, 4);
m << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16;
std::cout << "***************************" << std::endl;
std::cout << "起点元素(1,1),大小为(2,2)的块" << std::endl;
std::cout << m.block<2, 2>(1, 1) << std::endl; //使用固定大小的block,起始元素(1,1),块大小(2,2)
for (int i = 1; i <= 3; ++i) {
std::cout << "***************************" << std::endl;
std::cout << "块的大小为" << i << "x" << i << std::endl;
std::cout << m.block(0, 0, i, i) << std::endl; //使用动态大小的block,起始元素(0,0),块大小(i,i)
}
}
代码输出结果如下,需要自己好好品味一下:
***************************
起点元素(1,1),大小为(2,2)的块
6 7
10 11
***************************
块的大小为1x1
1
***************************
块的大小为2x2
1 2
5 6
***************************
块的大小为3x3
1 2 3
5 6 7
9 10 11
在Eigen中,块还能直接作为左值来修改矩阵中的某一区域的元素,具体的使用方法可以参考如下的示例代码:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main() {
Eigen::Array22f m;
m << 1, 2,
3, 4;
Eigen::Array44f a = Array44f::Constant(0.1);
std::cout << "***************************" << std::endl;
std::cout << "数组a:" << std::endl << a << std::endl;
std::cout << "***************************" << std::endl;
a.block<2,2>(1,1) = m;
std::cout << "将数组m赋值给数组a中的中心 2x2 block:" << std::endl << a << std::endl;
std::cout << "***************************" << std::endl;
a.block(0,0,2,3) = a.block(2,1,2,3);
std::cout << "将数组a右下角 2x3 block赋值给数组a左上角 2x3 block:" << std::endl << a << std::endl;
}
上述代码的输出结果如下:
***************************
数组a:
0.1 0.1 0.1 0.1
0.1 0.1 0.1 0.1
0.1 0.1 0.1 0.1
0.1 0.1 0.1 0.1
***************************
将数组m赋值给数组a中的中心 2x2 block:
0.1 0.1 0.1 0.1
0.1 1 2 0.1
0.1 3 4 0.1
0.1 0.1 0.1 0.1
***************************
将数组a右下角 2x3 block赋值给数组a左上角 2x3 block:
3 4 0.1 0.1
0.1 0.1 0.1 0.1
0.1 3 4 0.1
0.1 0.1 0.1 0.1
2.矩阵的行操作和列操作
在Eigen中,提供了直接对矩阵的某行或者某列进行计算的操作接口,这部分功能类似于python中numpy库的切片操作,也是极其方便的功能。
行操作:matrix.row(i)
列操作:matrix.col(j)
具体的应用参考如下示例代码:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main() {
Eigen::MatrixXf m(3,3);
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << "***************************" << std::endl;
std::cout << "矩阵m:" << std::endl << m << std::endl;
std::cout << "***************************" << std::endl;
std::cout << "矩阵m的第2行:" << std::endl << m.row(1) << std::endl;
std::cout << "***************************" << std::endl;
m.col(2) += 3 * m.col(0);
std::cout << "将矩阵m的第一列乘以上然后加到矩阵m的第3列上:" << std::endl << m << std::endl;
}
输出结果如下:
***************************
矩阵m:
1 2 3
4 5 6
7 8 9
***************************
矩阵m的第2行:
4 5 6
***************************
将矩阵m的第一列乘以上然后加到矩阵m的第3列上:
1 2 6
4 5 18
7 8 30
3.矩阵的角相关操作
左上角p*q:matrix.topLeftCorner(p,q);
matrix.topLeftCorner< p,q >();
左下角p*q:matrix.bottomLeftCorner(p,q);
matrix.bottomLeftCorner< p,q >();
右上角p*q:matrix.topRightCorner(p,q);
matrix.topRightCorner< p,q >();
右下角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§;
matrix.leftCols< p >();
右p列:matrix.rightCols§;
matrix.rightCols< p >();
示例代码:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main() {
Eigen::Matrix4f m;
m << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16;
std::cout << "***************************" << std::endl;
std::cout << "m.leftCols(2) = " << std::endl << m.leftCols(2) << std::endl;
std::cout << "***************************" << std::endl;
std::cout << "m.bottomRows<2>() = " << std::endl << m.bottomRows<2>() << std::endl;
std::cout << "***************************" << std::endl;
m.topLeftCorner(1, 3) = m.bottomRightCorner(3,1).transpose();
std::cout << "矩阵分配后,m = :" << std::endl << m << std::endl;
}
输出结果为:
***************************
m.leftCols(2) =
1 2
5 6
9 10
13 14
***************************
m.bottomRows<2>() =
9 10 11 12
13 14 15 16
***************************
矩阵分配后,m = :
8 12 16 4
5 6 7 8
9 10 11 12
13 14 15 16
4.vectors的块操作
前n个:vector.head(n);
vector.head< n >();
后n个:vector.tail(n);
vector.tail< n >();
i起始的n个元素:vector.segment(i,n);
vector.segment< n >(i);
更多技术欢迎加入交流:320297153