39#ifndef PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
40#define PCL_SEGMENTATION_MIN_CUT_SEGMENTATION_HPP_
42#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
43#include <pcl/segmentation/min_cut_segmentation.h>
44#include <pcl/search/search.h>
45#include <pcl/search/kdtree.h>
49template <
typename Po
intT>
51 inverse_sigma_ (16.0),
52 binary_potentials_are_valid_ (
false),
55 unary_potentials_are_valid_ (
false),
58 number_of_neighbours_ (14),
59 graph_is_valid_ (
false),
60 foreground_points_ (0),
61 background_points_ (0),
72template <
typename Po
intT>
75 foreground_points_.clear ();
76 background_points_.clear ();
79 edge_marker_.clear ();
83template <
typename Po
intT>
void
87 graph_is_valid_ =
false;
88 unary_potentials_are_valid_ =
false;
89 binary_potentials_are_valid_ =
false;
93template <
typename Po
intT>
double
96 return (
pow (1.0 / inverse_sigma_, 0.5));
100template <
typename Po
intT>
void
103 if (sigma > epsilon_)
105 inverse_sigma_ = 1.0 / (sigma * sigma);
106 binary_potentials_are_valid_ =
false;
111template <
typename Po
intT>
double
114 return (
pow (radius_, 0.5));
118template <
typename Po
intT>
void
121 if (radius > epsilon_)
123 radius_ = radius * radius;
124 unary_potentials_are_valid_ =
false;
129template <
typename Po
intT>
double
132 return (source_weight_);
136template <
typename Po
intT>
void
139 if (weight > epsilon_)
141 source_weight_ = weight;
142 unary_potentials_are_valid_ =
false;
154template <
typename Po
intT>
void
161template <
typename Po
intT>
unsigned int
164 return (number_of_neighbours_);
168template <
typename Po
intT>
void
174 graph_is_valid_ =
false;
175 unary_potentials_are_valid_ =
false;
176 binary_potentials_are_valid_ =
false;
181template <
typename Po
intT> std::vector<PointT, Eigen::aligned_allocator<PointT> >
184 return (foreground_points_);
188template <
typename Po
intT>
void
191 foreground_points_.clear ();
192 foreground_points_.insert(
195 unary_potentials_are_valid_ =
false;
199template <
typename Po
intT> std::vector<PointT, Eigen::aligned_allocator<PointT> >
202 return (background_points_);
206template <
typename Po
intT>
void
209 background_points_.clear ();
210 background_points_.insert(
213 unary_potentials_are_valid_ =
false;
217template <
typename Po
intT>
void
229 if ( graph_is_valid_ && unary_potentials_are_valid_ && binary_potentials_are_valid_ )
231 clusters.reserve (clusters_.size ());
232 std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (
clusters));
239 if ( !graph_is_valid_ )
247 graph_is_valid_ =
true;
248 unary_potentials_are_valid_ =
true;
249 binary_potentials_are_valid_ =
true;
252 if ( !unary_potentials_are_valid_ )
254 bool success = recalculateUnaryPotentials ();
260 unary_potentials_are_valid_ =
true;
263 if ( !binary_potentials_are_valid_ )
265 bool success = recalculateBinaryPotentials ();
271 binary_potentials_are_valid_ =
true;
277 max_flow_ = boost::boykov_kolmogorov_max_flow (*graph_, source_, sink_);
281 clusters.reserve (clusters_.size ());
282 std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (
clusters));
288template <
typename Po
intT>
double
302template <
typename Po
intT>
bool
308 if (input_->points.empty () ||
number_of_points == 0 || foreground_points_.empty () ==
true )
314 graph_.reset (
new mGraph);
317 *capacity_ = boost::get (boost::edge_capacity, *graph_);
320 *reverse_edges_ = boost::get (boost::edge_reverse, *graph_);
327 edge_marker_.clear ();
331 vertices_[
i_point] = boost::add_vertex (*graph_);
346 std::vector<float> distances;
347 search_->setInputCloud (input_, indices_);
366template <
typename Po
intT>
void
377 for (
const auto&
fg_point : foreground_points_)
422template <
typename Po
intT>
bool
438 (*capacity_)[
edge] = weight;
448template <
typename Po
intT>
double
452 double distance = 0.0;
456 distance *= inverse_sigma_;
457 weight = std::exp (-distance);
463template <
typename Po
intT>
bool
468 std::pair<EdgeDescriptor, bool>
sink_edge;
488template <
typename Po
intT>
bool
496 std::vector< std::set<VertexDescriptor> >
edge_marker;
533template <
typename Po
intT>
void
536 std::vector<int> labels;
537 labels.resize (input_->size (), 0);
538 for (
const auto&
i_point : (*indices_))
544 clusters_.resize (2, segment);
552 clusters_[1].indices.push_back (
static_cast<int> (
edge_iter->m_target));
554 clusters_[0].indices.push_back (
static_cast<int> (
edge_iter->m_target));
565 if (!clusters_.empty ())
570 colored_cloud->width = (clusters_[0].indices.size () + clusters_[1].indices.size ());
575 for (
const auto&
point_index : (clusters_[0].indices))
586 for (
const auto&
point_index : (clusters_[1].indices))
601#define PCL_INSTANTIATE_MinCutSegmentation(T) template class pcl::MinCutSegmentation<T>;
Iterator class for point clouds with or without given indices.
std::size_t size() const
Size of the range the iterator is going through.
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
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
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.
typename PointCloud::ConstPtr PointCloudConstPtr
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::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.
shared_ptr< PointCloud< PointT > > Ptr
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
A point structure representing Euclidean xyz coordinates, and the RGB color.