当前位置: 首页 > 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.dtcms.com/a/303073.html

相关文章:

  • 秩为1的矩阵的特征和性质
  • WireShark 抓包
  • Spring Boot项目生产环境部署完整指南
  • 数学建模算法-day[13]
  • 判断回文链表【两种O(n)时间复杂度】
  • iOS WebView 调试实战,第三方脚本加载失败与内容安全策略冲突问题排查指南
  • 前端高级综合搜索组件 SearchBox 使用详解!
  • React中的合成事件解释和理解
  • 归档日志-binlog
  • C语言的各种区
  • 背包DP之混合背包
  • 解决安装anaconda3后如何打开anaconda navigator的问题
  • 解构远程智能系统的视频能力链:从RTSP|RTMP协议接入到Unity3D头显呈现全流程指南
  • 力扣刷题(第一百零一天)
  • 0728 哈希表折半查找树二叉树
  • 【mysql】创建视图查询当月累计销售额的案例
  • python案例分析:基于新能源汽车论坛评价数据情感分析的客户满意度研究,文本挖掘包括lda主题分析和词频分析、情感分析、网络语义分析
  • 搜索二维矩阵Ⅱ C++
  • 【无标题】暗物质衰减现象解释
  • 二十一、动植物类(自然生态)
  • 鱼皮项目简易版 RPC 框架开发(三)
  • Python 实现多服务器并发启动 SDK-C Master 与 Viewer 的分布式方案
  • [尚庭公寓]15-个人中心
  • 力扣-22.括号生成
  • C++初学者4——标准数据类型
  • JavaScript对象与Math对象完全指南
  • 力扣7:整数反转
  • 利用DataStream和TrafficPeak实现大数据可观察性
  • jQuery 最新语法大全详解(2025版)
  • 下载k8s官方组件chart和容器镜像