Point Cloud Library (PCL)  1.11.0
min_cut_segmentation.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the copyright holder(s) nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * $Id:$
36  *
37  */
38 
39 #ifndef PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
40 #define PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
41 
42 #include <pcl/segmentation/boost.h>
43 #include <pcl/segmentation/min_cut_segmentation.h>
44 #include <pcl/search/search.h>
45 #include <pcl/search/kdtree.h>
46 #include <cstdlib>
47 #include <cmath>
48 
49 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50 template <typename PointT>
52  inverse_sigma_ (16.0),
53  binary_potentials_are_valid_ (false),
54  epsilon_ (0.0001),
55  radius_ (16.0),
56  unary_potentials_are_valid_ (false),
57  source_weight_ (0.8),
58  search_ (),
59  number_of_neighbours_ (14),
60  graph_is_valid_ (false),
61  foreground_points_ (0),
62  background_points_ (0),
63  clusters_ (0),
64  vertices_ (0),
65  edge_marker_ (0),
66  source_ (),/////////////////////////////////
67  sink_ (),///////////////////////////////////
68  max_flow_ (0.0)
69 {
70 }
71 
72 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 template <typename PointT>
75 {
76  foreground_points_.clear ();
77  background_points_.clear ();
78  clusters_.clear ();
79  vertices_.clear ();
80  edge_marker_.clear ();
81 }
82 
83 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 template <typename PointT> void
86 {
87  input_ = cloud;
88  graph_is_valid_ = false;
89  unary_potentials_are_valid_ = false;
90  binary_potentials_are_valid_ = false;
91 }
92 
93 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94 template <typename PointT> double
96 {
97  return (pow (1.0 / inverse_sigma_, 0.5));
98 }
99 
100 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 template <typename PointT> void
103 {
104  if (sigma > epsilon_)
105  {
106  inverse_sigma_ = 1.0 / (sigma * sigma);
107  binary_potentials_are_valid_ = false;
108  }
109 }
110 
111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 template <typename PointT> double
114 {
115  return (pow (radius_, 0.5));
116 }
117 
118 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 template <typename PointT> void
121 {
122  if (radius > epsilon_)
123  {
124  radius_ = radius * radius;
125  unary_potentials_are_valid_ = false;
126  }
127 }
128 
129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130 template <typename PointT> double
132 {
133  return (source_weight_);
134 }
135 
136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
137 template <typename PointT> void
139 {
140  if (weight > epsilon_)
141  {
142  source_weight_ = weight;
143  unary_potentials_are_valid_ = false;
144  }
145 }
146 
147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
148 template <typename PointT> typename pcl::MinCutSegmentation<PointT>::KdTreePtr
150 {
151  return (search_);
152 }
153 
154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155 template <typename PointT> void
157 {
158  search_ = tree;
159 }
160 
161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162 template <typename PointT> unsigned int
164 {
165  return (number_of_neighbours_);
166 }
167 
168 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 template <typename PointT> void
171 {
172  if (number_of_neighbours_ != neighbour_number && neighbour_number != 0)
173  {
174  number_of_neighbours_ = neighbour_number;
175  graph_is_valid_ = false;
176  unary_potentials_are_valid_ = false;
177  binary_potentials_are_valid_ = false;
178  }
179 }
180 
181 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182 template <typename PointT> std::vector<PointT, Eigen::aligned_allocator<PointT> >
184 {
185  return (foreground_points_);
186 }
187 
188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189 template <typename PointT> void
191 {
192  foreground_points_.clear ();
193  foreground_points_.reserve (foreground_points->points.size ());
194  for (std::size_t i_point = 0; i_point < foreground_points->points.size (); i_point++)
195  foreground_points_.push_back (foreground_points->points[i_point]);
196 
197  unary_potentials_are_valid_ = false;
198 }
199 
200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
201 template <typename PointT> std::vector<PointT, Eigen::aligned_allocator<PointT> >
203 {
204  return (background_points_);
205 }
206 
207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208 template <typename PointT> void
210 {
211  background_points_.clear ();
212  background_points_.reserve (background_points->points.size ());
213  for (std::size_t i_point = 0; i_point < background_points->points.size (); i_point++)
214  background_points_.push_back (background_points->points[i_point]);
215 
216  unary_potentials_are_valid_ = false;
217 }
218 
219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220 template <typename PointT> void
221 pcl::MinCutSegmentation<PointT>::extract (std::vector <pcl::PointIndices>& clusters)
222 {
223  clusters.clear ();
224 
225  bool segmentation_is_possible = initCompute ();
226  if ( !segmentation_is_possible )
227  {
228  deinitCompute ();
229  return;
230  }
231 
232  if ( graph_is_valid_ && unary_potentials_are_valid_ && binary_potentials_are_valid_ )
233  {
234  clusters.reserve (clusters_.size ());
235  std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
236  deinitCompute ();
237  return;
238  }
239 
240  clusters_.clear ();
241 
242  if ( !graph_is_valid_ )
243  {
244  bool success = buildGraph ();
245  if (!success)
246  {
247  deinitCompute ();
248  return;
249  }
250  graph_is_valid_ = true;
251  unary_potentials_are_valid_ = true;
252  binary_potentials_are_valid_ = true;
253  }
254 
255  if ( !unary_potentials_are_valid_ )
256  {
257  bool success = recalculateUnaryPotentials ();
258  if (!success)
259  {
260  deinitCompute ();
261  return;
262  }
263  unary_potentials_are_valid_ = true;
264  }
265 
266  if ( !binary_potentials_are_valid_ )
267  {
268  bool success = recalculateBinaryPotentials ();
269  if (!success)
270  {
271  deinitCompute ();
272  return;
273  }
274  binary_potentials_are_valid_ = true;
275  }
276 
277  //IndexMap index_map = boost::get (boost::vertex_index, *graph_);
278  ResidualCapacityMap residual_capacity = boost::get (boost::edge_residual_capacity, *graph_);
279 
280  max_flow_ = boost::boykov_kolmogorov_max_flow (*graph_, source_, sink_);
281 
282  assembleLabels (residual_capacity);
283 
284  clusters.reserve (clusters_.size ());
285  std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
286 
287  deinitCompute ();
288 }
289 
290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
291 template <typename PointT> double
293 {
294  return (max_flow_);
295 }
296 
297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
298 template <typename PointT> typename pcl::MinCutSegmentation<PointT>::mGraphPtr
300 {
301  return (graph_);
302 }
303 
304 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
305 template <typename PointT> bool
307 {
308  int number_of_points = static_cast<int> (input_->points.size ());
309  int number_of_indices = static_cast<int> (indices_->size ());
310 
311  if (input_->points.empty () || number_of_points == 0 || foreground_points_.empty () == true )
312  return (false);
313 
314  if (!search_)
315  search_.reset (new pcl::search::KdTree<PointT>);
316 
317  graph_.reset (new mGraph);
318 
319  capacity_.reset (new CapacityMap);
320  *capacity_ = boost::get (boost::edge_capacity, *graph_);
321 
322  reverse_edges_.reset (new ReverseEdgeMap);
323  *reverse_edges_ = boost::get (boost::edge_reverse, *graph_);
324 
325  VertexDescriptor vertex_descriptor(0);
326  vertices_.clear ();
327  vertices_.resize (number_of_points + 2, vertex_descriptor);
328 
329  std::set<int> out_edges_marker;
330  edge_marker_.clear ();
331  edge_marker_.resize (number_of_points + 2, out_edges_marker);
332 
333  for (int i_point = 0; i_point < number_of_points + 2; i_point++)
334  vertices_[i_point] = boost::add_vertex (*graph_);
335 
336  source_ = vertices_[number_of_points];
337  sink_ = vertices_[number_of_points + 1];
338 
339  for (int i_point = 0; i_point < number_of_indices; i_point++)
340  {
341  index_t point_index = (*indices_)[i_point];
342  double source_weight = 0.0;
343  double sink_weight = 0.0;
344  calculateUnaryPotential (point_index, source_weight, sink_weight);
345  addEdge (static_cast<int> (source_), point_index, source_weight);
346  addEdge (point_index, static_cast<int> (sink_), sink_weight);
347  }
348 
349  std::vector<int> neighbours;
350  std::vector<float> distances;
351  search_->setInputCloud (input_, indices_);
352  for (int i_point = 0; i_point < number_of_indices; i_point++)
353  {
354  index_t point_index = (*indices_)[i_point];
355  search_->nearestKSearch (i_point, number_of_neighbours_, neighbours, distances);
356  for (std::size_t i_nghbr = 1; i_nghbr < neighbours.size (); i_nghbr++)
357  {
358  double weight = calculateBinaryPotential (point_index, neighbours[i_nghbr]);
359  addEdge (point_index, neighbours[i_nghbr], weight);
360  addEdge (neighbours[i_nghbr], point_index, weight);
361  }
362  neighbours.clear ();
363  distances.clear ();
364  }
365 
366  return (true);
367 }
368 
369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370 template <typename PointT> void
371 pcl::MinCutSegmentation<PointT>::calculateUnaryPotential (int point, double& source_weight, double& sink_weight) const
372 {
373  double min_dist_to_foreground = std::numeric_limits<double>::max ();
374  //double min_dist_to_background = std::numeric_limits<double>::max ();
375  //double closest_background_point[] = {0.0, 0.0};
376  double initial_point[] = {0.0, 0.0};
377 
378  initial_point[0] = input_->points[point].x;
379  initial_point[1] = input_->points[point].y;
380 
381  for (std::size_t i_point = 0; i_point < foreground_points_.size (); i_point++)
382  {
383  double dist = 0.0;
384  dist += (foreground_points_[i_point].x - initial_point[0]) * (foreground_points_[i_point].x - initial_point[0]);
385  dist += (foreground_points_[i_point].y - initial_point[1]) * (foreground_points_[i_point].y - initial_point[1]);
386  if (min_dist_to_foreground > dist)
387  {
388  min_dist_to_foreground = dist;
389  }
390  }
391 
392  sink_weight = pow (min_dist_to_foreground / radius_, 0.5);
393 
394  source_weight = source_weight_;
395  return;
396 /*
397  if (background_points_.size () == 0)
398  return;
399 
400  for (int i_point = 0; i_point < background_points_.size (); i_point++)
401  {
402  double dist = 0.0;
403  dist += (background_points_[i_point].x - initial_point[0]) * (background_points_[i_point].x - initial_point[0]);
404  dist += (background_points_[i_point].y - initial_point[1]) * (background_points_[i_point].y - initial_point[1]);
405  if (min_dist_to_background > dist)
406  {
407  min_dist_to_background = dist;
408  closest_background_point[0] = background_points_[i_point].x;
409  closest_background_point[1] = background_points_[i_point].y;
410  }
411  }
412 
413  if (min_dist_to_background <= epsilon_)
414  {
415  source_weight = 0.0;
416  sink_weight = 1.0;
417  return;
418  }
419 
420  source_weight = 1.0 / (1.0 + pow (min_dist_to_background / min_dist_to_foreground, 0.5));
421  sink_weight = 1 - source_weight;
422 */
423 }
424 
425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
426 template <typename PointT> bool
427 pcl::MinCutSegmentation<PointT>::addEdge (int source, int target, double weight)
428 {
429  std::set<int>::iterator iter_out = edge_marker_[source].find (target);
430  if ( iter_out != edge_marker_[source].end () )
431  return (false);
432 
433  EdgeDescriptor edge;
434  EdgeDescriptor reverse_edge;
435  bool edge_was_added, reverse_edge_was_added;
436 
437  boost::tie (edge, edge_was_added) = boost::add_edge ( vertices_[source], vertices_[target], *graph_ );
438  boost::tie (reverse_edge, reverse_edge_was_added) = boost::add_edge ( vertices_[target], vertices_[source], *graph_ );
439  if ( !edge_was_added || !reverse_edge_was_added )
440  return (false);
441 
442  (*capacity_)[edge] = weight;
443  (*capacity_)[reverse_edge] = 0.0;
444  (*reverse_edges_)[edge] = reverse_edge;
445  (*reverse_edges_)[reverse_edge] = edge;
446  edge_marker_[source].insert (target);
447 
448  return (true);
449 }
450 
451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
452 template <typename PointT> double
454 {
455  double weight = 0.0;
456  double distance = 0.0;
457  distance += (input_->points[source].x - input_->points[target].x) * (input_->points[source].x - input_->points[target].x);
458  distance += (input_->points[source].y - input_->points[target].y) * (input_->points[source].y - input_->points[target].y);
459  distance += (input_->points[source].z - input_->points[target].z) * (input_->points[source].z - input_->points[target].z);
460  distance *= inverse_sigma_;
461  weight = std::exp (-distance);
462 
463  return (weight);
464 }
465 
466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
467 template <typename PointT> bool
469 {
470  OutEdgeIterator src_edge_iter;
471  OutEdgeIterator src_edge_end;
472  std::pair<EdgeDescriptor, bool> sink_edge;
473 
474  for (boost::tie (src_edge_iter, src_edge_end) = boost::out_edges (source_, *graph_); src_edge_iter != src_edge_end; src_edge_iter++)
475  {
476  double source_weight = 0.0;
477  double sink_weight = 0.0;
478  sink_edge.second = false;
479  calculateUnaryPotential (static_cast<int> (boost::target (*src_edge_iter, *graph_)), source_weight, sink_weight);
480  sink_edge = boost::lookup_edge (boost::target (*src_edge_iter, *graph_), sink_, *graph_);
481  if (!sink_edge.second)
482  return (false);
483 
484  (*capacity_)[*src_edge_iter] = source_weight;
485  (*capacity_)[sink_edge.first] = sink_weight;
486  }
487 
488  return (true);
489 }
490 
491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
492 template <typename PointT> bool
494 {
495  int number_of_points = static_cast<int> (indices_->size ());
496 
497  VertexIterator vertex_iter;
498  VertexIterator vertex_end;
499  OutEdgeIterator edge_iter;
500  OutEdgeIterator edge_end;
501 
502  std::vector< std::set<VertexDescriptor> > edge_marker;
503  std::set<VertexDescriptor> out_edges_marker;
504  edge_marker.clear ();
505  edge_marker.resize (number_of_points + 2, out_edges_marker);
506 
507  for (boost::tie (vertex_iter, vertex_end) = boost::vertices (*graph_); vertex_iter != vertex_end; vertex_iter++)
508  {
509  VertexDescriptor source_vertex = *vertex_iter;
510  if (source_vertex == source_ || source_vertex == sink_)
511  continue;
512  for (boost::tie (edge_iter, edge_end) = boost::out_edges (source_vertex, *graph_); edge_iter != edge_end; edge_iter++)
513  {
514  //If this is not the edge of the graph, but the reverse fictitious edge that is needed for the algorithm then continue
515  EdgeDescriptor reverse_edge = (*reverse_edges_)[*edge_iter];
516  if ((*capacity_)[reverse_edge] != 0.0)
517  continue;
518 
519  //If we already changed weight for this edge then continue
520  VertexDescriptor target_vertex = boost::target (*edge_iter, *graph_);
521  std::set<VertexDescriptor>::iterator iter_out = edge_marker[static_cast<int> (source_vertex)].find (target_vertex);
522  if ( iter_out != edge_marker[static_cast<int> (source_vertex)].end () )
523  continue;
524 
525  if (target_vertex != source_ && target_vertex != sink_)
526  {
527  //Change weight and remember that this edges were updated
528  double weight = calculateBinaryPotential (static_cast<int> (target_vertex), static_cast<int> (source_vertex));
529  (*capacity_)[*edge_iter] = weight;
530  edge_marker[static_cast<int> (source_vertex)].insert (target_vertex);
531  }
532  }
533  }
534 
535  return (true);
536 }
537 
538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
539 template <typename PointT> void
541 {
542  std::vector<int> labels;
543  labels.resize (input_->points.size (), 0);
544  int number_of_indices = static_cast<int> (indices_->size ());
545  for (int i_point = 0; i_point < number_of_indices; i_point++)
546  labels[(*indices_)[i_point]] = 1;
547 
548  clusters_.clear ();
549 
550  pcl::PointIndices segment;
551  clusters_.resize (2, segment);
552 
553  OutEdgeIterator edge_iter, edge_end;
554  for ( boost::tie (edge_iter, edge_end) = boost::out_edges (source_, *graph_); edge_iter != edge_end; edge_iter++ )
555  {
556  if (labels[edge_iter->m_target] == 1)
557  {
558  if (residual_capacity[*edge_iter] > epsilon_)
559  clusters_[1].indices.push_back (static_cast<int> (edge_iter->m_target));
560  else
561  clusters_[0].indices.push_back (static_cast<int> (edge_iter->m_target));
562  }
563  }
564 }
565 
566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
567 template <typename PointT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
569 {
571 
572  if (!clusters_.empty ())
573  {
574  int num_of_pts_in_first_cluster = static_cast<int> (clusters_[0].indices.size ());
575  int num_of_pts_in_second_cluster = static_cast<int> (clusters_[1].indices.size ());
576  int number_of_points = num_of_pts_in_first_cluster + num_of_pts_in_second_cluster;
577  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
578  unsigned char foreground_color[3] = {255, 255, 255};
579  unsigned char background_color[3] = {255, 0, 0};
580  colored_cloud->width = number_of_points;
581  colored_cloud->height = 1;
582  colored_cloud->is_dense = input_->is_dense;
583 
584  pcl::PointXYZRGB point;
585  for (int i_point = 0; i_point < num_of_pts_in_first_cluster; i_point++)
586  {
587  index_t point_index = clusters_[0].indices[i_point];
588  point.x = *(input_->points[point_index].data);
589  point.y = *(input_->points[point_index].data + 1);
590  point.z = *(input_->points[point_index].data + 2);
591  point.r = background_color[0];
592  point.g = background_color[1];
593  point.b = background_color[2];
594  colored_cloud->points.push_back (point);
595  }
596 
597  for (int i_point = 0; i_point < num_of_pts_in_second_cluster; i_point++)
598  {
599  index_t point_index = clusters_[1].indices[i_point];
600  point.x = *(input_->points[point_index].data);
601  point.y = *(input_->points[point_index].data + 1);
602  point.z = *(input_->points[point_index].data + 2);
603  point.r = foreground_color[0];
604  point.g = foreground_color[1];
605  point.b = foreground_color[2];
606  colored_cloud->points.push_back (point);
607  }
608  }
609 
610  return (colored_cloud);
611 }
612 
613 #define PCL_INSTANTIATE_MinCutSegmentation(T) template class pcl::MinCutSegmentation<T>;
614 
615 #endif // PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
KdTreePtr getSearchMethod() const
Returns search method that is used for finding KNN.
typename KdTree::Ptr KdTreePtr
std::vector< PointT, Eigen::aligned_allocator< PointT > > getBackgroundPoints() const
Returns the points that must belong to background.
shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:428
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
void setBackgroundPoints(typename pcl::PointCloud< PointT >::Ptr background_points)
Allows to specify points which are known to be the points of the background.
boost::graph_traits< mGraph >::out_edge_iterator OutEdgeIterator
double getMaxFlow() const
Returns that flow value that was calculated during the segmentation.
~MinCutSegmentation()
Destructor that frees memory.
boost::property_map< mGraph, boost::edge_capacity_t >::type CapacityMap
bool recalculateBinaryPotentials()
This method recalculates binary potentials(smooth cost) if some changes were made, instead of creating new graph.
void setForegroundPoints(typename pcl::PointCloud< PointT >::Ptr foreground_points)
Allows to specify points which are known to be the points of the object.
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
Definition: types.h:136
unsigned int getNumberOfNeighbours() const
Returns the number of neighbours to find.
void setRadius(double radius)
Allows to set the radius to the background.
mGraphPtr getGraph() const
Returns the graph that was build for finding the minimum cut.
boost::graph_traits< mGraph >::edge_descriptor EdgeDescriptor
Traits::vertex_descriptor VertexDescriptor
void setInputCloud(const PointCloudConstPtr &cloud) override
This method simply sets the input point cloud.
double calculateBinaryPotential(int source, int target) const
Returns the binary potential(smooth cost) for the given indices of points.
shared_ptr< mGraph > mGraphPtr
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
bool recalculateUnaryPotentials()
This method recalculates unary potentials(data cost) if some changes were made, instead of creating n...
double getSourceWeight() const
Returns weight that every edge from the source point has.
std::vector< PointT, Eigen::aligned_allocator< PointT > > getForegroundPoints() const
Returns the points that must belong to foreground.
void assembleLabels(ResidualCapacityMap &residual_capacity)
This method analyzes the residual network and assigns a label to every point in the cloud...
void calculateUnaryPotential(int point, double &source_weight, double &sink_weight) const
Returns unary potential(data cost) for the given point index.
void setSourceWeight(double weight)
Allows to set weight for source edges.
void setSearchMethod(const KdTreePtr &tree)
Allows to set search method for finding KNN.
double getRadius() const
Returns radius to the background.
boost::property_map< mGraph, boost::edge_reverse_t >::type ReverseEdgeMap
void setSigma(double sigma)
Allows to set the normalization value for the binary potentials as described in the article...
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415
boost::property_map< mGraph, boost::edge_residual_capacity_t >::type ResidualCapacityMap
bool addEdge(int source, int target, double weight)
This method simply adds the edge from the source point to the target point with a given weight...
bool buildGraph()
This method simply builds the graph that will be used during the segmentation.
double getSigma() const
Returns normalization value for binary potentials.
MinCutSegmentation()
Constructor that sets default values for member variables.
pcl::PointCloud< pcl::PointXYZRGB >::Ptr getColoredCloud()
Returns the colored cloud.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields)...
Definition: point_cloud.h:418
boost::graph_traits< mGraph >::vertex_iterator VertexIterator
void setNumberOfNeighbours(unsigned int neighbour_number)
Allows to set the number of neighbours to find.
void extract(std::vector< pcl::PointIndices > &clusters)
This method launches the segmentation algorithm and returns the clusters that were obtained during th...
A point structure representing Euclidean xyz coordinates, and the RGB color.
boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, boost::property< boost::vertex_name_t, std::string, boost::property< boost::vertex_index_t, long, boost::property< boost::vertex_color_t, boost::default_color_type, boost::property< boost::vertex_distance_t, long, boost::property< boost::vertex_predecessor_t, Traits::edge_descriptor > > > > >, boost::property< boost::edge_capacity_t, double, boost::property< boost::edge_residual_capacity_t, double, boost::property< boost::edge_reverse_t, Traits::edge_descriptor > > > > mGraph
typename PointCloud::ConstPtr PointCloudConstPtr
Definition: pcl_base.h:74