Point Cloud Library (PCL)  1.9.1-dev
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;
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);
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;
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;
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;
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 (size_t i_point = 0; i_point < foreground_points->points.size (); i_point++)
195  foreground_points_.push_back (foreground_points->points[i_point]);
196 
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 (size_t i_point = 0; i_point < background_points->points.size (); i_point++)
214  background_points_.push_back (background_points->points[i_point]);
215 
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 
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  bool success = true;
242 
243  if ( !graph_is_valid_ )
244  {
245  success = buildGraph ();
246  if (!success)
247  {
248  deinitCompute ();
249  return;
250  }
251  graph_is_valid_ = true;
254  }
255 
257  {
258  success = recalculateUnaryPotentials ();
259  if (!success)
260  {
261  deinitCompute ();
262  return;
263  }
265  }
266 
268  {
269  success = recalculateBinaryPotentials ();
270  if (!success)
271  {
272  deinitCompute ();
273  return;
274  }
276  }
277 
278  //IndexMap index_map = boost::get (boost::vertex_index, *graph_);
279  ResidualCapacityMap residual_capacity = boost::get (boost::edge_residual_capacity, *graph_);
280 
281  max_flow_ = boost::boykov_kolmogorov_max_flow (*graph_, source_, sink_);
282 
283  assembleLabels (residual_capacity);
284 
285  clusters.reserve (clusters_.size ());
286  std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
287 
288  deinitCompute ();
289 }
290 
291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
292 template <typename PointT> double
294 {
295  return (max_flow_);
296 }
297 
298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 template <typename PointT> typename pcl::MinCutSegmentation<PointT>::mGraphPtr
301 {
302  return (graph_);
303 }
304 
305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
306 template <typename PointT> bool
308 {
309  int number_of_points = static_cast<int> (input_->points.size ());
310  int number_of_indices = static_cast<int> (indices_->size ());
311 
312  if (input_->points.empty () || number_of_points == 0 || foreground_points_.empty () == true )
313  return (false);
314 
315  if (!search_)
317 
318  graph_.reset (new mGraph);
319 
320  capacity_.reset (new CapacityMap);
321  *capacity_ = boost::get (boost::edge_capacity, *graph_);
322 
323  reverse_edges_.reset (new ReverseEdgeMap);
324  *reverse_edges_ = boost::get (boost::edge_reverse, *graph_);
325 
326  VertexDescriptor vertex_descriptor(0);
327  vertices_.clear ();
328  vertices_.resize (number_of_points + 2, vertex_descriptor);
329 
330  std::set<int> out_edges_marker;
331  edge_marker_.clear ();
332  edge_marker_.resize (number_of_points + 2, out_edges_marker);
333 
334  for (int i_point = 0; i_point < number_of_points + 2; i_point++)
335  vertices_[i_point] = boost::add_vertex (*graph_);
336 
337  source_ = vertices_[number_of_points];
338  sink_ = vertices_[number_of_points + 1];
339 
340  for (int i_point = 0; i_point < number_of_indices; i_point++)
341  {
342  int point_index = (*indices_)[i_point];
343  double source_weight = 0.0;
344  double sink_weight = 0.0;
345  calculateUnaryPotential (point_index, source_weight, sink_weight);
346  addEdge (static_cast<int> (source_), point_index, source_weight);
347  addEdge (point_index, static_cast<int> (sink_), sink_weight);
348  }
349 
350  std::vector<int> neighbours;
351  std::vector<float> distances;
352  search_->setInputCloud (input_, indices_);
353  for (int i_point = 0; i_point < number_of_indices; i_point++)
354  {
355  int point_index = (*indices_)[i_point];
356  search_->nearestKSearch (i_point, number_of_neighbours_, neighbours, distances);
357  for (size_t i_nghbr = 1; i_nghbr < neighbours.size (); i_nghbr++)
358  {
359  double weight = calculateBinaryPotential (point_index, neighbours[i_nghbr]);
360  addEdge (point_index, neighbours[i_nghbr], weight);
361  addEdge (neighbours[i_nghbr], point_index, weight);
362  }
363  neighbours.clear ();
364  distances.clear ();
365  }
366 
367  return (true);
368 }
369 
370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
371 template <typename PointT> void
372 pcl::MinCutSegmentation<PointT>::calculateUnaryPotential (int point, double& source_weight, double& sink_weight) const
373 {
374  double min_dist_to_foreground = std::numeric_limits<double>::max ();
375  //double min_dist_to_background = std::numeric_limits<double>::max ();
376  double closest_foreground_point[2];
377  closest_foreground_point[0] = closest_foreground_point[1] = 0;
378  //double closest_background_point[] = {0.0, 0.0};
379  double initial_point[] = {0.0, 0.0};
380 
381  initial_point[0] = input_->points[point].x;
382  initial_point[1] = input_->points[point].y;
383 
384  for (size_t i_point = 0; i_point < foreground_points_.size (); i_point++)
385  {
386  double dist = 0.0;
387  dist += (foreground_points_[i_point].x - initial_point[0]) * (foreground_points_[i_point].x - initial_point[0]);
388  dist += (foreground_points_[i_point].y - initial_point[1]) * (foreground_points_[i_point].y - initial_point[1]);
389  if (min_dist_to_foreground > dist)
390  {
391  min_dist_to_foreground = dist;
392  closest_foreground_point[0] = foreground_points_[i_point].x;
393  closest_foreground_point[1] = foreground_points_[i_point].y;
394  }
395  }
396 
397  sink_weight = pow (min_dist_to_foreground / radius_, 0.5);
398 
399  source_weight = source_weight_;
400  return;
401 /*
402  if (background_points_.size () == 0)
403  return;
404 
405  for (int i_point = 0; i_point < background_points_.size (); i_point++)
406  {
407  double dist = 0.0;
408  dist += (background_points_[i_point].x - initial_point[0]) * (background_points_[i_point].x - initial_point[0]);
409  dist += (background_points_[i_point].y - initial_point[1]) * (background_points_[i_point].y - initial_point[1]);
410  if (min_dist_to_background > dist)
411  {
412  min_dist_to_background = dist;
413  closest_background_point[0] = background_points_[i_point].x;
414  closest_background_point[1] = background_points_[i_point].y;
415  }
416  }
417 
418  if (min_dist_to_background <= epsilon_)
419  {
420  source_weight = 0.0;
421  sink_weight = 1.0;
422  return;
423  }
424 
425  source_weight = 1.0 / (1.0 + pow (min_dist_to_background / min_dist_to_foreground, 0.5));
426  sink_weight = 1 - source_weight;
427 */
428 }
429 
430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
431 template <typename PointT> bool
432 pcl::MinCutSegmentation<PointT>::addEdge (int source, int target, double weight)
433 {
434  std::set<int>::iterator iter_out = edge_marker_[source].find (target);
435  if ( iter_out != edge_marker_[source].end () )
436  return (false);
437 
438  EdgeDescriptor edge;
439  EdgeDescriptor reverse_edge;
440  bool edge_was_added, reverse_edge_was_added;
441 
442  boost::tie (edge, edge_was_added) = boost::add_edge ( vertices_[source], vertices_[target], *graph_ );
443  boost::tie (reverse_edge, reverse_edge_was_added) = boost::add_edge ( vertices_[target], vertices_[source], *graph_ );
444  if ( !edge_was_added || !reverse_edge_was_added )
445  return (false);
446 
447  (*capacity_)[edge] = weight;
448  (*capacity_)[reverse_edge] = 0.0;
449  (*reverse_edges_)[edge] = reverse_edge;
450  (*reverse_edges_)[reverse_edge] = edge;
451  edge_marker_[source].insert (target);
452 
453  return (true);
454 }
455 
456 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
457 template <typename PointT> double
459 {
460  double weight = 0.0;
461  double distance = 0.0;
462  distance += (input_->points[source].x - input_->points[target].x) * (input_->points[source].x - input_->points[target].x);
463  distance += (input_->points[source].y - input_->points[target].y) * (input_->points[source].y - input_->points[target].y);
464  distance += (input_->points[source].z - input_->points[target].z) * (input_->points[source].z - input_->points[target].z);
465  distance *= inverse_sigma_;
466  weight = std::exp (-distance);
467 
468  return (weight);
469 }
470 
471 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
472 template <typename PointT> bool
474 {
475  OutEdgeIterator src_edge_iter;
476  OutEdgeIterator src_edge_end;
477  std::pair<EdgeDescriptor, bool> sink_edge;
478 
479  for (boost::tie (src_edge_iter, src_edge_end) = boost::out_edges (source_, *graph_); src_edge_iter != src_edge_end; src_edge_iter++)
480  {
481  double source_weight = 0.0;
482  double sink_weight = 0.0;
483  sink_edge.second = false;
484  calculateUnaryPotential (static_cast<int> (boost::target (*src_edge_iter, *graph_)), source_weight, sink_weight);
485  sink_edge = boost::lookup_edge (boost::target (*src_edge_iter, *graph_), sink_, *graph_);
486  if (!sink_edge.second)
487  return (false);
488 
489  (*capacity_)[*src_edge_iter] = source_weight;
490  (*capacity_)[sink_edge.first] = sink_weight;
491  }
492 
493  return (true);
494 }
495 
496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
497 template <typename PointT> bool
499 {
500  int number_of_points = static_cast<int> (indices_->size ());
501 
502  VertexIterator vertex_iter;
503  VertexIterator vertex_end;
504  OutEdgeIterator edge_iter;
505  OutEdgeIterator edge_end;
506 
507  std::vector< std::set<VertexDescriptor> > edge_marker;
508  std::set<VertexDescriptor> out_edges_marker;
509  edge_marker.clear ();
510  edge_marker.resize (number_of_points + 2, out_edges_marker);
511 
512  for (boost::tie (vertex_iter, vertex_end) = boost::vertices (*graph_); vertex_iter != vertex_end; vertex_iter++)
513  {
514  VertexDescriptor source_vertex = *vertex_iter;
515  if (source_vertex == source_ || source_vertex == sink_)
516  continue;
517  for (boost::tie (edge_iter, edge_end) = boost::out_edges (source_vertex, *graph_); edge_iter != edge_end; edge_iter++)
518  {
519  //If this is not the edge of the graph, but the reverse fictitious edge that is needed for the algorithm then continue
520  EdgeDescriptor reverse_edge = (*reverse_edges_)[*edge_iter];
521  if ((*capacity_)[reverse_edge] != 0.0)
522  continue;
523 
524  //If we already changed weight for this edge then continue
525  VertexDescriptor target_vertex = boost::target (*edge_iter, *graph_);
526  std::set<VertexDescriptor>::iterator iter_out = edge_marker[static_cast<int> (source_vertex)].find (target_vertex);
527  if ( iter_out != edge_marker[static_cast<int> (source_vertex)].end () )
528  continue;
529 
530  if (target_vertex != source_ && target_vertex != sink_)
531  {
532  //Change weight and remember that this edges were updated
533  double weight = calculateBinaryPotential (static_cast<int> (target_vertex), static_cast<int> (source_vertex));
534  (*capacity_)[*edge_iter] = weight;
535  edge_marker[static_cast<int> (source_vertex)].insert (target_vertex);
536  }
537  }
538  }
539 
540  return (true);
541 }
542 
543 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
544 template <typename PointT> void
546 {
547  std::vector<int> labels;
548  labels.resize (input_->points.size (), 0);
549  int number_of_indices = static_cast<int> (indices_->size ());
550  for (int i_point = 0; i_point < number_of_indices; i_point++)
551  labels[(*indices_)[i_point]] = 1;
552 
553  clusters_.clear ();
554 
555  pcl::PointIndices segment;
556  clusters_.resize (2, segment);
557 
558  OutEdgeIterator edge_iter, edge_end;
559  for ( boost::tie (edge_iter, edge_end) = boost::out_edges (source_, *graph_); edge_iter != edge_end; edge_iter++ )
560  {
561  if (labels[edge_iter->m_target] == 1)
562  {
563  if (residual_capacity[*edge_iter] > epsilon_)
564  clusters_[1].indices.push_back (static_cast<int> (edge_iter->m_target));
565  else
566  clusters_[0].indices.push_back (static_cast<int> (edge_iter->m_target));
567  }
568  }
569 }
570 
571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
572 template <typename PointT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
574 {
576 
577  if (!clusters_.empty ())
578  {
579  int num_of_pts_in_first_cluster = static_cast<int> (clusters_[0].indices.size ());
580  int num_of_pts_in_second_cluster = static_cast<int> (clusters_[1].indices.size ());
581  int number_of_points = num_of_pts_in_first_cluster + num_of_pts_in_second_cluster;
582  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
583  unsigned char foreground_color[3] = {255, 255, 255};
584  unsigned char background_color[3] = {255, 0, 0};
585  colored_cloud->width = number_of_points;
586  colored_cloud->height = 1;
587  colored_cloud->is_dense = input_->is_dense;
588 
589  pcl::PointXYZRGB point;
590  int point_index = 0;
591  for (int i_point = 0; i_point < num_of_pts_in_first_cluster; i_point++)
592  {
593  point_index = clusters_[0].indices[i_point];
594  point.x = *(input_->points[point_index].data);
595  point.y = *(input_->points[point_index].data + 1);
596  point.z = *(input_->points[point_index].data + 2);
597  point.r = background_color[0];
598  point.g = background_color[1];
599  point.b = background_color[2];
600  colored_cloud->points.push_back (point);
601  }
602 
603  for (int i_point = 0; i_point < num_of_pts_in_second_cluster; i_point++)
604  {
605  point_index = clusters_[1].indices[i_point];
606  point.x = *(input_->points[point_index].data);
607  point.y = *(input_->points[point_index].data + 1);
608  point.z = *(input_->points[point_index].data + 2);
609  point.r = foreground_color[0];
610  point.g = foreground_color[1];
611  point.b = foreground_color[2];
612  colored_cloud->points.push_back (point);
613  }
614  }
615 
616  return (colored_cloud);
617 }
618 
619 #define PCL_INSTANTIATE_MinCutSegmentation(T) template class pcl::MinCutSegmentation<T>;
620 
621 #endif // PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
double calculateBinaryPotential(int source, int target) const
Returns the binary potential(smooth cost) for the given indices of points.
typename KdTree::Ptr KdTreePtr
std::vector< PointT, Eigen::aligned_allocator< PointT > > getForegroundPoints() const
Returns the points that must belong to foreground.
KdTreePtr search_
Stores the search method that will be used for finding K nearest neighbors.
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:423
bool unary_potentials_are_valid_
Signalizes if the unary potentials are valid.
unsigned int getNumberOfNeighbours() const
Returns the number of neighbours to find.
double getMaxFlow() const
Returns that flow value that was calculated during the segmentation.
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 getRadius() const
Returns radius to the background.
~MinCutSegmentation()
Destructor that frees memory.
std::vector< std::set< int > > edge_marker_
Stores the information about the edges that were added to the graph.
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.
IndicesPtr indices_
A pointer to the vector of point indices to use.
Definition: pcl_base.h:154
double radius_
Stores the distance to the background.
void setForegroundPoints(typename pcl::PointCloud< PointT >::Ptr foreground_points)
Allows to specify points which are known to be the points of the object.
boost::shared_ptr< mGraph > mGraphPtr
void setRadius(double radius)
Allows to set the radius to the background.
boost::graph_traits< mGraph >::edge_descriptor EdgeDescriptor
unsigned int number_of_neighbours_
Stores the number of neighbors to find.
std::vector< PointT, Eigen::aligned_allocator< PointT > > foreground_points_
Stores the points that are known to be in the foreground.
Traits::vertex_descriptor VertexDescriptor
void setInputCloud(const PointCloudConstPtr &cloud) override
This method simply sets the input point cloud.
VertexDescriptor sink_
Stores the vertex that serves as sink.
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:428
double epsilon_
Used for comparison of the floating point numbers.
bool initCompute()
This method should get called before starting the actual computation.
Definition: pcl_base.hpp:138
std::vector< pcl::PointIndices > clusters_
After the segmentation it will contain the segments.
bool recalculateUnaryPotentials()
This method recalculates unary potentials(data cost) if some changes were made, instead of creating n...
std::vector< PointT, Eigen::aligned_allocator< PointT > > getBackgroundPoints() const
Returns the points that must belong to background.
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:426
void assembleLabels(ResidualCapacityMap &residual_capacity)
This method analyzes the residual network and assigns a label to every point in the cloud...
mGraphPtr graph_
Stores the graph for finding the maximum flow.
void setSourceWeight(double weight)
Allows to set weight for source edges.
void setSearchMethod(const KdTreePtr &tree)
Allows to set search method for finding KNN.
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
bool binary_potentials_are_valid_
Signalizes if the binary potentials are valid.
boost::property_map< mGraph, boost::edge_reverse_t >::type ReverseEdgeMap
boost::shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:441
void setSigma(double sigma)
Allows to set the normalization value for the binary potentials as described in the article...
boost::property_map< mGraph, boost::edge_residual_capacity_t >::type ResidualCapacityMap
bool deinitCompute()
This method should get called after finishing the actual computation.
Definition: pcl_base.hpp:171
std::vector< VertexDescriptor > vertices_
Stores the vertices of the graph.
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 graph_is_valid_
Signalizes if the graph is valid.
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.
std::vector< PointT, Eigen::aligned_allocator< PointT > > background_points_
Stores the points that are known to be in the background.
VertexDescriptor source_
Stores the vertex that serves as source.
mGraphPtr getGraph() const
Returns the graph that was build for finding the minimum cut.
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:431
boost::graph_traits< mGraph >::vertex_iterator VertexIterator
PointCloudConstPtr input_
The input point cloud dataset.
Definition: pcl_base.h:151
double inverse_sigma_
Stores the sigma coefficient.
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...
std::shared_ptr< ReverseEdgeMap > reverse_edges_
Stores reverse edges for every edge in the graph.
A point structure representing Euclidean xyz coordinates, and the RGB color.
std::shared_ptr< CapacityMap > capacity_
Stores the capacity of every edge in the graph.
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
void calculateUnaryPotential(int point, double &source_weight, double &sink_weight) const
Returns unary potential(data cost) for the given point index.
double max_flow_
Stores the maximum flow value that was calculated during the segmentation.
double source_weight_
Stores the weight for every edge that comes from source point.
typename PointCloud::ConstPtr PointCloudConstPtr
Definition: pcl_base.h:74
KdTreePtr getSearchMethod() const
Returns search method that is used for finding KNN.
double getSourceWeight() const
Returns weight that every edge from the source point has.