38 #ifndef PCL_SEGMENTATION_IMPL_CPC_SEGMENTATION_HPP_
39 #define PCL_SEGMENTATION_IMPL_CPC_SEGMENTATION_HPP_
41 #include <pcl/sample_consensus/sac_model_plane.h>
42 #include <pcl/segmentation/cpc_segmentation.h>
44 template <
typename Po
intT>
47 template <
typename Po
intT>
50 template <
typename Po
intT>
void
57 calculateConvexConnections (sv_adjacency_list_);
60 applyKconvexity (k_factor_);
65 grouping_data_valid_ =
true;
67 applyCuttingPlane (max_cuts_);
70 mergeSmallSegments ();
73 PCL_WARN (
"[pcl::CPCSegmentation::segment] WARNING: Call function setInputSupervoxels first. Nothing has been done. \n");
76 template <
typename Po
intT>
void
79 using SegLabel2ClusterMap = std::map<std::uint32_t, pcl::PointCloud<WeightSACPointType>::Ptr>;
83 if (depth_levels_left <= 0)
87 SegLabel2ClusterMap seg_to_edge_points_map;
88 std::map<std::uint32_t, std::vector<EdgeID> > seg_to_edgeIDs_map;
89 EdgeIterator edge_itr, edge_itr_end, next_edge;
90 boost::tie (edge_itr, edge_itr_end) = boost::edges (sv_adjacency_list_);
91 for (next_edge = edge_itr; edge_itr != edge_itr_end; edge_itr = next_edge)
94 std::uint32_t source_sv_label = sv_adjacency_list_[boost::source (*edge_itr, sv_adjacency_list_)];
95 std::uint32_t target_sv_label = sv_adjacency_list_[boost::target (*edge_itr, sv_adjacency_list_)];
97 std::uint32_t source_segment_label = sv_label_to_seg_label_map_[source_sv_label];
98 std::uint32_t target_segment_label = sv_label_to_seg_label_map_[target_sv_label];
101 if (source_segment_label != target_segment_label)
105 if (sv_adjacency_list_[*edge_itr].used_for_cutting)
108 const pcl::PointXYZRGBA source_centroid = sv_label_to_supervoxel_map_[source_sv_label]->centroid_;
109 const pcl::PointXYZRGBA target_centroid = sv_label_to_supervoxel_map_[target_sv_label]->centroid_;
114 WeightSACPointType edge_centroid;
115 edge_centroid.getVector3fMap () = (source_centroid.getVector3fMap () + target_centroid.getVector3fMap ()) / 2;
118 edge_centroid.getNormalVector3fMap () = (target_centroid.getVector3fMap () - source_centroid.getVector3fMap ()).normalized ();
121 edge_centroid.intensity = sv_adjacency_list_[*edge_itr].is_convex ? -sv_adjacency_list_[*edge_itr].normal_difference : sv_adjacency_list_[*edge_itr].normal_difference;
122 if (seg_to_edge_points_map.find (source_segment_label) == seg_to_edge_points_map.end ())
126 seg_to_edge_points_map[source_segment_label]->push_back (edge_centroid);
127 seg_to_edgeIDs_map[source_segment_label].push_back (*edge_itr);
129 bool cut_found =
false;
131 for (
const auto &seg_to_edge_points : seg_to_edge_points_map)
134 if (seg_to_edge_points.second->size () < min_segment_size_for_cutting_)
139 std::vector<double> weights;
140 weights.resize (seg_to_edge_points.second->size ());
141 for (std::size_t cp = 0;
cp < seg_to_edge_points.second->size (); ++
cp)
143 float& cur_weight = (*seg_to_edge_points.second)[cp].intensity;
144 cur_weight = cur_weight < concavity_tolerance_threshold_ ? 0 : 1;
145 weights[
cp] = cur_weight;
151 WeightedRandomSampleConsensus weight_sac (model_p, seed_resolution_,
true);
153 weight_sac.setWeights (weights, use_directed_weights_);
154 weight_sac.setMaxIterations (ransac_itrs_);
157 if (!weight_sac.computeModel ())
162 Eigen::VectorXf model_coefficients;
163 weight_sac.getModelCoefficients (model_coefficients);
165 model_coefficients[3] += std::numeric_limits<float>::epsilon ();
167 weight_sac.getInliers (*support_indices);
172 if (use_local_constrains_)
174 Eigen::Vector3f plane_normal (model_coefficients[0], model_coefficients[1], model_coefficients[2]);
178 std::vector<pcl::PointIndices> cluster_indices;
181 tree->setInputCloud (edge_cloud_cluster);
187 euclidean_clusterer.
setIndices (support_indices);
188 euclidean_clusterer.
extract (cluster_indices);
191 for (
const auto &cluster_index : cluster_indices)
194 float cluster_score = 0;
196 for (
const auto ¤t_index : cluster_index.indices)
198 double index_score = weights[current_index];
199 if (use_directed_weights_)
200 index_score *= 1.414 * (std::abs (plane_normal.dot (edge_cloud_cluster->
at (current_index).getNormalVector3fMap ())));
201 cluster_score += index_score;
204 cluster_score /= cluster_index.indices.size ();
206 if (cluster_score >= min_cut_score_)
208 cut_support_indices.insert (cut_support_indices.end (), cluster_index.indices.begin (), cluster_index.indices.end ());
211 if (cut_support_indices.empty ())
219 double current_score = weight_sac.getBestScore ();
220 cut_support_indices = *support_indices;
222 if (current_score < min_cut_score_)
229 int number_connections_cut = 0;
230 for (
const auto &point_index : cut_support_indices)
232 if (use_clean_cutting_)
235 std::uint32_t source_sv_label = sv_adjacency_list_[boost::source (seg_to_edgeIDs_map[seg_to_edge_points.first][point_index], sv_adjacency_list_)];
236 std::uint32_t target_sv_label = sv_adjacency_list_[boost::target (seg_to_edgeIDs_map[seg_to_edge_points.first][point_index], sv_adjacency_list_)];
238 const pcl::PointXYZRGBA source_centroid = sv_label_to_supervoxel_map_[source_sv_label]->centroid_;
239 const pcl::PointXYZRGBA target_centroid = sv_label_to_supervoxel_map_[target_sv_label]->centroid_;
246 sv_adjacency_list_[seg_to_edgeIDs_map[seg_to_edge_points.first][point_index]].used_for_cutting =
true;
247 if (sv_adjacency_list_[seg_to_edgeIDs_map[seg_to_edge_points.first][point_index]].is_valid)
249 ++number_connections_cut;
250 sv_adjacency_list_[seg_to_edgeIDs_map[seg_to_edge_points.first][point_index]].is_valid =
false;
254 if (number_connections_cut > 0)
263 applyCuttingPlane (depth_levels_left);
272 template <
typename Po
intT>
bool
276 if (threshold_ == std::numeric_limits<double>::max ())
278 PCL_ERROR (
"[pcl::CPCSegmentation<PointT>::WeightedRandomSampleConsensus::computeModel] No threshold set!\n");
283 best_score_ = -std::numeric_limits<double>::max ();
286 Eigen::VectorXf model_coefficients;
288 unsigned skipped_count = 0;
290 const unsigned max_skip = max_iterations_ * 10;
293 while (iterations_ < max_iterations_ && skipped_count < max_skip)
296 sac_model_->setIndices (model_pt_indices_);
297 sac_model_->getSamples (iterations_, selection);
299 if (selection.empty ())
301 PCL_ERROR (
"[pcl::CPCSegmentation<PointT>::WeightedRandomSampleConsensus::computeModel] No samples could be selected!\n");
306 if (!sac_model_->computeModelCoefficients (selection, model_coefficients))
313 sac_model_->setIndices (full_cloud_pt_indices_);
316 sac_model_->selectWithinDistance (model_coefficients, threshold_, *current_inliers);
317 double current_score = 0;
318 Eigen::Vector3f plane_normal (model_coefficients[0], model_coefficients[1], model_coefficients[2]);
319 for (
const auto ¤t_index : *current_inliers)
321 double index_score = weights_[current_index];
322 if (use_directed_weights_)
324 index_score *= 1.414 * (std::abs (plane_normal.dot (point_cloud_ptr_->at (current_index).getNormalVector3fMap ())));
326 current_score += index_score;
329 current_score /= current_inliers->size ();
332 if (current_score > best_score_)
334 best_score_ = current_score;
337 model_coefficients_ = model_coefficients;
341 PCL_DEBUG (
"[pcl::CPCSegmentation<PointT>::WeightedRandomSampleConsensus::computeModel] Trial %d (max %d): score is %f (best is: %f so far).\n", iterations_, max_iterations_, current_score, best_score_);
342 if (iterations_ > max_iterations_)
344 PCL_DEBUG (
"[pcl::CPCSegmentation<PointT>::WeightedRandomSampleConsensus::computeModel] RANSAC reached the maximum number of trials.\n");
349 PCL_DEBUG (
"[pcl::CPCSegmentation<PointT>::WeightedRandomSampleConsensus::computeModel] Model: %lu size, %f score.\n", model_.size (), best_score_);
358 sac_model_->selectWithinDistance (model_coefficients_, threshold_, inliers_);
A segmentation algorithm partitioning a supervoxel graph.
void segment()
Merge supervoxels using cuts through local convexities.
~CPCSegmentation() override
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
virtual void setIndices(const IndicesPtr &indices)
Provide a pointer to the vector of indices that represents the input data.
PointCloud represents the base class in PCL for storing collections of 3D points.
const PointT & at(int column, int row) const
Obtain the point given by the (column, row) coordinates.
shared_ptr< PointCloud< PointT > > Ptr
SampleConsensusModelPlane defines a model for 3D plane segmentation.
shared_ptr< SampleConsensusModelPlane< PointT > > Ptr
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
shared_ptr< KdTree< PointT, Tree > > Ptr
double pointToPlaneDistanceSigned(const Point &p, double a, double b, double c, double d)
Get the distance from a point to a plane (signed) defined by ax+by+cz+d=0.
PCL_EXPORTS void print_info(const char *format,...)
Print an info message on stream with colors.
int cp(int from, int to)
Returns field copy operation code.
IndicesAllocator<> Indices
Type used for indices in PCL.
shared_ptr< Indices > IndicesPtr
A point structure representing Euclidean xyz coordinates, and the RGBA color.