当前位置: 首页 > news >正文

Eigen 中矩阵的拼接(Concatenation)与 分块(Block Access)操作使用详解和示例演示

一、矩阵分块访问(Block)

Eigen 使用 .block().topLeftCorner().row().col() 等函数进行矩阵子块访问:

1.1 block(i, j, rows, cols) — 访问子块

MatrixXd mat(4, 4);
mat << 1, 2, 3, 4,5, 6, 7, 8,9,10,11,12,13,14,15,16;MatrixXd sub = mat.block(1, 1, 2, 2); // 从(1,1)取2x2子矩阵

1.2 快捷方式访问角落区域

mat.topLeftCorner(2, 2);
mat.bottomRightCorner(2, 2);
mat.topRows(2);
mat.leftCols(3);

1.3 修改子块

mat.block(0, 0, 2, 2) = Matrix2d::Ones();

二、矩阵拼接(Concatenation)

2.1 横向拼接(水平拼接)

MatrixXd A(2, 2), B(2, 3);
A << 1, 2, 3, 4;
B << 5, 6, 7, 8, 9, 10;MatrixXd C(A.rows(), A.cols() + B.cols());
C << A, B;  // 水平拼接

2.2 纵向拼接(垂直拼接)

MatrixXd D(3, 2);
D << 11, 12,13, 14,15, 16;MatrixXd E(A.rows() + D.rows(), A.cols());
E << A,D;  // 垂直拼接

三、动态拼接(适用于未知大小)

Eigen 不直接支持 push_back,可通过 resize + block 实现:

MatrixXd total(0, 2);  // 初始空矩阵,列数固定为2
MatrixXd row(1, 2);
row << 1, 2;total.conservativeResize(total.rows() + 1, NoChange);  // 保持列数不变
total.bottomRows(1) = row;

四、行列访问与赋值

Matrix3d A;
A.row(0) = RowVector3d(1, 2, 3);    // 设置第1行
A.col(1) = Vector3d(4, 5, 6);       // 设置第2列

五、分块迭代

可用于滑动窗口、图块处理等:

MatrixXd big = MatrixXd::Random(6, 6);
for (int i = 0; i < big.rows(); i += 3) {for (int j = 0; j < big.cols(); j += 3) {MatrixXd block = big.block(i, j, 3, 3);std::cout << "Block at (" << i << "," << j << "):\n" << block << std::endl;}
}

六、拼接 Vector(向量拼接)

Eigen 无直接 append 接口,可手动拼接:

Vector3d a(1, 2, 3);
Vector2d b(4, 5);VectorXd c(a.size() + b.size());
c << a, b;   // 拼接为5维向量

七、矩阵拼接的注意事项

操作方式是否推荐原因说明
conservativeResize() + 赋值✅ 推荐动态拼接、可扩展
std::vector<MatrixXd> 后合并✅ 推荐适合收集多个块再整体合并
STL push_back 模拟拼接❌ 不推荐Eigen 矩阵不是 STL 容器,效率低

八、示例演示

1、信息矩阵拼接示例

图优化中常构建如下稀疏结构矩阵:

H=[H11H120H12TH22H230H23TH33] H = \begin{bmatrix} H_{11} & H_{12} & 0 \\ H_{12}^T & H_{22} & H_{23} \\ 0 & H_{23}^T & H_{33} \end{bmatrix} H=H11H12T0H12H22H23T0H23H33

MatrixXd H(9, 9);
H.setZero();MatrixXd H11 = MatrixXd::Identity(3, 3);
MatrixXd H12 = MatrixXd::Constant(3, 3, 0.5);
MatrixXd H22 = MatrixXd::Identity(3, 3) * 2;
MatrixXd H23 = MatrixXd::Constant(3, 3, 1.0);
MatrixXd H33 = MatrixXd::Identity(3, 3) * 3;H.block(0, 0, 3, 3) = H11;
H.block(0, 3, 3, 3) = H12;
H.block(3, 0, 3, 3) = H12.transpose();
H.block(3, 3, 3, 3) = H22;
H.block(3, 6, 3, 3) = H23;
H.block(6, 3, 3, 3) = H23.transpose();
H.block(6, 6, 3, 3) = H33;

2、矩阵合并示例

处理多个点云帧时,常需将坐标矩阵拼接成大块矩阵以用于 SVD 或最小二乘:

