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