Point Cloud Library (PCL)  1.9.1
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 ((static_cast<int> (cluster_iter->indices.size ()) >= min_pts_per_cluster_) &&
293  (static_cast<int> (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  clusters.resize(clusters_.size());
302 
303  deinitCompute ();
304 }
305 
306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307 template <typename PointT, typename NormalT> bool
309 {
310  // if user forgot to pass point cloud or if it is empty
311  if ( input_->points.size () == 0 )
312  return (false);
313 
314  // if user forgot to pass normals or the sizes of point and normal cloud are different
315  if ( normals_ == 0 || input_->points.size () != normals_->points.size () )
316  return (false);
317 
318  // if residual test is on then we need to check if all needed parameters were correctly initialized
319  if (residual_flag_)
320  {
321  if (residual_threshold_ <= 0.0f)
322  return (false);
323  }
324 
325  // if curvature test is on ...
326  // if (curvature_flag_)
327  // {
328  // in this case we do not need to check anything that related to it
329  // so we simply commented it
330  // }
331 
332  // from here we check those parameters that are always valuable
333  if (neighbour_number_ == 0)
334  return (false);
335 
336  // if user didn't set search method
337  if (!search_)
338  search_.reset (new pcl::search::KdTree<PointT>);
339 
340  if (indices_)
341  {
342  if (indices_->empty ())
343  PCL_ERROR ("[pcl::RegionGrowing::prepareForSegmentation] Empty given indices!\n");
344  search_->setInputCloud (input_, indices_);
345  }
346  else
347  search_->setInputCloud (input_);
348 
349  return (true);
350 }
351 
352 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
353 template <typename PointT, typename NormalT> void
355 {
356  int point_number = static_cast<int> (indices_->size ());
357  std::vector<int> neighbours;
358  std::vector<float> distances;
359 
360  point_neighbours_.resize (input_->points.size (), neighbours);
361  if (input_->is_dense)
362  {
363  for (int i_point = 0; i_point < point_number; i_point++)
364  {
365  int point_index = (*indices_)[i_point];
366  neighbours.clear ();
367  search_->nearestKSearch (i_point, neighbour_number_, neighbours, distances);
368  point_neighbours_[point_index].swap (neighbours);
369  }
370  }
371  else
372  {
373  for (int i_point = 0; i_point < point_number; i_point++)
374  {
375  neighbours.clear ();
376  int point_index = (*indices_)[i_point];
377  if (!pcl::isFinite (input_->points[point_index]))
378  continue;
379  search_->nearestKSearch (i_point, neighbour_number_, neighbours, distances);
380  point_neighbours_[point_index].swap (neighbours);
381  }
382  }
383 }
384 
385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
386 template <typename PointT, typename NormalT> void
388 {
389  int num_of_pts = static_cast<int> (indices_->size ());
390  point_labels_.resize (input_->points.size (), -1);
391 
392  std::vector< std::pair<float, int> > point_residual;
393  std::pair<float, int> pair;
394  point_residual.resize (num_of_pts, pair);
395 
396  if (normal_flag_ == true)
397  {
398  for (int i_point = 0; i_point < num_of_pts; i_point++)
399  {
400  int point_index = (*indices_)[i_point];
401  point_residual[i_point].first = normals_->points[point_index].curvature;
402  point_residual[i_point].second = point_index;
403  }
404  std::sort (point_residual.begin (), point_residual.end (), comparePair);
405  }
406  else
407  {
408  for (int i_point = 0; i_point < num_of_pts; i_point++)
409  {
410  int point_index = (*indices_)[i_point];
411  point_residual[i_point].first = 0;
412  point_residual[i_point].second = point_index;
413  }
414  }
415  int seed_counter = 0;
416  int seed = point_residual[seed_counter].second;
417 
418  int segmented_pts_num = 0;
419  int number_of_segments = 0;
420  while (segmented_pts_num < num_of_pts)
421  {
422  int pts_in_segment;
423  pts_in_segment = growRegion (seed, number_of_segments);
424  segmented_pts_num += pts_in_segment;
425  num_pts_in_segment_.push_back (pts_in_segment);
426  number_of_segments++;
427 
428  //find next point that is not segmented yet
429  for (int i_seed = seed_counter + 1; i_seed < num_of_pts; i_seed++)
430  {
431  int index = point_residual[i_seed].second;
432  if (point_labels_[index] == -1)
433  {
434  seed = index;
435  seed_counter = i_seed;
436  break;
437  }
438  }
439  }
440 }
441 
442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
443 template <typename PointT, typename NormalT> int
444 pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
445 {
446  std::queue<int> seeds;
447  seeds.push (initial_seed);
448  point_labels_[initial_seed] = segment_number;
449 
450  int num_pts_in_segment = 1;
451 
452  while (!seeds.empty ())
453  {
454  int curr_seed;
455  curr_seed = seeds.front ();
456  seeds.pop ();
457 
458  size_t i_nghbr = 0;
459  while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
460  {
461  int index = point_neighbours_[curr_seed][i_nghbr];
462  if (point_labels_[index] != -1)
463  {
464  i_nghbr++;
465  continue;
466  }
467 
468  bool is_a_seed = false;
469  bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
470 
471  if (belongs_to_segment == false)
472  {
473  i_nghbr++;
474  continue;
475  }
476 
477  point_labels_[index] = segment_number;
478  num_pts_in_segment++;
479 
480  if (is_a_seed)
481  {
482  seeds.push (index);
483  }
484 
485  i_nghbr++;
486  }// next neighbour
487  }// next seed
488 
489  return (num_pts_in_segment);
490 }
491 
492 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
493 template <typename PointT, typename NormalT> bool
494 pcl::RegionGrowing<PointT, NormalT>::validatePoint (int initial_seed, int point, int nghbr, bool& is_a_seed) const
495 {
496  is_a_seed = true;
497 
498  float cosine_threshold = cosf (theta_threshold_);
499  float data[4];
500 
501  data[0] = input_->points[point].data[0];
502  data[1] = input_->points[point].data[1];
503  data[2] = input_->points[point].data[2];
504  data[3] = input_->points[point].data[3];
505  Eigen::Map<Eigen::Vector3f> initial_point (static_cast<float*> (data));
506  Eigen::Map<Eigen::Vector3f> initial_normal (static_cast<float*> (normals_->points[point].normal));
507 
508  //check the angle between normals
509  if (smooth_mode_flag_ == true)
510  {
511  Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> (normals_->points[nghbr].normal));
512  float dot_product = fabsf (nghbr_normal.dot (initial_normal));
513  if (dot_product < cosine_threshold)
514  {
515  return (false);
516  }
517  }
518  else
519  {
520  Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> (normals_->points[nghbr].normal));
521  Eigen::Map<Eigen::Vector3f> initial_seed_normal (static_cast<float*> (normals_->points[initial_seed].normal));
522  float dot_product = fabsf (nghbr_normal.dot (initial_seed_normal));
523  if (dot_product < cosine_threshold)
524  return (false);
525  }
526 
527  // check the curvature if needed
528  if (curvature_flag_ && normals_->points[nghbr].curvature > curvature_threshold_)
529  {
530  is_a_seed = false;
531  }
532 
533  // check the residual if needed
534  float data_1[4];
535 
536  data_1[0] = input_->points[nghbr].data[0];
537  data_1[1] = input_->points[nghbr].data[1];
538  data_1[2] = input_->points[nghbr].data[2];
539  data_1[3] = input_->points[nghbr].data[3];
540  Eigen::Map<Eigen::Vector3f> nghbr_point (static_cast<float*> (data_1));
541  float residual = fabsf (initial_normal.dot (initial_point - nghbr_point));
542  if (residual_flag_ && residual > residual_threshold_)
543  is_a_seed = false;
544 
545  return (true);
546 }
547 
548 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
549 template <typename PointT, typename NormalT> void
551 {
552  int number_of_segments = static_cast<int> (num_pts_in_segment_.size ());
553  int number_of_points = static_cast<int> (input_->points.size ());
554 
555  pcl::PointIndices segment;
556  clusters_.resize (number_of_segments, segment);
557 
558  for (int i_seg = 0; i_seg < number_of_segments; i_seg++)
559  {
560  clusters_[i_seg].indices.resize ( num_pts_in_segment_[i_seg], 0);
561  }
562 
563  std::vector<int> counter;
564  counter.resize (number_of_segments, 0);
565 
566  for (int i_point = 0; i_point < number_of_points; i_point++)
567  {
568  int segment_index = point_labels_[i_point];
569  if (segment_index != -1)
570  {
571  int point_index = counter[segment_index];
572  clusters_[segment_index].indices[point_index] = i_point;
573  counter[segment_index] = point_index + 1;
574  }
575  }
576 
577  number_of_segments_ = number_of_segments;
578 }
579 
580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
581 template <typename PointT, typename NormalT> void
583 {
584  cluster.indices.clear ();
585 
586  bool segmentation_is_possible = initCompute ();
587  if ( !segmentation_is_possible )
588  {
589  deinitCompute ();
590  return;
591  }
592 
593  // first of all we need to find out if this point belongs to cloud
594  bool point_was_found = false;
595  int number_of_points = static_cast <int> (indices_->size ());
596  for (int point = 0; point < number_of_points; point++)
597  if ( (*indices_)[point] == index)
598  {
599  point_was_found = true;
600  break;
601  }
602 
603  if (point_was_found)
604  {
605  if (clusters_.empty ())
606  {
607  point_neighbours_.clear ();
608  point_labels_.clear ();
609  num_pts_in_segment_.clear ();
610  number_of_segments_ = 0;
611 
612  segmentation_is_possible = prepareForSegmentation ();
613  if ( !segmentation_is_possible )
614  {
615  deinitCompute ();
616  return;
617  }
618 
619  findPointNeighbours ();
620  applySmoothRegionGrowingAlgorithm ();
621  assembleRegions ();
622  }
623  // if we have already made the segmentation, then find the segment
624  // to which this point belongs
625  std::vector <pcl::PointIndices>::iterator i_segment;
626  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
627  {
628  bool segment_was_found = false;
629  for (size_t i_point = 0; i_point < i_segment->indices.size (); i_point++)
630  {
631  if (i_segment->indices[i_point] == index)
632  {
633  segment_was_found = true;
634  cluster.indices.clear ();
635  cluster.indices.reserve (i_segment->indices.size ());
636  std::copy (i_segment->indices.begin (), i_segment->indices.end (), std::back_inserter (cluster.indices));
637  break;
638  }
639  }
640  if (segment_was_found)
641  {
642  break;
643  }
644  }// next segment
645  }// end if point was found
646 
647  deinitCompute ();
648 }
649 
650 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
651 template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
653 {
655 
656  if (!clusters_.empty ())
657  {
658  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
659 
660  srand (static_cast<unsigned int> (time (0)));
661  std::vector<unsigned char> colors;
662  for (size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
663  {
664  colors.push_back (static_cast<unsigned char> (rand () % 256));
665  colors.push_back (static_cast<unsigned char> (rand () % 256));
666  colors.push_back (static_cast<unsigned char> (rand () % 256));
667  }
668 
669  colored_cloud->width = input_->width;
670  colored_cloud->height = input_->height;
671  colored_cloud->is_dense = input_->is_dense;
672  for (size_t i_point = 0; i_point < input_->points.size (); i_point++)
673  {
674  pcl::PointXYZRGB point;
675  point.x = *(input_->points[i_point].data);
676  point.y = *(input_->points[i_point].data + 1);
677  point.z = *(input_->points[i_point].data + 2);
678  point.r = 255;
679  point.g = 0;
680  point.b = 0;
681  colored_cloud->points.push_back (point);
682  }
683 
684  std::vector< pcl::PointIndices >::iterator i_segment;
685  int next_color = 0;
686  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
687  {
688  std::vector<int>::iterator i_point;
689  for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
690  {
691  int index;
692  index = *i_point;
693  colored_cloud->points[index].r = colors[3 * next_color];
694  colored_cloud->points[index].g = colors[3 * next_color + 1];
695  colored_cloud->points[index].b = colors[3 * next_color + 2];
696  }
697  next_color++;
698  }
699  }
700 
701  return (colored_cloud);
702 }
703 
704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
705 template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
707 {
709 
710  if (!clusters_.empty ())
711  {
712  colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGBA>)->makeShared ();
713 
714  srand (static_cast<unsigned int> (time (0)));
715  std::vector<unsigned char> colors;
716  for (size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
717  {
718  colors.push_back (static_cast<unsigned char> (rand () % 256));
719  colors.push_back (static_cast<unsigned char> (rand () % 256));
720  colors.push_back (static_cast<unsigned char> (rand () % 256));
721  }
722 
723  colored_cloud->width = input_->width;
724  colored_cloud->height = input_->height;
725  colored_cloud->is_dense = input_->is_dense;
726  for (size_t i_point = 0; i_point < input_->points.size (); i_point++)
727  {
728  pcl::PointXYZRGBA point;
729  point.x = *(input_->points[i_point].data);
730  point.y = *(input_->points[i_point].data + 1);
731  point.z = *(input_->points[i_point].data + 2);
732  point.r = 255;
733  point.g = 0;
734  point.b = 0;
735  point.a = 0;
736  colored_cloud->points.push_back (point);
737  }
738 
739  std::vector< pcl::PointIndices >::iterator i_segment;
740  int next_color = 0;
741  for (i_segment = clusters_.begin (); i_segment != clusters_.end (); i_segment++)
742  {
743  std::vector<int>::iterator i_point;
744  for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
745  {
746  int index;
747  index = *i_point;
748  colored_cloud->points[index].r = colors[3 * next_color];
749  colored_cloud->points[index].g = colors[3 * next_color + 1];
750  colored_cloud->points[index].b = colors[3 * next_color + 2];
751  }
752  next_color++;
753  }
754  }
755 
756  return (colored_cloud);
757 }
758 
759 #define PCL_INSTANTIATE_RegionGrowing(T) template class pcl::RegionGrowing<T, pcl::Normal>;
760 
761 #endif // PCL_SEGMENTATION_REGION_GROWING_HPP_
pcl::RegionGrowing::getNumberOfNeighbours
unsigned int getNumberOfNeighbours() const
Returns the number of nearest neighbours used for KNN.
Definition: region_growing.hpp:213
pcl::RegionGrowing::getMaxClusterSize
int getMaxClusterSize()
Get the maximum number of points that a cluster needs to contain in order to be considered valid.
Definition: region_growing.hpp:109
pcl::PointCloud::width
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
point_types.h
pcl::PointCloud::Ptr
boost::shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:428
pcl::PointCloud::points
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
pcl::isFinite
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...
Definition: point_tests.h:54
pcl::RegionGrowing::setCurvatureTestFlag
virtual void setCurvatureTestFlag(bool value)
Allows to turn on/off the curvature test.
Definition: region_growing.hpp:144
pcl::RegionGrowing::extract
virtual void extract(std::vector< pcl::PointIndices > &clusters)
This method launches the segmentation algorithm and returns the clusters that were obtained during th...
Definition: region_growing.hpp:261
pcl::RegionGrowing::applySmoothRegionGrowingAlgorithm
void applySmoothRegionGrowingAlgorithm()
This function implements the algorithm described in the article "Segmentation of point clouds using s...
Definition: region_growing.hpp:387
pcl::RegionGrowing::setResidualThreshold
void setResidualThreshold(float residual)
Allows to set residual threshold used for testing the points.
Definition: region_growing.hpp:192
pcl::RegionGrowing::setNumberOfNeighbours
void setNumberOfNeighbours(unsigned int neighbour_number)
Allows to set the number of neighbours.
Definition: region_growing.hpp:220
pcl::RegionGrowing::prepareForSegmentation
virtual bool prepareForSegmentation()
This method simply checks if it is possible to execute the segmentation algorithm with the current se...
Definition: region_growing.hpp:308
pcl::RegionGrowing::setSmoothnessThreshold
void setSmoothnessThreshold(float theta)
Allows to set smoothness threshold used for testing the points.
Definition: region_growing.hpp:178
pcl::PointCloud< pcl::PointXYZRGB >
pcl::PointXYZRGB
A point structure representing Euclidean xyz coordinates, and the RGB color.
Definition: point_types.hpp:619
pcl::RegionGrowing::~RegionGrowing
virtual ~RegionGrowing()
This destructor destroys the cloud, normals and search method used for finding KNN.
Definition: region_growing.hpp:80
pcl::RegionGrowing::growRegion
int growRegion(int initial_seed, int segment_number)
This method grows a segment for the given seed point.
Definition: region_growing.hpp:444
pcl::RegionGrowing::getColoredCloud
pcl::PointCloud< pcl::PointXYZRGB >::Ptr getColoredCloud()
If the cloud was successfully segmented, then function returns colored cloud.
Definition: region_growing.hpp:652
pcl::RegionGrowing::getCurvatureThreshold
float getCurvatureThreshold() const
Returns curvature threshold.
Definition: region_growing.hpp:199
pcl::PointXYZRGBA
A point structure representing Euclidean xyz coordinates, and the RGBA color.
Definition: point_types.hpp:552
pcl::RegionGrowing::setResidualTestFlag
virtual void setResidualTestFlag(bool value)
Allows to turn on/off the residual test.
Definition: region_growing.hpp:161
pcl::RegionGrowing::RegionGrowing
RegionGrowing()
Constructor that sets default values for member variables.
Definition: region_growing.hpp:57
pcl::RegionGrowing::getSearchMethod
KdTreePtr getSearchMethod() const
Returns the pointer to the search method that is used for KNN.
Definition: region_growing.hpp:227
pcl::RegionGrowing::getResidualThreshold
float getResidualThreshold() const
Returns residual threshold.
Definition: region_growing.hpp:185
pcl::comparePair
bool comparePair(std::pair< float, int > i, std::pair< float, int > j)
This function is used as a comparator for sorting.
Definition: region_growing.h:341
pcl::RegionGrowing::setMaxClusterSize
void setMaxClusterSize(int max_cluster_size)
Set the maximum number of points that a cluster needs to contain in order to be considered valid.
Definition: region_growing.hpp:116
pcl::search::KdTree< PointT >
pcl::RegionGrowing::KdTreePtr
KdTree::Ptr KdTreePtr
Definition: region_growing.h:66
pcl::RegionGrowing::assembleRegions
void assembleRegions()
This function simply assembles the regions from list of point labels.
Definition: region_growing.hpp:550
pcl::PointIndices::indices
std::vector< int > indices
Definition: PointIndices.h:19
pcl::PointCloud::height
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415
pcl::PointCloud::is_dense
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:418
pcl::RegionGrowing::NormalPtr
Normal::Ptr NormalPtr
Definition: region_growing.h:68
pcl::PointIndices
Definition: PointIndices.h:12
pcl::RegionGrowing::getCurvatureTestFlag
bool getCurvatureTestFlag() const
Returns the flag that signalize if the curvature test is turned on/off.
Definition: region_growing.hpp:137
pcl::RegionGrowing::setInputNormals
void setInputNormals(const NormalPtr &norm)
This method sets the normals.
Definition: region_growing.hpp:251
pcl::RegionGrowing::getSmoothnessThreshold
float getSmoothnessThreshold() const
Returns smoothness threshold.
Definition: region_growing.hpp:171
pcl::RegionGrowing::setSmoothModeFlag
void setSmoothModeFlag(bool value)
This function allows to turn on/off the smoothness constraint.
Definition: region_growing.hpp:130
pcl::RegionGrowing::getInputNormals
NormalPtr getInputNormals() const
Returns normals.
Definition: region_growing.hpp:244
pcl::RegionGrowing::validatePoint
virtual bool validatePoint(int initial_seed, int point, int nghbr, bool &is_a_seed) const
This function is checking if the point with index 'nghbr' belongs to the segment.
Definition: region_growing.hpp:494
pcl::RegionGrowing::findPointNeighbours
virtual void findPointNeighbours()
This method finds KNN for each point and saves them to the array because the algorithm needs to find ...
Definition: region_growing.hpp:354
std
Definition: multi_grid_octree_data.hpp:45
pcl::RegionGrowing::setSearchMethod
void setSearchMethod(const KdTreePtr &tree)
Allows to set search method that will be used for finding KNN.
Definition: region_growing.hpp:234
pcl::RegionGrowing::setCurvatureThreshold
void setCurvatureThreshold(float curvature)
Allows to set curvature threshold used for testing the points.
Definition: region_growing.hpp:206
pcl::RegionGrowing::getColoredCloudRGBA
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr getColoredCloudRGBA()
If the cloud was successfully segmented, then function returns colored cloud.
Definition: region_growing.hpp:706
pcl::RegionGrowing::getResidualTestFlag
bool getResidualTestFlag() const
Returns the flag that signalize if the residual test is turned on/off.
Definition: region_growing.hpp:154
pcl::RegionGrowing::getSmoothModeFlag
bool getSmoothModeFlag() const
Returns the flag value.
Definition: region_growing.hpp:123
pcl::RegionGrowing::setMinClusterSize
void setMinClusterSize(int min_cluster_size)
Set the minimum number of points that a cluster needs to contain in order to be considered valid.
Definition: region_growing.hpp:102
pcl::RegionGrowing::getSegmentFromPoint
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.
Definition: region_growing.hpp:582
pcl::RegionGrowing::getMinClusterSize
int getMinClusterSize()
Get the minimum number of points that a cluster needs to contain in order to be considered valid.
Definition: region_growing.hpp:95