41#include <pcl/common/io.h>
42#include <pcl/common/point_tests.h>
43#include <pcl/search/organized.h>
44#include <pcl/search/kdtree.h>
54 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));
60template <
typename Po
intT>
63 r =
static_cast<float> (p.r) / 255.0;
64 g =
static_cast<float> (p.g) / 255.0;
65 b =
static_cast<float> (p.b) / 255.0;
68template <
typename Po
intT>
69grabcut::Color::operator PointT ()
const
72 p.r =
static_cast<std::uint32_t
> (
r * 255);
73 p.g =
static_cast<std::uint32_t
> (
g * 255);
74 p.b =
static_cast<std::uint32_t
> (
b * 255);
80template <
typename Po
intT>
void
86template <
typename Po
intT>
bool
92 PCL_ERROR (
"[pcl::GrabCut::initCompute ()] Init failed!\n");
96 std::vector<pcl::PCLPointField> in_fields_;
100 PCL_ERROR (
"[pcl::GrabCut::initCompute ()] No RGB data available, aborting!\n");
106 for (std::size_t i = 0; i <
input_->size (); ++i)
120 const std::size_t indices_size =
indices_->size ();
122 hard_segmentation_ = std::vector<segmentation::grabcut::SegmentationValue> (indices_size,
134 if (
image_->isOrganized ())
149template <
typename Po
intT>
void
152 graph_.addEdge (v1, v2, capacity, rev_capacity);
155template <
typename Po
intT>
void
158 graph_.addSourceEdge (v, source_capacity);
159 graph_.addTargetEdge (v, sink_capacity);
162template <
typename Po
intT>
void
171 for (
const auto &index : indices->indices)
184template <
typename Po
intT>
void
194template <
typename Po
intT>
int
203 float flow =
graph_.solve ();
206 PCL_INFO (
"%d pixels changed segmentation (max flow = %f)\n", changed, flow);
211template <
typename Po
intT>
void
214 std::size_t changed =
indices_->size ();
220template <
typename Po
intT>
int
227 const int number_of_indices =
static_cast<int> (
indices_->size ());
228 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
251template <
typename Po
intT>
void
255 for (
const auto &index : indices->indices)
260 for (
const auto &index : indices->indices)
264 for (
const auto &index : indices->indices)
268template <
typename Po
intT>
void
272 const int number_of_indices =
static_cast<int> (
indices_->size ());
278 for (std::size_t idx = 0; idx <
indices_->size (); ++idx)
285 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
287 int point_index = (*indices_) [i_point];
315 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
320 const auto point_index = (*indices_) [i_point];
321 auto weights_it = n_link.
weights.begin ();
322 for (
auto indices_it = n_link.
indices.cbegin (); indices_it != n_link.
indices.cend (); ++indices_it, ++weights_it)
324 if ((*indices_it != point_index) && (*indices_it !=
UNAVAILABLE))
333template <
typename Po
intT>
void
336 const int number_of_indices =
static_cast<int> (
indices_->size ());
337 for (
int i_point = 0; i_point < number_of_indices; ++i_point)
342 const auto point_index = (*indices_) [i_point];
343 auto dists_it = n_link.
dists.cbegin ();
344 auto weights_it = n_link.
weights.begin ();
345 for (
auto indices_it = n_link.
indices.cbegin (); indices_it != n_link.
indices.cend (); ++indices_it, ++dists_it, ++weights_it)
347 if (*indices_it != point_index)
350 float color_distance = *weights_it;
352 *weights_it =
static_cast<float> (
lambda_ * std::exp (-
beta_ * color_distance) / sqrt (*dists_it));
359template <
typename Po
intT>
void
362 for(
unsigned int y = 0; y <
image_->height; ++y )
364 for(
unsigned int x = 0; x <
image_->width; ++x )
368 std::size_t point_index = y *
input_->width + x;
371 if( x > 0 && y < image_->height-1 )
374 if( y < image_->height-1 )
377 if( x < image_->width-1 && y < image_->height-1 )
380 if( x < image_->width-1 )
386template <
typename Po
intT>
void
390 std::size_t edges = 0;
392 const int number_of_indices =
static_cast<int> (
indices_->size ());
394 for (
int i_point = 0; i_point < number_of_indices; i_point++)
396 const auto point_index = (*indices_)[i_point];
397 const PointT& point =
input_->points [point_index];
406 for (
const auto& nn_index : links.
indices)
408 if (nn_index != point_index)
411 links.
weights.push_back (color_distance);
412 result+= color_distance;
422 beta_ = 1e5 / (2*result / edges);
425template <
typename Po
intT>
void
429 std::size_t edges = 0;
431 for (
unsigned int y = 0; y <
input_->height; ++y)
433 for (
unsigned int x = 0; x <
input_->width; ++x)
435 std::size_t point_index = y *
input_->width + x;
442 if (x > 0 && y < input_->height-1)
444 std::size_t upleft = (y+1) *
input_->width + x - 1;
446 links.
dists[0] = std::sqrt (2.f);
454 if (y < input_->height-1)
456 std::size_t up = (y+1) *
input_->width + x;
466 if (x < input_->width-1 && y < input_->height-1)
468 std::size_t upright = (y+1) *
input_->width + x + 1;
470 links.
dists[2] = std::sqrt (2.f);
472 image_->points [upright]);
478 if (x < input_->width-1)
480 std::size_t right = y *
input_->width + x + 1;
492 beta_ = 1e5 / (2*result / edges);
495template <
typename Po
intT>
void
501template <
typename Po
intT>
void
507 clusters[0].indices.reserve (
indices_->size ());
508 clusters[1].indices.reserve (
indices_->size ());
511 const int indices_size =
static_cast<int> (
indices_->size ());
512 for (
int i = 0; i < indices_size; ++i)
514 clusters[1].indices.push_back (i);
516 clusters[0].indices.push_back (i);
void computeL()
Compute L parameter from given lambda.
std::uint32_t K_
Number of GMM components.
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 graph_
Graph for Graphcut.
std::vector< std::size_t > GMM_component_
std::uint32_t width_
image width
std::uint32_t height_
image height
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.
segmentation::grabcut::GMM background_GMM_
void computeBetaOrganized()
Compute beta from image.
float L_
L = a large value to force a pixel to be foreground or background.
float lambda_
lambda = 50. This value was suggested the GrabCut paper.
typename PCLBase< PointT >::PointCloudConstPtr PointCloudConstPtr
std::vector< segmentation::grabcut::SegmentationValue > hard_segmentation_
void computeNLinksOrganized()
Compute NLinks from image.
bool isSource(vertex_descriptor v)
std::vector< NLinks > n_links_
Precomputed N-link weights.
void setTerminalWeights(vertex_descriptor v, float source_capacity, float sink_capacity)
Set the weights of SOURCE --> v and v --> SINK.
segmentation::grabcut::GMM foreground_GMM_
segmentation::grabcut::Image::Ptr image_
Converted input.
KdTreePtr tree_
Pointer to the spatial search object.
float beta_
beta = 1/2 * average of the squared color distances between all pairs of 8-neighboring pixels.
void setBackgroundPointsIndices(int x1, int y1, int x2, int y2)
Set background indices, foreground indices = indices \ background indices.
int nb_neighbours_
Number of neighbours.
std::vector< vertex_descriptor > graph_nodes_
Graph nodes.
void setInputCloud(const PointCloudConstPtr &cloud) override
Provide a pointer to the input dataset.
void computeBetaNonOrganized()
Compute beta from cloud.
bool initialized_
is segmentation initialized
std::vector< segmentation::grabcut::TrimapValue > trimap_
PointCloudConstPtr input_
The input point cloud dataset.
IndicesPtr indices_
A pointer to the vector of point indices to use.
bool initCompute()
This method should get called before starting the actual computation.
PointIndices::ConstPtr PointIndicesConstPtr
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
Define standard C methods to do distance calculations.
TrimapValue
User supplied Trimap values.
PCL_EXPORTS void buildGMMs(const Image &image, const Indices &indices, const std::vector< SegmentationValue > &hardSegmentation, std::vector< std::size_t > &components, GMM &background_GMM, GMM &foreground_GMM)
Build the initial GMMs using the Orchard and Bouman color clustering algorithm.
pcl::PointCloud< Color > Image
An Image is a point cloud of Color.
SegmentationValue
Grabcut derived hard segmentation values.
PCL_EXPORTS void learnGMMs(const Image &image, const Indices &indices, const std::vector< SegmentationValue > &hard_segmentation, std::vector< std::size_t > &components, GMM &background_GMM, GMM &foreground_GMM)
Iteratively learn GMMs using GrabCut updating algorithm.
int getFieldIndex(const pcl::PointCloud< PointT > &, const std::string &field_name, std::vector< pcl::PCLPointField > &fields)
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
Structure to save RGB colors into floats.