41#include <pcl/common/io.h>
42#include <pcl/common/point_tests.h>
43#include <pcl/search/auto.h>
53 return ((c1.
r-c2.
r)*(c1.
r-c2.
r)+(c1.
g-c2.
g)*(c1.
g-c2.
g)+(c1.
b-c2.
b)*(c1.
b-c2.
b));
59template <
typename Po
intT>
62 r =
static_cast<float> (p.r) / 255.0;
63 g =
static_cast<float> (p.g) / 255.0;
64 b =
static_cast<float> (p.b) / 255.0;
67template <
typename Po
intT>
68grabcut::Color::operator
PointT ()
const
71 p.r =
static_cast<std::uint32_t
> (r * 255);
72 p.g =
static_cast<std::uint32_t
> (g * 255);
73 p.b =
static_cast<std::uint32_t
> (b * 255);
79template <
typename Po
intT>
void
85template <
typename Po
intT>
bool
91 PCL_ERROR (
"[pcl::GrabCut::initCompute ()] Init failed!\n");
95 std::vector<pcl::PCLPointField> in_fields_;
96 if ((pcl::getFieldIndex<PointT> (
"rgb", in_fields_) == -1) &&
97 (pcl::getFieldIndex<PointT> (
"rgba", in_fields_) == -1))
99 PCL_ERROR (
"[pcl::GrabCut::initCompute ()] No RGB data available, aborting!\n");
104 image_.reset (
new Image (input_->width, input_->height));
105 for (std::size_t i = 0; i < input_->size (); ++i)
107 (*image_) [i] =
Color ((*input_)[i]);
109 width_ = image_->width;
110 height_ = image_->height;
113 if (!tree_ && !input_->isOrganized ())
116 const std::size_t indices_size = indices_->size ();
117 trimap_ = std::vector<segmentation::grabcut::TrimapValue> (indices_size, TrimapUnknown);
118 hard_segmentation_ = std::vector<segmentation::grabcut::SegmentationValue> (indices_size,
119 SegmentationBackground);
120 GMM_component_.resize (indices_size);
121 n_links_.resize (indices_size);
124 foreground_GMM_.resize (K_);
125 background_GMM_.resize (K_);
130 if (image_->isOrganized ())
132 computeBetaOrganized ();
133 computeNLinksOrganized ();
137 computeBetaNonOrganized ();
138 computeNLinksNonOrganized ();
141 initialized_ =
false;
145template <
typename Po
intT>
void
148 graph_.addEdge (v1, v2, capacity, rev_capacity);
151template <
typename Po
intT>
void
154 graph_.addSourceEdge (v, source_capacity);
155 graph_.addTargetEdge (v, sink_capacity);
158template <
typename Po
intT>
void
165 std::fill (trimap_.begin (), trimap_.end (), TrimapBackground);
166 std::fill (hard_segmentation_.begin (), hard_segmentation_.end (), SegmentationBackground);
167 for (
const auto &index : indices->indices)
169 trimap_[index] = TrimapUnknown;
170 hard_segmentation_[index] = SegmentationForeground;
180template <
typename Po
intT>
void
184 buildGMMs (*image_, *indices_, hard_segmentation_, GMM_component_, background_GMM_, foreground_GMM_);
190template <
typename Po
intT>
int
194 learnGMMs (*image_, *indices_, hard_segmentation_, GMM_component_, background_GMM_, foreground_GMM_);
199 float flow = graph_.solve ();
201 int changed = updateHardSegmentation ();
202 PCL_INFO (
"%d pixels changed segmentation (max flow = %f)\n", changed, flow);
207template <
typename Po
intT>
void
210 std::size_t changed = indices_->size ();
213 changed = refineOnce ();
216template <
typename Po
intT>
int
223 const int number_of_indices =
static_cast<int> (indices_->size ());
224 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
228 if (trimap_ [i_point] == TrimapBackground)
229 hard_segmentation_ [i_point] = SegmentationBackground;
231 if (trimap_ [i_point] == TrimapForeground)
232 hard_segmentation_ [i_point] = SegmentationForeground;
235 if (isSource (graph_nodes_[i_point]))
236 hard_segmentation_ [i_point] = SegmentationForeground;
238 hard_segmentation_ [i_point] = SegmentationBackground;
241 if (old_value != hard_segmentation_ [i_point])
247template <
typename Po
intT>
void
251 for (
const auto &index : indices->indices)
255 if (t == TrimapForeground)
256 for (
const auto &index : indices->indices)
257 hard_segmentation_[index] = SegmentationForeground;
259 if (t == TrimapBackground)
260 for (
const auto &index : indices->indices)
261 hard_segmentation_[index] = SegmentationBackground;
264template <
typename Po
intT>
void
268 const int number_of_indices =
static_cast<int> (indices_->size ());
271 graph_nodes_.clear ();
272 graph_nodes_.resize (indices_->size ());
273 int start = graph_.addNodes (indices_->size ());
274 for (std::size_t idx = 0; idx < indices_->size (); ++idx)
276 graph_nodes_[idx] = start;
281 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
283 int point_index = (*indices_) [i_point];
286 switch (trimap_[point_index])
290 fore =
static_cast<float> (-std::log (background_GMM_.probabilityDensity ((*image_)[point_index])));
291 back =
static_cast<float> (-std::log (foreground_GMM_.probabilityDensity ((*image_)[point_index])));
294 case TrimapBackground :
307 setTerminalWeights (graph_nodes_[i_point], fore, back);
311 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
313 const NLinks &n_link = n_links_[i_point];
316 const auto point_index = (*indices_) [i_point];
317 auto weights_it = n_link.
weights.begin ();
318 for (
auto indices_it = n_link.
indices.cbegin (); indices_it != n_link.
indices.cend (); ++indices_it, ++weights_it)
320 if ((*indices_it != point_index) && (*indices_it !=
UNAVAILABLE))
322 addEdge (graph_nodes_[i_point], graph_nodes_[*indices_it], *weights_it, *weights_it);
329template <
typename Po
intT>
void
332 const int number_of_indices =
static_cast<int> (indices_->size ());
333 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
335 NLinks &n_link = n_links_[i_point];
338 const auto point_index = (*indices_) [i_point];
339 auto dists_it = n_link.
dists.cbegin ();
340 auto weights_it = n_link.
weights.begin ();
341 for (
auto indices_it = n_link.
indices.cbegin (); indices_it != n_link.
indices.cend (); ++indices_it, ++dists_it, ++weights_it)
343 if (*indices_it != point_index)
346 float color_distance = *weights_it;
348 *weights_it =
static_cast<float> (lambda_ * std::exp (-beta_ * color_distance) / sqrt (*dists_it));
355template <
typename Po
intT>
void
358 for(
unsigned int y = 0; y < image_->height; ++y )
360 for(
unsigned int x = 0; x < image_->width; ++x )
364 std::size_t point_index = y * input_->width + x;
365 NLinks &links = n_links_[point_index];
367 if( x > 0 && y < image_->height-1 )
370 if( y < image_->height-1 )
373 if( x < image_->width-1 && y < image_->height-1 )
376 if( x < image_->width-1 )
382template <
typename Po
intT>
void
386 std::size_t edges = 0;
388 const int number_of_indices =
static_cast<int> (indices_->size ());
390 for (
int i_point = 0; i_point < number_of_indices; i_point++)
392 const auto point_index = (*indices_)[i_point];
393 const PointT& point = input_->points [point_index];
396 NLinks &links = n_links_[i_point];
397 int found = tree_->nearestKSearch (point, nb_neighbours_, links.
indices, links.
dists);
402 for (
const auto& nn_index : links.
indices)
404 if (nn_index != point_index)
407 links.
weights.push_back (color_distance);
408 result+= color_distance;
418 beta_ = 1e5 / (2*result / edges);
421template <
typename Po
intT>
void
425 std::size_t edges = 0;
427 for (
unsigned int y = 0; y < input_->height; ++y)
429 for (
unsigned int x = 0; x < input_->width; ++x)
431 std::size_t point_index = y * input_->width + x;
432 NLinks &links = n_links_[point_index];
438 if (x > 0 && y < input_->height-1)
440 std::size_t upleft = (y+1) * input_->width + x - 1;
442 links.
dists[0] = std::sqrt (2.f);
450 if (y < input_->height-1)
452 std::size_t up = (y+1) * input_->width + x;
462 if (x < input_->width-1 && y < input_->height-1)
464 std::size_t upright = (y+1) * input_->width + x + 1;
466 links.
dists[2] = std::sqrt (2.f);
468 image_->points [upright]);
474 if (x < input_->width-1)
476 std::size_t right = y * input_->width + x + 1;
488 beta_ = 1e5 / (2*result / edges);
491template <
typename Po
intT>
void
497template <
typename Po
intT>
void
503 clusters[0].indices.reserve (indices_->size ());
504 clusters[1].indices.reserve (indices_->size ());
506 assert (hard_segmentation_.size () == indices_->size ());
507 const int indices_size =
static_cast<int> (indices_->size ());
508 for (
int i = 0; i < indices_size; ++i)
509 if (hard_segmentation_[i] == SegmentationForeground)
510 clusters[1].indices.push_back (i);
512 clusters[0].indices.push_back (i);
void computeL()
Compute L parameter from given lambda.
void addEdge(vertex_descriptor v1, vertex_descriptor v2, float capacity, float rev_capacity)
Add an edge to the graph, graph must be oriented so we add the edge and its reverse.
virtual void fitGMMs()
Fit Gaussian Multi Models.
int updateHardSegmentation()
void computeNLinksNonOrganized()
Compute NLinks from cloud.
virtual void refine()
Run Grabcut refinement on the hard segmentation.
void setTrimap(const PointIndicesConstPtr &indices, segmentation::grabcut::TrimapValue t)
Edit Trimap.
pcl::segmentation::grabcut::BoykovKolmogorov::vertex_descriptor vertex_descriptor
void extract(std::vector< pcl::PointIndices > &clusters)
This method launches the segmentation algorithm and returns the clusters that were obtained during th...
void initGraph()
Build the graph for GraphCut.
void computeBetaOrganized()
Compute beta from image.
typename PCLBase< PointT >::PointCloudConstPtr PointCloudConstPtr
void computeNLinksOrganized()
Compute NLinks from image.
void setTerminalWeights(vertex_descriptor v, float source_capacity, float sink_capacity)
Set the weights of SOURCE --> v and v --> SINK.
void setBackgroundPointsIndices(int x1, int y1, int x2, int y2)
Set background indices, foreground indices = indices \ background indices.
void setInputCloud(const PointCloudConstPtr &cloud) override
Provide a pointer to the input dataset.
void computeBetaNonOrganized()
Compute beta from cloud.
PointIndices::ConstPtr PointIndicesConstPtr
Define standard C methods to do distance calculations.
@ many_knn_search
The search method will mainly be used for nearestKSearch where k is larger than 1.
TrimapValue
User supplied Trimap values.
SegmentationValue
Grabcut derived hard segmentation values.
pcl::PointCloud< Color > Image
An Image is a point cloud of Color.
float squaredEuclideanDistance(const PointType1 &p1, const PointType2 &p2)
Calculate the squared euclidean distance between the two given points.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
static constexpr index_t UNAVAILABLE
std::vector< float > weights
std::vector< float > dists
A point structure representing Euclidean xyz coordinates, and the RGB color.
Structure to save RGB colors into floats.