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