Point Cloud Library (PCL)  1.7.0
region_growing.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  * Author : Sergey Ushakov
36  * Email : mine_all_mine@bk.ru
37  *
38  */
39 
40 #ifndef PCL_SEGMENTATION_REGION_GROWING_HPP_
41 #define PCL_SEGMENTATION_REGION_GROWING_HPP_
42 
43 #include <pcl/segmentation/region_growing.h>
44 
45 #include <pcl/search/search.h>
46 #include <pcl/search/kdtree.h>
47 #include <pcl/point_cloud.h>
48 #include <pcl/point_types.h>
49 
50 #include <queue>
51 #include <list>
52 #include <cmath>
53 #include <time.h>
54 
55 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
56 template <typename PointT, typename NormalT>
58  min_pts_per_cluster_ (1),
59  max_pts_per_cluster_ (std::numeric_limits<int>::max ()),
60  smooth_mode_flag_ (true),
61  curvature_flag_ (true),
62  residual_flag_ (false),
63  theta_threshold_ (30.0f / 180.0f * static_cast<float> (M_PI)),
64  residual_threshold_ (0.05f),
65  curvature_threshold_ (0.05f),
66  neighbour_number_ (30),
67  search_ (),
68  normals_ (),
69  point_neighbours_ (0),
70  point_labels_ (0),
71  normal_flag_ (true),
72  num_pts_in_segment_ (0),
73  clusters_ (0),
74  number_of_segments_ (0)
75 {
76 }
77 
78 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79 template <typename PointT, typename NormalT>
81 {
82  if (search_ != 0)
83  search_.reset ();
84  if (normals_ != 0)
85  normals_.reset ();
86 
87  point_neighbours_.clear ();
88  point_labels_.clear ();
89  num_pts_in_segment_.clear ();
90  clusters_.clear ();
91 }
92 
93 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94 template <typename PointT, typename NormalT> int
96 {
97  return (min_pts_per_cluster_);
98 }
99 
100 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 template <typename PointT, typename NormalT> void
103 {
104  min_pts_per_cluster_ = min_cluster_size;
105 }
106 
107 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108 template <typename PointT, typename NormalT> int
110 {
111  return (max_pts_per_cluster_);
112 }
113 
114 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
115 template <typename PointT, typename NormalT> void
117 {
118  max_pts_per_cluster_ = max_cluster_size;
119 }
120 
121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
122 template <typename PointT, typename NormalT> bool
124 {
125  return (smooth_mode_flag_);
126 }
127 
128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129 template <typename PointT, typename NormalT> void
131 {
132  smooth_mode_flag_ = value;
133 }
134 
135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 template <typename PointT, typename NormalT> bool
138 {
139  return (curvature_flag_);
140 }
141 
142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
143 template <typename PointT, typename NormalT> void
145 {
146  curvature_flag_ = value;
147 
148  if (curvature_flag_ == false && residual_flag_ == false)
149  residual_flag_ = true;
150 }
151 
152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153 template <typename PointT, typename NormalT> bool
155 {
156  return (residual_flag_);
157 }
158 
159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
160 template <typename PointT, typename NormalT> void
162 {
163  residual_flag_ = value;
164 
165  if (curvature_flag_ == false && residual_flag_ == false)
166  curvature_flag_ = true;
167 }
168 
169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
170 template <typename PointT, typename NormalT> float
172 {
173  return (theta_threshold_);
174 }
175 
176 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177 template <typename PointT, typename NormalT> void
179 {
180  theta_threshold_ = theta;
181 }
182 
183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
184 template <typename PointT, typename NormalT> float
186 {
187  return (residual_threshold_);
188 }
189 
190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
191 template <typename PointT, typename NormalT> void
193 {
194  residual_threshold_ = residual;
195 }
196 
197 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198 template <typename PointT, typename NormalT> float
200 {
201  return (curvature_threshold_);
202 }
203 
204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
205 template <typename PointT, typename NormalT> void
207 {
208  curvature_threshold_ = curvature;
209 }
210 
211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
212 template <typename PointT, typename NormalT> unsigned int
214 {
215  return (neighbour_number_);
216 }
217 
218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219 template <typename PointT, typename NormalT> void
221 {
222  neighbour_number_ = neighbour_number;
223 }
224 
225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 template <typename PointT, typename NormalT> typename pcl::RegionGrowing<PointT, NormalT>::KdTreePtr
228 {
229  return (search_);
230 }
231 
232 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
233 template <typename PointT, typename NormalT> void
235 {
236  if (search_ != 0)
237  search_.reset ();
238 
239  search_ = tree;
240 }
241 
242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
243 template <typename PointT, typename NormalT> typename pcl::RegionGrowing<PointT, NormalT>::NormalPtr
245 {
246  return (normals_);
247 }
248 
249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
250 template <typename PointT, typename NormalT> void
252 {
253  if (normals_ != 0)
254  normals_.reset ();
255 
256  normals_ = norm;
257 }
258 
259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
260 template <typename PointT, typename NormalT> void
261 pcl::RegionGrowing<PointT, NormalT>::extract (std::vector <pcl::PointIndices>& clusters)
262 {
263  clusters_.clear ();
264  clusters.clear ();
265  point_neighbours_.clear ();
266  point_labels_.clear ();
267  num_pts_in_segment_.clear ();
268  number_of_segments_ = 0;
269 
270  bool segmentation_is_possible = initCompute ();
271  if ( !segmentation_is_possible )
272  {
273  deinitCompute ();
274  return;
275  }
276 
277  segmentation_is_possible = prepareForSegmentation ();
278  if ( !segmentation_is_possible )
279  {
280  deinitCompute ();
281  return;
282  }
283 
284  findPointNeighbours ();
285  applySmoothRegionGrowingAlgorithm ();
286  assembleRegions ();
287 
288  clusters.resize (clusters_.size ());
289  std::vector<pcl::PointIndices>::iterator cluster_iter_input = clusters.begin ();
290  for (std::vector<pcl::PointIndices>::const_iterator cluster_iter = clusters_.begin (); cluster_iter != clusters_.end (); cluster_iter++)
291  {
292  if ((cluster_iter->indices.size () >= min_pts_per_cluster_) &&
293  (cluster_iter->indices.size () <= max_pts_per_cluster_))
294  {
295  *cluster_iter_input = *cluster_iter;
296  cluster_iter_input++;
297  }
298  }
299 
300  clusters_ = std::vector<pcl::PointIndices> (clusters.begin (), cluster_iter_input);
301 
302  deinitCompute ();
303 }
304 
305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
306 template <typename PointT, typename NormalT> bool
308 {
309  // if user forgot to pass point cloud or if it is empty
310  if ( input_->points.size () == 0 )
311  return (false);
312 
313  // if user forgot to pass normals or the sizes of point and normal cloud are different
314  if ( normals_ == 0 || input_->points.size () != normals_->points.size () )
315  return (false);
316 
317  // if residual test is on then we need to check if all needed parameters were correctly initialized
318  if (residual_flag_)
319  {
320  if (residual_threshold_ <= 0.0f)
321  return (false);
322  }
323 
324  // if curvature test is on ...
325  // if (curvature_flag_)
326  // {
327  // in this case we do not need to check anything that related to it
328  // so we simply commented it
329  // }
330 
331  // from here we check those parameters that are always valuable
332  if (neighbour_number_ == 0)
333  return (false);
334 
335  // if user didn't set search method
336  if (!search_)
337  search_.reset (new pcl::search::KdTree<PointT>);
338 
339  if (indices_)
340  {
341  if (indices_->empty ())
342  PCL_ERROR ("[pcl::RegionGrowing::prepareForSegmentation] Empty given indices!\n");
343  search_->setInputCloud (input_, indices_);
344  }
345  else
346  search_->setInputCloud (input_);
347 
348  return (true);
349 }
350 
351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
352 template <typename PointT, typename NormalT> void
354 {
355  int point_number = static_cast<int> (indices_->size ());
356  std::vector<int> neighbours;
357  std::vector<float> distances;
358 
359  point_neighbours_.resize (input_->points.size (), neighbours);
360 
361  for (int i_point = 0; i_point < point_number; i_point++)
362  {
363  int point_index = (*indices_)[i_point];
364  neighbours.clear ();
365  search_->nearestKSearch (i_point, neighbour_number_, neighbours, distances);
366  point_neighbours_[point_index].swap (neighbours);
367  }
368 }
369 
370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
371 template <typename PointT, typename NormalT> void
373 {
374  int num_of_pts = static_cast<int> (indices_->size ());
375  point_labels_.resize (input_->points.size (), -1);
376 
377  std::vector< std::pair<float, int> > point_residual;
378  std::pair<float, int> pair;
379  point_residual.resize (num_of_pts, pair);
380 
381  if (normal_flag_ == true)
382  {
383  for (int i_point = 0; i_point < num_of_pts; i_point++)
384  {
385  int point_index = (*indices_)[i_point];
386  point_residual[i_point].first = normals_->points[point_index].curvature;
387  point_residual[i_point].second = point_index;
388  }
389  std::sort (point_residual.begin (), point_residual.end (), comparePair);
390  }
391  else
392  {
393  for (int i_point = 0; i_point < num_of_pts; i_point++)
394  {
395  int point_index = (*indices_)[i_point];
396  point_residual[i_point].first = 0;
397  point_residual[i_point].second = point_index;
398  }
399  }
400  int seed_counter = 0;
401  int seed = point_residual[seed_counter].second;
402 
403  int segmented_pts_num = 0;
404  int number_of_segments = 0;
405  while (segmented_pts_num < num_of_pts)
406  {
407  int pts_in_segment;
408  pts_in_segment = growRegion (seed, number_of_segments);
409  segmented_pts_num += pts_in_segment;
410  num_pts_in_segment_.push_back (pts_in_segment);
411  number_of_segments++;
412 
413  //find next point that is not segmented yet
414  for (int i_seed = seed_counter + 1; i_seed < num_of_pts; i_seed++)
415  {
416  int index = point_residual[i_seed].second;
417  if (point_labels_[index] == -1)
418  {
419  seed = index;
420  break;
421  }
422  }
423  }
424 }
425 
426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
427 template <typename PointT, typename NormalT> int
428 pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
429 {
430  std::queue<int> seeds;
431  seeds.push (initial_seed);
432  point_labels_[initial_seed] = segment_number;
433 
434  int num_pts_in_segment = 1;
435 
436  while (!seeds.empty ())
437  {
438  int curr_seed;
439  curr_seed = seeds.front ();
440  seeds.pop ();
441 
442  size_t i_nghbr = 0;
443  while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
444  {
445  int index = point_neighbours_[curr_seed][i_nghbr];
446  if (point_labels_[index] != -1)
447  {
448  i_nghbr++;
449  continue;
450  }
451 
452  bool is_a_seed = false;
453  bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
454 
455  if (belongs_to_segment == false)
456  {
457  i_nghbr++;
458  continue;
459  }
460 
461  point_labels_[index] = segment_number;
462  num_pts_in_segment++;
463 
464  if (is_a_seed)
465  {
466  seeds.push (index);
467  }
468 
469  i_nghbr++;
470  }// next neighbour
471  }// next seed
472 
473  return (num_pts_in_segment);
474 }
475 
476 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
477 template <typename PointT, typename NormalT> bool
478 pcl::RegionGrowing<PointT, NormalT>::validatePoint (int initial_seed, int point, int nghbr, bool& is_a_seed) const
479 {
480  is_a_seed = true;
481 
482  float cosine_threshold = cosf (theta_threshold_);
483  float data[4];
484 
485  data[0] = input_->points[point].data[0];
486  data[1] = input_->points[point].data[1];
487  data[2] = input_->points[point].data[2];
488  data[3] = input_->points[point].data[3];
489  Eigen::Map<Eigen::Vector3f> initial_point (static_cast<float*> (data));
490  Eigen::Map<Eigen::Vector3f> initial_normal (static_cast<float*> (normals_->points[point].normal));
491 
492  //check the angle between normals
493  if (smooth_mode_flag_ == true)
494  {
495  Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> (normals_->points[nghbr].normal));
496  float dot_product = fabsf (nghbr_normal.dot (initial_normal));
497  if (dot_product < cosine_threshold)
498  {
499  return (false);
500  }
501  }
502  else
503  {
504  Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> (normals_->points[nghbr].normal));
505  Eigen::Map<Eigen::Vector3f> initial_seed_normal (static_cast<float*> (normals_->points[initial_seed].normal));
506  float dot_product = fabsf (nghbr_normal.dot (initial_seed_normal));
507  if (dot_product < cosine_threshold)
508  return (false);
509  }
510 
511  // check the curvature if needed
512  if (curvature_flag_ && normals_->points[nghbr].curvature > curvature_threshold_)
513  {
514  is_a_seed = false;
515  }
516 
517  // check the residual if needed
518  data[0] = input_->points[nghbr].data[0];
519  data[1] = input_->points[nghbr].data[1];
520  data[2] = input_->points[nghbr].data[2];
521  data[3] = input_->points[nghbr].data[3];
522  Eigen::Map<Eigen::Vector3f> nghbr_point (static_cast<float*> (data));
523  float residual = fabsf (initial_normal.dot (initial_point - nghbr_point));
524  if (residual_flag_ && residual > residual_threshold_)
525  is_a_seed = false;
526 
527  return (true);
528 }
529 
530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
531 template <typename PointT, typename NormalT> void
533 {
534  int number_of_segments = static_cast<int> (num_pts_in_segment_.size ());
535  int number_of_points = static_cast<int> (input_->points.size ());
536 
537  pcl::PointIndices segment;
538  clusters_.resize (number_of_segments, segment);
539 
540  for (int i_seg = 0; i_seg < number_of_segments; i_seg++)
541  {
542  clusters_[i_seg].indices.resize ( num_pts_in_segment_[i_seg], 0);
543  }
544 
545  std::vector<int> counter;
546  counter.resize (number_of_segments, 0);
547 
548  for (int i_point = 0; i_point < number_of_points; i_point++)
549  {
550  int segment_index = point_labels_[i_point];
551  if (segment_index != -1)
552  {
553  int point_index = counter[segment_index];
554  clusters_[segment_index].indices[point_index] = i_point;
555  counter[segment_index] = point_index + 1;
556  }
557  }
558 
559  number_of_segments_ = number_of_segments;
560 }
561 
562 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
563 template <typename PointT, typename NormalT> void
565 {
566  cluster.indices.clear ();
567 
568  bool segmentation_is_possible = initCompute ();
569  if ( !segmentation_is_possible )
570  {
571  deinitCompute ();
572  return;
573  }
574 
575  // first of all we need to find out if this point belongs to cloud
576  bool point_was_found = false;
577  int number_of_points = static_cast <int> (indices_->size ());
578  for (size_t point = 0; point < number_of_points; point++)
579  if ( (*indices_)[point] == index)
580  {
581  point_was_found = true;
582  break;
583  }
584 
585  if (point_was_found)
586  {
587  if (clusters_.empty ())
588  {
589  point_neighbours_.clear ();
590  point_labels_.clear ();
591  num_pts_in_segment_.clear ();
592  number_of_segments_ = 0;
593 
594  segmentation_is_possible = prepareForSegmentation ();
595  if ( !segmentation_is_possible )
596  {
597  deinitCompute ();
598  return;
599  }
600 
601  findPointNeighbours ();
602  applySmoothRegionGrowingAlgorithm ();
603  assembleRegions ();
604  }
605  // if we have already made the segmentation, then find the segment
606  // to which this point belongs
607  std::vector <pcl::PointIndices>::iterator i_segment;
608  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
609  {
610  bool segment_was_found = false;
611  for (size_t i_point = 0; i_point < i_segment->indices.size (); i_point++)
612  {
613  if (i_segment->indices[i_point] == index)
614  {
615  segment_was_found = true;
616  cluster.indices.clear ();
617  cluster.indices.reserve (i_segment->indices.size ());
618  std::copy (i_segment->indices.begin (), i_segment->indices.end (), std::back_inserter (cluster.indices));
619  break;
620  }
621  }
622  if (segment_was_found)
623  {
624  break;
625  }
626  }// next segment
627  }// end if point was found
628 
629  deinitCompute ();
630 }
631 
632 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
633 template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
635 {
637 
638  if (!clusters_.empty ())
639  {
640  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
641 
642  srand (static_cast<unsigned int> (time (0)));
643  std::vector<unsigned char> colors;
644  for (size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
645  {
646  colors.push_back (static_cast<unsigned char> (rand () % 256));
647  colors.push_back (static_cast<unsigned char> (rand () % 256));
648  colors.push_back (static_cast<unsigned char> (rand () % 256));
649  }
650 
651  colored_cloud->width = input_->width;
652  colored_cloud->height = input_->height;
653  colored_cloud->is_dense = input_->is_dense;
654  for (size_t i_point = 0; i_point < input_->points.size (); i_point++)
655  {
656  pcl::PointXYZRGB point;
657  point.x = *(input_->points[i_point].data);
658  point.y = *(input_->points[i_point].data + 1);
659  point.z = *(input_->points[i_point].data + 2);
660  point.r = 255;
661  point.g = 0;
662  point.b = 0;
663  colored_cloud->points.push_back (point);
664  }
665 
666  std::vector< pcl::PointIndices >::iterator i_segment;
667  int next_color = 0;
668  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
669  {
670  std::vector<int>::iterator i_point;
671  for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
672  {
673  int index;
674  index = *i_point;
675  colored_cloud->points[index].r = colors[3 * next_color];
676  colored_cloud->points[index].g = colors[3 * next_color + 1];
677  colored_cloud->points[index].b = colors[3 * next_color + 2];
678  }
679  next_color++;
680  }
681  }
682 
683  return (colored_cloud);
684 }
685 
686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
687 template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
689 {
691 
692  if (!clusters_.empty ())
693  {
694  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGBA>)->makeShared ();
695 
696  srand (static_cast<unsigned int> (time (0)));
697  std::vector<unsigned char> colors;
698  for (size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
699  {
700  colors.push_back (static_cast<unsigned char> (rand () % 256));
701  colors.push_back (static_cast<unsigned char> (rand () % 256));
702  colors.push_back (static_cast<unsigned char> (rand () % 256));
703  }
704 
705  colored_cloud->width = input_->width;
706  colored_cloud->height = input_->height;
707  colored_cloud->is_dense = input_->is_dense;
708  for (size_t i_point = 0; i_point < input_->points.size (); i_point++)
709  {
710  pcl::PointXYZRGBA point;
711  point.x = *(input_->points[i_point].data);
712  point.y = *(input_->points[i_point].data + 1);
713  point.z = *(input_->points[i_point].data + 2);
714  point.r = 255;
715  point.g = 0;
716  point.b = 0;
717  point.a = 0;
718  colored_cloud->points.push_back (point);
719  }
720 
721  std::vector< pcl::PointIndices >::iterator i_segment;
722  int next_color = 0;
723  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
724  {
725  std::vector<int>::iterator i_point;
726  for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
727  {
728  int index;
729  index = *i_point;
730  colored_cloud->points[index].r = colors[3 * next_color];
731  colored_cloud->points[index].g = colors[3 * next_color + 1];
732  colored_cloud->points[index].b = colors[3 * next_color + 2];
733  }
734  next_color++;
735  }
736  }
737 
738  return (colored_cloud);
739 }
740 
741 #define PCL_INSTANTIATE_RegionGrowing(T) template class pcl::RegionGrowing<T, pcl::Normal>;
742 
743 #endif // PCL_SEGMENTATION_REGION_GROWING_HPP_
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
Definition: kdtree.h:62
float getResidualThreshold() const
Returns residual threshold.
void setSmoothModeFlag(bool value)
This function allows to turn on/off the smoothness constraint.
virtual bool prepareForSegmentation()
This method simply checks if it is possible to execute the segmentation algorithm with the current se...
void setMaxClusterSize(int max_cluster_size)
Set the maximum number of points that a cluster needs to contain in order to be considered valid...
boost::shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:428
void setMinClusterSize(int min_cluster_size)
Set the minimum number of points that a cluster needs to contain in order to be considered valid...
bool getSmoothModeFlag() const
Returns the flag value.
RegionGrowing()
Constructor that sets default values for member variables.
virtual void extract(std::vector< pcl::PointIndices > &clusters)
This method launches the segmentation algorithm and returns the clusters that were obtained during th...
int getMinClusterSize()
Get the minimum number of points that a cluster needs to contain in order to be considered valid...
virtual ~RegionGrowing()
This destructor destroys the cloud, normals and search method used for finding KNN.
void setCurvatureThreshold(float curvature)
Allows to set curvature threshold used for testing the points.
std::vector< int > indices
Definition: PointIndices.h:19
unsigned int getNumberOfNeighbours() const
Returns the number of nearest neighbours used for KNN.
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
int growRegion(int initial_seed, int segment_number)
This method grows a segment for the given seed point.
void setNumberOfNeighbours(unsigned int neighbour_number)
Allows to set the number of neighbours.
A point structure representing Euclidean xyz coordinates, and the RGBA color.
bool getCurvatureTestFlag() const
Returns the flag that signalize if the curvature test is turned on/off.
void setSmoothnessThreshold(float theta)
Allows to set smoothness threshold used for testing the points.
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
KdTree::Ptr KdTreePtr
bool comparePair(std::pair< float, int > i, std::pair< float, int > j)
This function is used as a comparator for sorting.
virtual void setResidualTestFlag(bool value)
Allows to turn on/off the residual test.
virtual void findPointNeighbours()
This method finds KNN for each point and saves them to the array because the algorithm needs to find ...
pcl::PointCloud< pcl::PointXYZRGB >::Ptr getColoredCloud()
If the cloud was successfully segmented, then function returns colored cloud.
void setInputNormals(const NormalPtr &norm)
This method sets the normals.
virtual void getSegmentFromPoint(int index, pcl::PointIndices &cluster)
For a given point this function builds a segment to which it belongs and returns this segment...
Normal::Ptr NormalPtr
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr getColoredCloudRGBA()
If the cloud was successfully segmented, then function returns colored cloud.
void applySmoothRegionGrowingAlgorithm()
This function implements the algorithm described in the article &quot;Segmentation of point clouds using s...
int getMaxClusterSize()
Get the maximum number of points that a cluster needs to contain in order to be considered valid...
NormalPtr getInputNormals() const
Returns normals.
void setResidualThreshold(float residual)
Allows to set residual threshold used for testing the points.
void assembleRegions()
This function simply assembles the regions from list of point labels.
KdTreePtr getSearchMethod() const
Returns the pointer to the search method that is used for KNN.
bool getResidualTestFlag() const
Returns the flag that signalize if the residual test is turned on/off.
float getSmoothnessThreshold() const
Returns smoothness threshold.
virtual void setCurvatureTestFlag(bool value)
Allows to turn on/off the curvature test.
float getCurvatureThreshold() const
Returns curvature threshold.
A point structure representing Euclidean xyz coordinates, and the RGB color.
virtual bool validatePoint(int initial_seed, int point, int nghbr, bool &is_a_seed) const
This function is checking if the point with index &#39;nghbr&#39; belongs to the segment. ...
void setSearchMethod(const KdTreePtr &tree)
Allows to set search method that will be used for finding KNN.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values).
Definition: point_cloud.h:418
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415