C++——Eigen库的学习(5)

六、矩阵的块操作(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

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值