25 #include <boost/graph/adjacency_list.hpp>
26 #include <boost/graph/graph_concepts.hpp>
27 #include <boost/graph/subgraph.hpp>
37 #include <boost/smart_ptr/make_shared.hpp>
39 #include <pcl/filters/approximate_voxel_grid.h>
40 #include <pcl/filters/filter.h>
41 #include <pcl/filters/voxel_grid.h>
67 std::unique_lock lock(write_mutex_);
68 config_.commitWrite();
69 usingPointCloudProvider(getProperty<std::string>(
"ProviderName").getValue());
81 enableResultPointClouds<PointT>(
"CRFSegmentationResult");
82 enableResultPointClouds<pcl::PointXYZI>(
"CRFSegmentationConfidence");
83 if (config_.getUpToDateReadBuffer().out.provide_graph_pclouds)
86 enableResultPointClouds<PointT>(
"Graph0");
87 enableResultPointClouds<PointT>(
"Graph1");
88 enableResultPointClouds<PointT>(
"Graph2");
89 enableResultPointClouds<PointT>(
"Graph3");
90 enableResultPointClouds<PointT>(
"Graph4");
93 if (config_.getUpToDateReadBuffer().out.provide_confidence_pclouds)
95 if (config_.getUpToDateReadBuffer().out.colorize_confidence_pclouds)
98 enableResultPointClouds<PointT>(
"Confidence0");
99 enableResultPointClouds<PointT>(
"Confidence1");
100 enableResultPointClouds<PointT>(
"Confidence2");
101 enableResultPointClouds<PointT>(
"Confidence3");
102 enableResultPointClouds<PointT>(
"Confidence4");
107 enableResultPointClouds<pcl::PointXYZI>(
"Confidence0");
108 enableResultPointClouds<pcl::PointXYZI>(
"Confidence1");
109 enableResultPointClouds<pcl::PointXYZI>(
"Confidence2");
110 enableResultPointClouds<pcl::PointXYZI>(
"Confidence3");
111 enableResultPointClouds<pcl::PointXYZI>(
"Confidence4");
117 createOrUpdateRemoteGuiTab(
121 std::unique_lock lock(write_mutex_);
122 prx.getValue(config_.getWriteBuffer(),
"Config");
123 config_.commitWrite();
142 pcl::PointCloud<PointT>::Ptr input_cloud_ptr(
new pcl::PointCloud<PointT>());
143 pcl::PointCloud<PointT>::Ptr output_cloud_ptr(
new pcl::PointCloud<PointT>());
145 if (!waitForPointClouds())
147 ARMARX_INFO <<
"Timeout or error while waiting for point cloud data";
152 getPointClouds(input_cloud_ptr);
157 input_cloud_ptr->is_dense =
false;
158 pcl::removeNaNFromPointCloud(*input_cloud_ptr, *input_cloud_ptr,
indices);
159 relabelPointCloud(input_cloud_ptr);
160 ARMARX_DEBUG <<
"Point Cloud has " << input_cloud_ptr->size() <<
" Points before Downsampling";
161 auto config = config_.getUpToDateReadBuffer();
162 if (config.general.use_vertex_only_graph)
165 computeVertexOnlyGraph(input_cloud_ptr);
170 computeGraphUsingVoxelGrid(input_cloud_ptr);
176 updatePersistentGraph();
179 copyRGBLNormalToRGBL(*temp_cloud_ptr, *output_cloud_ptr);
181 config = config_.getUpToDateReadBuffer();
184 if (config.edge.use_xyz && !config.edge.use_combined)
188 std::vector<float> xyz_infl(3);
189 std::fill(xyz_infl.begin(), xyz_infl.end(), config.edge.xyz_influence);
191 new PottsCompatibility(10));
194 if (config.edge.use_normals && !config.edge.use_combined)
199 std::vector<float> normals_infl(3);
200 std::fill(normals_infl.begin(), normals_infl.end(), config.edge.normals_influence);
202 normals_infl,
new PottsCompatibility(10));
205 if (config.edge.use_curvature && !config.edge.use_combined)
209 std::vector<float> curv_infl(1);
210 std::fill(curv_infl.begin(), curv_infl.end(), config.edge.curvature_influence);
212 curv_infl,
new PottsCompatibility(10));
215 if (config.edge.use_rgb && !config.edge.use_combined)
219 std::vector<float> rgb_infl(3);
220 std::fill(rgb_infl.begin(), rgb_infl.end(), config.edge.rgb_influence);
222 new PottsCompatibility(10));
225 if (config.edge.use_time && !config.edge.use_combined)
229 std::vector<float> time_infl(1);
230 std::fill(time_infl.begin(), time_infl.end(), config.edge.time_influence);
234 if (config.edge.use_combined)
239 num_feat += config.edge.use_rgb ? 3 : 0;
240 num_feat += config.edge.use_normals ? 3 : 0;
241 num_feat += config.edge.use_xyz ? 3 : 0;
242 num_feat += config.edge.use_time ? 1 : 0;
243 num_feat += config.edge.use_curvature ? 1 : 0;
244 std::vector<float> comb_infl(num_feat);
246 for (
int i = 0; i < 3; i++)
249 if (config.edge.use_rgb)
251 comb_infl[i + j] = config.edge.rgb_influence;
254 if (config.edge.use_normals)
256 comb_infl[i + j] = config.edge.normals_influence;
259 if (config.edge.use_xyz)
261 comb_infl[i + j] = config.edge.xyz_influence;
265 if (config.edge.use_curvature)
267 comb_infl[j] = config.edge.curvature_influence;
270 if (config.edge.use_time)
272 comb_infl[j] = config.edge.time_influence;
276 config.edge.use_normals,
278 config.edge.use_curvature,
279 config.edge.use_time,
280 new PottsCompatibility(config.edge.potts_compatibilty));
290 if (config.out.provide_graph_pclouds)
294 if (config.out.provide_confidence_pclouds)
296 provideAllConfidences();
298 output_cloud_ptr->points.clear();
305 copyRGBLNormalToRGBL(*temp_cloud_ptr, *output_cloud_ptr);
307 outputGraph = retrieveGraphFromPersistentGraph(timestamp_queue_.back());
310 pcl::PointCloud<pcl::PointXYZI>::Ptr confidence_cloud_ptr(
311 new pcl::PointCloud<pcl::PointXYZI>());
312 pcl::copyPointCloud(*temp_cloud_ptr, *confidence_cloud_ptr);
313 for (
long unsigned int i = 0; i < confidence_cloud_ptr->points.size(); i++)
330 confidence_cloud_ptr->points[i].intensity = conf;
333 output_cloud_ptr->header = input_cloud_ptr->header;
334 provideResultPointClouds<decltype(output_cloud_ptr)>(output_cloud_ptr,
"CRFSegmentationResult");
335 provideResultPointClouds<decltype(confidence_cloud_ptr)>(confidence_cloud_ptr,
336 "CRFSegmentationConfidence");
341 DenseCRFSegmentationProcessor::computeGraphUsingVoxelGrid(
const PointCloudT::Ptr inputCloudPtr)
344 double r = config.general.voxel_resolution;
346 graph_builder.setInputCloud(inputCloudPtr);
348 graph_builder.compute(*current_graph_ptr_);
350 ARMARX_DEBUG <<
"Graph has " <<
static_cast<int>(boost::num_vertices(*current_graph_ptr_))
351 <<
" Vertices and " <<
static_cast<int>(boost::num_edges(*current_graph_ptr_))
353 if (config.edge.use_curvature || config.edge.use_normals)
365 DenseCRFSegmentationProcessor::computeRandomUnaryEnergy(
int num_points)
368 Eigen::MatrixXf energy(config.general.num_classes, num_points);
369 const double u_energy = -log(1.0 / config.general.num_classes);
370 const double n_energy =
371 -log((1.0 - config.general.ground_truth_prob) / (config.general.num_classes - 1));
372 const double p_energy = -log(config.general.ground_truth_prob);
373 energy.fill(u_energy);
374 std::random_device dev;
375 std::mt19937 rng(dev());
376 std::uniform_int_distribution<std::mt19937::result_type> dist(0,
377 config.general.num_classes - 1);
378 for (
int k = 0; k < num_points; k++)
384 energy.col(k).fill(n_energy);
385 energy(r, k) = p_energy;
392 DenseCRFSegmentationProcessor::generateRandomClassLabels()
396 std::random_device dev;
397 std::mt19937 rng(dev());
398 std::uniform_int_distribution<std::mt19937::result_type> dist(
400 for (boost::tie(vi, v_end) = boost::vertices(*current_graph_ptr_); vi != v_end; ++vi)
403 (*current_graph_ptr_)[*vi].label = r;
427 pcl::PointCloud<pcl::PointXYZL>::ConstPtr
428 DenseCRFSegmentationProcessor::selectRandomSeeds()
432 std::vector<Graph::vertex_descriptor> v_out;
433 boost::tie(vi, v_end) = boost::vertices(*current_graph_ptr_);
437 std::back_inserter(v_out),
439 std::mt19937{std::random_device{}()});
443 for (
auto i = v_out.begin(); i != v_out.end(); i++, j++)
445 tempCloudPtr->points[j] = (*current_graph_ptr_)[*i];
447 tempCloudPtr->points[j].label = j;
450 pcl::PointCloud<pcl::PointXYZL>::Ptr outCloudPtr(
new pcl::PointCloud<pcl::PointXYZL>());
451 pcl::copyPointCloud(*tempCloudPtr, *outCloudPtr);
490 DenseCRFSegmentationProcessor::updatePersistentGraph()
495 static_cast<double>(current_graph_ptr_->m_graph.m_point_cloud->header.stamp / 1000.0) -
497 timestamp_queue_.push_back(current_ts);
499 if (timestamp_queue_.size() > 5)
502 double tsToRemove = timestamp_queue_.front();
503 timestamp_queue_.pop_front();
504 removeTimestampFromPersistentGraph(tsToRemove);
506 addCurrentGraphToPersistentGraph();
507 ARMARX_DEBUG <<
"Root Graph consisting of " << timestamp_queue_.size() <<
" Subgraphs has "
508 <<
static_cast<int>(boost::num_vertices(*persistent_graph_ptr_)) <<
" Vertices";
513 DenseCRFSegmentationProcessor::addGraphToPersistentGraph(
Graph& graph)
519 static_cast<double>(graph.m_graph.m_point_cloud->header.stamp / 1000.0) - initial_time_;
520 for (boost::tie(vi, v_end) = boost::vertices(graph); vi != v_end; ++vi)
522 VertexWTsId new_vertex = boost::add_vertex(*persistent_graph_ptr_);
523 boost::put(tsm, new_vertex, current_ts);
525 boost::put(cm, new_vertex, -1.0);
527 (*persistent_graph_ptr_)[new_vertex] = point;
532 DenseCRFSegmentationProcessor::addCurrentGraphToPersistentGraph()
535 addGraphToPersistentGraph(*current_graph_ptr_);
539 DenseCRFSegmentationProcessor::removeGraphFromPersistentGraph(
Graph& graph)
543 static_cast<double>(graph.m_graph.m_point_cloud->header.stamp / 1000.0) - initial_time_;
544 removeTimestampFromPersistentGraph(graph_ts);
548 DenseCRFSegmentationProcessor::removeCurrentGraphFromPersistentGraph()
551 removeGraphFromPersistentGraph(*current_graph_ptr_);
555 DenseCRFSegmentationProcessor::removeTimestampFromPersistentGraph(
double ts)
559 typedef vertex_timestamp_unequal_filter<TimestampMap> FilterT;
560 FilterT filter(tsm, ts);
561 GraphWithTimestamp filtered_graph = filterAndCopyPersistentGraph<FilterT>(tsm, filter);
563 persistent_graph_ptr_.swap(temp_graph_ptr);
567 DenseCRFSegmentationProcessor::retrieveGraphFromPersistentGraph(
double ts)
571 typedef vertex_timestamp_equal_filter<TimestampMap> FilterT;
572 FilterT filter(tsm, ts);
573 GraphWithTimestamp filtered_graph = filterAndCopyPersistentGraph<FilterT>(tsm, filter);
574 return filtered_graph;
578 DenseCRFSegmentationProcessor::retrieveCurrentGraphFromPersistentGraph()
582 static_cast<double>(current_graph_ptr_->m_graph.m_point_cloud->header.stamp / 1000.0) -
584 return retrieveGraphFromPersistentGraph(current_ts);
588 DenseCRFSegmentationProcessor::provideAllGraphs()
591 for (
unsigned int i = 0; i < timestamp_queue_.size(); i++)
593 double ts = timestamp_queue_.at(i);
595 PointCloudT::Ptr output_cloud_ptr(
new PointCloudT());
601 copyRGBLNormalToRGBL(*temp_cloud_ptr, *output_cloud_ptr);
607 DenseCRFSegmentationProcessor::computeVertexOnlyGraph(PointCloudT::Ptr input_cloud_ptr)
612 pcl::PointCloud<PointT>::Ptr temp_cloud_ptr(
new pcl::PointCloud<PointT>());
613 ARMARX_DEBUG << input_cloud_ptr->size() <<
"before downsampling";
615 if (config.general.use_approximate_voxels)
618 pcl::ApproximateVoxelGrid<PointT> vg;
619 vg.setInputCloud(input_cloud_ptr);
620 vg.setLeafSize(config.general.voxel_resolution * 100,
621 config.general.voxel_resolution * 100,
622 config.general.voxel_resolution * 100);
623 vg.filter(*temp_cloud_ptr);
624 temp_cloud_ptr.swap(input_cloud_ptr);
629 pcl::VoxelGrid<PointT> vg;
630 vg.setInputCloud(input_cloud_ptr);
631 vg.setLeafSize(config.general.voxel_resolution * 100,
632 config.general.voxel_resolution * 100,
633 config.general.voxel_resolution * 100);
634 vg.filter(*temp_cloud_ptr);
635 temp_cloud_ptr.swap(input_cloud_ptr);
638 ARMARX_DEBUG << input_cloud_ptr->size() <<
"after downsampling";
641 pcl::NormalEstimation<PointT, PointWithNormalT> ne;
642 ne.setInputCloud(input_cloud_ptr);
643 pcl::search::KdTree<PointT>::Ptr tree(
new pcl::search::KdTree<PointT>());
644 ne.setSearchMethod(tree);
647 copyRGBLToRGBLNormal(*input_cloud_ptr, *cloud_normals);
649 ne.setRadiusSearch(100 * 5 * config.general.voxel_resolution);
652 ne.compute(*cloud_normals);
654 GraphPtr temp_graph_ptr = boost::make_shared<Graph>(
Graph(cloud_normals));
655 current_graph_ptr_.swap(temp_graph_ptr);
656 ARMARX_DEBUG <<
"Graph has " <<
static_cast<int>(boost::num_vertices(*current_graph_ptr_))
657 <<
" Vertices and " <<
static_cast<int>(boost::num_edges(*current_graph_ptr_))
662 DenseCRFSegmentationProcessor::copyRGBLToRGBLNormal(
PointCloudT& input_cloud,
666 output_cloud.header = input_cloud.header;
667 output_cloud.width = input_cloud.width;
668 output_cloud.height = input_cloud.height;
669 output_cloud.is_dense = input_cloud.is_dense;
670 output_cloud.sensor_orientation_ = input_cloud.sensor_orientation_;
671 output_cloud.sensor_origin_ = input_cloud.sensor_origin_;
672 output_cloud.points.resize(input_cloud.points.size());
674 if (input_cloud.points.size() == 0)
680 for (
size_t i = 0; i < output_cloud.size(); i++)
682 output_cloud.points[i].x = input_cloud.points[i].x;
683 output_cloud.points[i].y = input_cloud.points[i].y;
684 output_cloud.points[i].z = input_cloud.points[i].z;
685 output_cloud.points[i].r = input_cloud.points[i].r;
686 output_cloud.points[i].g = input_cloud.points[i].g;
687 output_cloud.points[i].b = input_cloud.points[i].b;
688 output_cloud.points[i].a = uint8_t(255);
689 output_cloud.points[i].label = input_cloud.points[i].label;
690 output_cloud.points[i].normal_x = 0;
691 output_cloud.points[i].normal_y = 0;
692 output_cloud.points[i].normal_z = 0;
693 output_cloud.points[i].curvature = 0;
702 output_cloud.header = input_cloud.header;
703 output_cloud.width = input_cloud.width;
704 output_cloud.height = input_cloud.height;
705 output_cloud.is_dense = input_cloud.is_dense;
706 output_cloud.sensor_orientation_ = input_cloud.sensor_orientation_;
707 output_cloud.sensor_origin_ = input_cloud.sensor_origin_;
708 output_cloud.points.resize(input_cloud.points.size());
710 if (input_cloud.points.size() == 0)
715 for (
size_t i = 0; i < output_cloud.size(); i++)
717 output_cloud.points[i].x = input_cloud.points[i].x;
718 output_cloud.points[i].y = input_cloud.points[i].y;
719 output_cloud.points[i].z = input_cloud.points[i].z;
720 output_cloud.points[i].r = input_cloud.points[i].r;
721 output_cloud.points[i].g = input_cloud.points[i].g;
722 output_cloud.points[i].b = input_cloud.points[i].b;
723 output_cloud.points[i].a = uint8_t(255);
724 output_cloud.points[i].label = input_cloud.points[i].label;
729 DenseCRFSegmentationProcessor::relabelPointCloud(pcl::PointCloud<PointT>::Ptr input_cloud_ptr)
732 std::map<uint32_t, uint32_t> labelmap;
733 uint32_t highest_new_label = 1;
734 for (
auto& point : input_cloud_ptr->points)
736 if (labelmap.find(point.label) != labelmap.end())
738 point.label = labelmap.at(point.label);
742 labelmap.insert(std::make_pair(point.label, highest_new_label));
743 point.label = highest_new_label;
750 DenseCRFSegmentationProcessor::provideAllConfidences()
755 for (
unsigned int i = 0; i < timestamp_queue_.size(); i++)
757 double ts = timestamp_queue_.at(i);
767 PointCloudT::Ptr output_cloud_ptr(
new PointCloudT());
768 copyRGBLNormalToRGBL(*temp_cloud_ptr, *output_cloud_ptr);
769 for (
long unsigned int j = 0; j < output_cloud_ptr->points.size(); j++)
773 output_cloud_ptr->points[j].
r =
c.r * 255.0;
774 output_cloud_ptr->points[j].g =
c.g * 255.0;
775 output_cloud_ptr->points[j].b =
c.b * 255.0;
777 provideResultPointClouds<decltype(output_cloud_ptr)>(output_cloud_ptr,
782 pcl::PointCloud<pcl::PointXYZI>::Ptr confidence_cloud_ptr(
783 new pcl::PointCloud<pcl::PointXYZI>());
784 pcl::copyPointCloud(*temp_cloud_ptr, *confidence_cloud_ptr);
785 for (
long unsigned int j = 0; j < confidence_cloud_ptr->points.size(); j++)
788 confidence_cloud_ptr->points[j].intensity = conf;
790 provideResultPointClouds<decltype(confidence_cloud_ptr)>(
800 Vector5f vec{config.xyz_influence,
801 config.rgb_influence,
802 config.normals_influence,
803 config.curvature_influence,
804 config.time_influence};
814 const Ice::Current& current)
817 std::unique_lock lock(write_mutex_);
819 config.xyz_influence = xyz;
820 config.rgb_influence = rgb;
821 config.normals_influence = normals;
822 config.curvature_influence = curvature;
823 config.time_influence = time;