| 266 | } |
| 267 | |
| 268 | void ObjectUpdateFunctor::detectObjects(DynamicSceneGraph& graph) const { |
| 269 | const auto& segments = graph.getLayer(DsgLayers::SEGMENTS); |
| 270 | |
| 271 | const ClusteringWorkspace total_ws(segments); |
| 272 | const auto py_all = computeIBpy(*tasks_); |
| 273 | const auto px_all = computeIBpx(total_ws); |
| 274 | const auto py_x_all = |
| 275 | computeIBpyGivenX(total_ws, *tasks_, *metric_, config.selector.py_x); |
| 276 | double I_xy_all = mutualInformation(py_all, px_all, py_x_all); |
| 277 | |
| 278 | // connected component search |
| 279 | const auto new_components = graph_utilities::getConnectedComponents( |
| 280 | segments, |
| 281 | [&](const auto& n) { return isNodeActive(n, node_to_component_, ignored_); }, |
| 282 | [&](const auto& edge) { |
| 283 | const auto source_active = |
| 284 | isNodeActive(segments.getNode(edge.source), node_to_component_, ignored_); |
| 285 | const auto target_active = |
| 286 | isNodeActive(segments.getNode(edge.target), node_to_component_, ignored_); |
| 287 | return source_active && target_active; |
| 288 | }); |
| 289 | |
| 290 | // reassign components |
| 291 | for (const auto& nodes : new_components) { |
| 292 | size_t new_id = components_ids_.next(); |
| 293 | auto new_component = std::make_unique<ComponentInfo>( |
| 294 | config.selector, *tasks_, *metric_, segments, nodes, I_xy_all); |
| 295 | for (const auto node_id : nodes) { |
| 296 | node_to_component_[node_id] = new_id; |
| 297 | } |
| 298 | |
| 299 | const auto clusters = new_component->ws.getClusters(); |
| 300 | for (const auto& cluster : clusters) { |
| 301 | VLOG(5) << "Cluster: " << displayNodeSymbolContainer(cluster); |
| 302 | |
| 303 | auto attrs = getMergedAttributes(graph, cluster); |
| 304 | if (!attrs) { |
| 305 | LOG(ERROR) << "empty cluster!"; |
| 306 | continue; |
| 307 | } |
| 308 | |
| 309 | const auto& feature = |
| 310 | CHECK_NOTNULL(dynamic_cast<SemanticNodeAttributes*>(attrs.get())) |
| 311 | ->semantic_feature; |
| 312 | const auto result = tasks_->getBestScore(*metric_, feature); |
| 313 | if (result.score < config.min_object_score) { |
| 314 | VLOG(1) << "Skipping object with score: " << result.score; |
| 315 | continue; |
| 316 | } |
| 317 | |
| 318 | graph.emplaceNode(DsgLayers::OBJECTS, next_node_id_, std::move(attrs)); |
| 319 | new_component->objects.push_back(next_node_id_); |
| 320 | |
| 321 | const auto parent = getBestParent(graph, cluster); |
| 322 | if (!parent) { |
| 323 | LOG(WARNING) << "object '" << next_node_id_.getLabel() << "' without parent!"; |
| 324 | active_.insert(next_node_id_); |
| 325 | } else { |
nothing calls this directly
no test coverage detected