摘要
Kimera-Semantics 是 MIT SPARK 实验室开源的实时三维度量-语义重建库(ICRA 2020,arXiv:1910.02490),依托 Voxblox 的 TSDF(Truncated Signed Distance Field)体素框架,将外部 2D 语义分割标签融入三维几何重建,输出带语义标注的全局 3D 网格 。系统提供两种积分器:fast(~0.1 s/帧,速度优先)和 merged(~1 s/帧,精度优先),核心差异在光线投射策略上。每个体素用对数概率向量存储各类别后验,通过 Bayesian 逐帧更新,最终取最大后验类别作为语义标签。本文从数据结构、融合算法、双路积分器设计到 ROS 集成完整梳理实现细节。
一、系统定位与模块依赖
Kimera-Semantics 在整个 Kimera 框架中处于最后一层,消费上游模块的输出:
位姿 T_W_C
逐像素语义标签图
Dense Stereo 深度图
(StereoBM)
TSDF 体素层
Stereo 双目图像
Kimera-VIO
视觉惯性里程计
IMU
外部 2D 语义分割
DeepLab / Mask-RCNN 等
Kimera-Semantics
SemanticTsdfServer
Marching Cubes
语义 Mesh 提取
全局语义 3D Mesh
与 Kimera-Mesher 的核心区别:
| 对比项 | Kimera-Mesher | Kimera-Semantics |
|---|---|---|
| 重建方法 | 2D Delaunay → 3D 反投影 | TSDF 体素 + Bundled Raycasting |
| 处理延迟 | < 20 ms | 0.1--1 s |
| 全局一致性 | 多帧融合窗口 | 全局 TSDF 累积 |
| 精度(EuRoC V1_01 RMSE) | 0.482 m | 0.364 m |
| 语义融合方式 | 三角面片纹理贴图 | 体素级 Bayesian 概率更新 |
二、核心数据结构
2.1 SemanticVoxel:带语义的体素单元
kimera_semantics/include/kimera_semantics/semantic_voxel.h
cpp
struct SemanticVoxel {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
SemanticLabel semantic_label = 0u; // 当前最大后验标签
SemanticProbabilities semantic_priors = // 各类别对数概率向量
SemanticProbabilities::Constant(-0.60205999132f); // log(1/N) 均匀初始化
HashableColor color = HashableColor::Gray();// 可视化颜色
};
三个设计细节值得关注:
- 对数概率(Log-odds)存储 :不存原始概率,而是存 logp(ck)\log p(c_k)logp(ck),将 Bayesian 乘法更新转为加法,避免浮点下溢。
- 均匀先验初始化 :
-0.60205999132 ≈ log(1/N_labels),即所有类别等概率,体现"未观测则不偏向任何语义"的设计意图。 - 颜色与标签同步 :
color字段在每次语义更新后由updateSemanticVoxel()同步,使 Voxblox 下游网格提取直接复用颜色信息,无需额外映射。
2.2 语义颜色映射表
SemanticLabel2Color 维护双向映射,前 8 个标签使用预定义颜色,其余随机分配:
| Label ID | 颜色 | 语义类别 |
|---|---|---|
| 0 | 灰色 | Unknown(未知) |
| 1 | 绿色 | Ceiling(天花板) |
| 2 | 蓝色 | Chair(椅子) |
| 3 | 紫色 | Floor(地面) |
| 4 | 粉色 | Objects/Furniture |
| 5 | 青色 | Sofa(沙发) |
| 6 | 橙色 | Table(桌子) |
| 7 | 黄色 | Wall/Window/TV/Board |
颜色编码通过 HashableColor(对 vxb::Color 的扩展,支持哈希运算)实现从 RGB 像素到语义标签的O(1) 反查,支持语义图以 RGB 编码标签直接输入。
三、语义融合算法:Bayesian 对数概率更新
3.1 似然矩阵(Semantic Log-Likelihood Matrix)构建
SemanticIntegratorBase(semantic_integrator_base.h/cpp)初始化时构建 N×NN \times NN×N 的对数似然矩阵 L\mathbf{L}L(NNN 为语义类别总数):
Lij={logpmatchif i=jlog(1−pmatch)if i≠j0if j=unknown label(第0列) \mathbf{L}{ij} = \begin{cases} \log p{\text{match}} & \text{if } i = j \\ \log(1 - p_{\text{match}}) & \text{if } i \neq j \\ 0 & \text{if } j = \text{unknown label(第0列)} \end{cases} Lij=⎩ ⎨ ⎧logpmatchlog(1−pmatch)0if i=jif i=jif j=unknown label(第0列)
其中 pmatch=0.9p_{\text{match}} = 0.9pmatch=0.9(默认观测置信度),表示"传感器测量到类别 jjj 时,该体素真实类别为 jjj 的概率为 90%"。第 0 列(unknown)置零,避免"未知"标签对已有语义先验的干扰。
3.2 体素更新:逐帧 Bayesian 累积
每次新的语义点云帧到达,对每个被光线穿过的体素执行:
pvoxel(t)+=L⋅fobs \mathbf{p}^{(t)}{\text{voxel}} \mathrel{+}= \mathbf{L} \cdot \mathbf{f}{\text{obs}} pvoxel(t)+=L⋅fobs
其中:
- pvoxel(t)∈RN\mathbf{p}^{(t)}_{\text{voxel}} \in \mathbb{R}^Npvoxel(t)∈RN:体素当前对数概率向量(累积量)
- L∈RN×N\mathbf{L} \in \mathbb{R}^{N \times N}L∈RN×N:上述对数似然矩阵
- fobs∈RN\mathbf{f}_{\text{obs}} \in \mathbb{R}^Nfobs∈RN:本帧在该体素方向上的观测频率向量(某条射线束中各标签的频率统计)
加法等价于概率乘法(对数空间性质):
logp(t)(ck)=logp(t−1)(ck)+logp(ot∣ck) \log p^{(t)}(c_k) = \log p^{(t-1)}(c_k) + \log p(\mathbf{o}_t \mid c_k) logp(t)(ck)=logp(t−1)(ck)+logp(ot∣ck)
3.3 归一化与最大后验标签提取
每次更新后执行归一化(Euclidean norm,非 softmax):
if norm(p) == 0: p = uniform log-probability
else: p = p / ||p||
最终标签取对数概率最大分量:
c^=argmaxk pk(t) \hat{c} = \arg\max_k \, p^{(t)}_k c^=argkmaxpk(t)
完整更新流程如下:
新语义点云帧
(点位置 + 语义标签)
光线投射
Raycasting
统计射线束中各标签频率
f_obs ∈ ℝ^N
体素对数概率更新
p += L · f_obs
归一化
p = p / ||p||
最大后验标签
c_hat = argmax(p)
更新 semantic_label
- 同步颜色 color
TSDF 体素颜色写入
供 Marching Cubes 使用
3.4 动态物体过滤
通过 isSemanticLabelValid() 过滤被标记为动态的类别(如 label 20 = 人类),这些标签对应的点不参与 TSDF 更新,避免运动物体污染静态地图。
四、双路积分器:Fast vs Merged
两种积分器均继承 SemanticIntegratorBase,差异在几何 TSDF 更新策略。
4.1 FastSemanticTsdfIntegrator
继承 Voxblox 的 FastTsdfIntegrator,核心加速机制:
① 近似哈希集提前终止
维护两个 ApproxHashSet(各占 ~8 MB 内存):
| 集合 | 作用 |
|---|---|
start_voxel_approx_set_ |
防止同一扫描中同一起始体素重复投射光线 |
voxel_observed_approx_set_ |
记录当前帧已更新体素 |
当光线连续经过 max_consecutive_ray_collisions 个已更新 体素时,该光线提前终止,跳过自由空间更新------这正是大部分帧间计算量的来源。
② 体素下采样
参数 start_voxel_subsampling_factor 控制每个体素发出的光线数上限,进一步削减冗余投射。
内存重置极低频率(每 10,000 帧一次),实际运行中几乎无 GC 开销。
性能 :约 0.1 s/帧,比 Merged 方法快约一个数量级。
4.2 MergedSemanticTsdfIntegrator
继承 Voxblox 的 MergedTsdfIntegrator,核心机制是光线束合并(Ray Bundling):
同一体素内的多个点被"合并"为一个代表点,仅发出一条光线。
适合大体素尺寸场景(体素内多点密度高时合并效果好),精度高于 Fast 方法,但计算量约高 10 倍(~1 s/帧)。
并行化通过 integrateVoxels() → 多线程 integrateVoxel() 实现,每个体素的更新为线程安全。
MergedIntegrator
点云按体素哈希分组
同体素多点合并为一
单光线 TSDF 更新
语义频率统计后 Bayesian 更新
FastIntegrator
连续命中则
继续
每条光线独立投射
ApproxHashSet
已更新体素检测
提前终止 Early Exit
TSDF + 语义更新
4.3 积分器选择策略
| 场景 | 推荐积分器 | 理由 |
|---|---|---|
| 实时机器人导航 | fast |
0.1 s 满足感知-规划周期 |
| 离线精细建图 | merged |
更完整的自由空间更新,精度更高 |
| 小体素(< 3 cm) | fast ≈ merged |
小体素下合并效果有限,两者差距缩小 |
| 大体素(> 10 cm) | merged 优势更大 |
体素内点密度高,合并收益大 |
五、ROS 集成:SemanticTsdfServer
5.1 节点架构
vxb::Layer
/semantic_pointcloud
语义点云
SemanticTsdfServer
kimera_semantics_node
/tesse/left_cam/image_raw
左目图像
/tesse/segmentation/image_raw
2D 语义分割图
/tesse/depth/image_raw
深度图
TF: left_cam_base_link → world
(由 Kimera-VIO 发布)
Marching Cubes
网格提取
/semantic_mesh
发布语义 Mesh
/tsdf_pointcloud
调试点云
SemanticTsdfServer 继承 vxb::TsdfServer,在其基础上增加独立的 semantic_layer_(vxb::Layer<SemanticVoxel>),由工厂 SemanticTsdfIntegratorFactory::create() 根据参数实例化 Fast 或 Merged 积分器。
5.2 关键 Launch 参数
| 参数 | 默认值 | 说明 |
|---|---|---|
voxel_size |
0.05 m | TSDF 体素分辨率 |
max_ray_length_m |
5 m | 光线最大长度 |
metric_semantic_reconstruction |
true | 开启语义模式 |
semantic_tsdf_integrator_type |
"fast" |
积分器类型 |
run_stereo_dense |
false | 用 StereoBM 生成深度图 |
sensor_frame |
left_cam |
传感器坐标系 |
dynamic_labels |
[20] | 动态物体标签(人类) |
rosbag_rate |
2.0 | rosbag 回放倍速 |
5.3 与 Kimera-VIO 的连接点
Kimera-VIO-ROS 以 left_cam_base_link 发布 TF,Kimera-Semantics 以此 TF 将点云从相机系变换到世界系后再积分 TSDF。sensor_frame 参数可在仿真(地面真值 left_cam)和真实系统(VIO 估计 left_cam_base_link)间切换,便于精度对比。
六、实验性能数据
运行时延(EuRoC MH/V1/V2 序列)
| 积分器类型 | 帧处理时间 | 相对加速比 |
|---|---|---|
merged |
~1.0 s | 1× |
fast |
~0.1 s | 约 10× |
网格精度(EuRoC V1/V2,RMSE,ICP 阈值 1.0 m)
| 序列 | Mesher 多帧 [m] | Semantics 全局 [m] | 提升 [%] |
|---|---|---|---|
| V1_01 | 0.482 | 0.364 | +24 |
| V1_03 | 0.451 | 0.353 | +22 |
| V2_02 | 0.491 | 0.432 | +12 |
| V2_03 | 0.530 | 0.411 | +22 |
全局语义网格在大多数序列误差下降 12--24%,代价是处理时间高约两个数量级。
小结
Kimera-Semantics 的三个核心设计决策:
-
对数概率向量而非单一标签 :每个体素维护 NNN 维对数概率,多帧观测通过加法累积而非覆盖,天然抗噪且不遗忘历史------这是与简单"最新标签覆盖"方案的根本区别。
-
Fast 积分器的近似哈希提前终止:用 8 MB 近似集换取约 10 倍速度提升,且近似误差主要体现在自由空间(空体素)的更新遗漏,而非占用表面,对最终网格精度影响有限。这是工程上典型的"精度换速度"权衡,且损失可控。
-
动态物体标签过滤(label 20 = 人):在 TSDF 积分前剔除动态标签对应点,比后处理(建图后再删除)更干净,避免动态物体在 TSDF 中留下"幽灵体素"。
局限性 :语义质量完全依赖外部 2D 分割模型,系统无自我修正机制;merged 积分器在 CPU 实时约束下难以部署(1 s/帧);TSDF 分辨率受内存限制,大规模室外场景需搭配空间哈希(Voxblox 已支持,但参数调优较复杂)。
参考资料
- Rosinol A. et al., Kimera: an Open-Source Library for Real-Time Metric-Semantic Localization and Mapping, ICRA 2020. arXiv:1910.02490
- Oleynikova H. et al., Voxblox: Incremental 3D Euclidean Signed Distance Fields for On-Board MAV Planning, IROS 2017.
- 代码仓库:https://github.com/MIT-SPARK/Kimera-Semantics