kimera semantic的SemanticTsdfServer继承了voxblox的TsdfServer,有自己的单独的semanticlayer,使用了自己的semantic的integrator。
流程与voxblox的一致,记录一下:
void FastSemanticTsdfIntegrator::integrateSemanticFunction
该函数前面做的事情就是如同voxblox一样,更新继承的voxel层,然后更新semanticlayer。
updateTsdfVoxel(origin, point_G, global_voxel_idx, color, weight, voxel);
SemanticVoxel* semantic_voxel = allocateStorageAndGetSemanticVoxelPtr(
global_voxel_idx, &semantic_block, &semantic_block_idx);
SemanticProbabilities semantic_label_frequencies =
SemanticProbabilities::Zero();
CHECK_LT(semantic_label, semantic_label_frequencies.size());
semantic_label_frequencies[semantic_label] += 1.0f;
updateSemanticVoxel(global_voxel_idx,
semantic_label_frequencies,
&mutexes_,
voxel,
semantic_voxel);
// TODO(Toni): ideally, return new_sdf from updateTsdfVoxel, but we need to
// modify Voxblox for that.
// Similar to color blending in Voxblox tsdf_integrator.cc,
// Quoting Voxblox:
// color blending is expensive only do it close to the surface
// if (std::abs(sdf) < config_.default_truncation_distance) {
// Do the same for semantic updates:
// Don't do it bcs of copyrights... :'(
////// Here is the actual logic of Kimera-Semantics: /////////////////////
// Calculate new probabilities given the measurement frequencies.
updateSemanticVoxelProbabilities(measurement_frequencies,
&semantic_voxel->semantic_priors);
// Get MLE semantic label.
calculateMaximumLikelihoodLabel(semantic_voxel->semantic_priors,
&semantic_voxel->semantic_label);
// Colorize according to current MLE semantic label.
updateSemanticVoxelColor(semantic_voxel->semantic_label,
&semantic_voxel->color);
updateSemanticVoxelProbabilities的实现很简单:
*semantic_prior_probability +=
semantic_log_likelihood_ * measurement_frequencies;
其中,semantic_log_likelihood_这个是hardcode的一个似然模型。比如label数量是N,则记录一个N*N的矩阵,矩阵的一行如苹果,代表了如果看到的结果是苹果,那么实际上,是其他物体的概率,如是地板的概率为0,是苹果的概率为0.9,是雪梨的概率为0.05,是香蕉的概率为0,等,记录该行对应的列的位置。
measurement_frequencies是一个列向量,对应着此次观测的物品的概率。如香蕉的概率为0.8。。。
在对得到的某个semantic分割的像素进行更新某个voxel时,因为label的数字是唯一的(深度学习学出来的)直接把measurement_frequencies对应的该label的位置改为1,其他为0.
实际上,如果带了confidence,可以把1改为对应的confidence(如果数据量的问题不能输出全部的类别的概率,就只关注这个得出来的最高的label概率就行)。
semantic_log_likelihood_measurement_frequencies得到的是一个N1的列向量,里面记录了该voxel对应的不同label的概率。
接下来的calculateMaximumLikelihoodLabel,就是挑选对应的最大概率的label:
semantic_posterior.maxCoeff(semantic_label);
而updateSemanticVoxelColor这个仅仅是赋予label对应的颜色,给人看的,可以不需要这种操作。