std::vector<Vector3d> cloudA = { Vector3d(1,2,3), Vector3d(4,5,6) };
std::vector<Vector3d> cloudB = { Vector3d(7,8,9), Vector3d(10,11,12) };MatrixXd matA(3, cloudA.size());
MatrixXd matB(3, cloudB.size());
for (size_t i = 0; i < cloudA.size(); ++i) {matA.col(i) = cloudA[i];matB.col(i) = cloudB[i];
}// 拼接为 6xN 点对矩阵
MatrixXd combined(6, cloudA.size());
combined << matA,matB;

3、使用 SparseMatrix 进行分块拼接(稀疏构图)示例

对于大规模问题,更推荐使用稀疏矩阵拼接:

#include <Eigen/Sparse>
using namespace Eigen;typedef SparseMatrix<double> SpMat;
std::vector<Triplet<double>> triplets;int block_size = 3;// 插入块 (i,j)
Matrix3d block = Matrix3d::Identity();
for (int i = 0; i < block_size; ++i)for (int j = 0; j < block_size; ++j)triplets.emplace_back(i + 3, j + 3, block(i,j));  // 插入到 H(3:6, 3:6)SpMat H_sparse(9, 9);
H_sparse.setFromTriplets(triplets.begin(), triplets.end());

4、构建动态扩展矩阵队列(如 sliding window)示例

可维护多帧 pose 或 observation:

std::vector<MatrixXd> pose_blocks;// 每次新状态加入
MatrixXd new_pose(6, 1); // 6 DOF
new_pose.setRandom();
pose_blocks.push_back(new_pose);// 拼接为整体大矩阵
MatrixXd all_pose(6, pose_blocks.size());
for (size_t i = 0; i < pose_blocks.size(); ++i)all_pose.col(i) = pose_blocks[i];

5、拆分一个大矩阵为多个子块示例

例如将优化后的状态拆成多个节点:

VectorXd x = VectorXd::LinSpaced(18, 1, 18);  // 假设每 6 为一帧状态
int n = x.size() / 6;std::vector<VectorXd> frames;
for (int i = 0; i < n; ++i)frames.push_back(x.segment(i * 6, 6));  // 拆成多个6维状态

九、总结-拼接与分块方法对比

方法用途是否动态备注
.block(i,j,r,c)任意子块读写高效
conservativeResize() + bottomRows()逐行拼接常用于采样/流式输入
std::vector<MatrixXd>先收集后合并推荐
稀疏矩阵 Triplet 方式大规模稀疏拼接图优化必备
.segment()拆向量高效

http://www.lryc.cn/news/602279.html

相关文章:

  • 简明量子态密度矩阵理论知识点总结
  • 搜索二维矩阵Ⅱ C++
  • 【LeetCode】算法详解#10 ---搜索二维矩阵II
  • 秩为1的矩阵的特征和性质
  • 青少年编程高阶课程介绍
  • 青少年编程中阶课
  • 『 C++ 入门到放弃 』- 哈希表
  • 攻防世界-引导-Web_php_unserialize
  • 《LeetCode 热题 100》整整 100 题量大管饱题解套餐 中
  • cacti的RCE
  • 关于“PromptPilot” 之3 -Prompt构造器核心专项能力:任务调度
  • keepalived原理及实战部署
  • MBR和GPT分区的区别
  • 电商项目DevOps一体化运维实战
  • 【Datawhale夏令营】端侧Agent开发实践
  • CodeBuddy的安装教程
  • JAVA东郊到家按摩服务同款同城家政服务按摩私教茶艺师服务系统小程序+公众号+APP+H5
  • 基于BEKK-GARCH模型的参数估计、最大似然估计以及参数标准误估计的MATLAB实现
  • openlayer根据不同的状态显示不同的图层颜色
  • Fortran实现 3维反距离加权(IDW)插值算法
  • 初识 docker [下] 项目部署
  • ETH 交易流程深度技术详解
  • 二、Linux文本处理与文件操作核心命令
  • 从0开始学习R语言--Day60--EM插补法
  • git stash apply 冲突合并方法解决
  • Kafka 3.9.1的KRaft模式部署
  • linux系统----Ansible中的playbook简单应用
  • 从零开始的云计算生活——第三十七天,跬步千里,ansible之playbook
  • 【Blender小技巧】Blender使用多边形建形工具创建多边形模型,挤出面,模型创建修改编辑UV贴图
  • 【第四章:大模型(LLM)】01.神经网络中的 NLP-(2)Seq2Seq 原理及代码解析