Point Cloud Library (PCL) 1.15.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
59//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60template <typename PointT, typename NormalT>
62{
63 point_neighbours_.clear ();
64 point_labels_.clear ();
65 num_pts_in_segment_.clear ();
66 clusters_.clear ();
67}
68
69//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70template <typename PointT, typename NormalT> pcl::uindex_t
72{
73 return (min_pts_per_cluster_);
74}
75
76//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77template <typename PointT, typename NormalT> void
79{
80 min_pts_per_cluster_ = min_cluster_size;
81}
82
83//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84template <typename PointT, typename NormalT> pcl::uindex_t
86{
87 return (max_pts_per_cluster_);
89
90//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91template <typename PointT, typename NormalT> void
93{
94 max_pts_per_cluster_ = max_cluster_size;
95}
97//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98template <typename PointT, typename NormalT> bool
101 return (smooth_mode_flag_);
102}
103
104//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105template <typename PointT, typename NormalT> void
107{
108 smooth_mode_flag_ = value;
110
111//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112template <typename PointT, typename NormalT> bool
114{
115 return (curvature_flag_);
116}
117
118//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119template <typename PointT, typename NormalT> void
121{
122 curvature_flag_ = value;
123
124 if (!curvature_flag_ && !residual_flag_)
125 residual_flag_ = true;
126}
128//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129template <typename PointT, typename NormalT> bool
132 return (residual_flag_);
133}
134
135//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136template <typename PointT, typename NormalT> void
138{
139 residual_flag_ = value;
141 if (!curvature_flag_ && !residual_flag_)
142 curvature_flag_ = true;
143}
145//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146template <typename PointT, typename NormalT> float
148{
149 return (theta_threshold_);
151
152//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153template <typename PointT, typename NormalT> void
155{
156 theta_threshold_ = theta;
157}
158
159//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
160template <typename PointT, typename NormalT> float
162{
163 return (residual_threshold_);
165
166//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
167template <typename PointT, typename NormalT> void
169{
170 residual_threshold_ = residual;
171}
172
173//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
174template <typename PointT, typename NormalT> float
176{
177 return (curvature_threshold_);
178}
179
180//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181template <typename PointT, typename NormalT> void
183{
184 curvature_threshold_ = curvature;
185}
186
187//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
188template <typename PointT, typename NormalT> unsigned int
191 return (neighbour_number_);
192}
193
194//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
195template <typename PointT, typename NormalT> void
197{
198 neighbour_number_ = neighbour_number;
199}
200
201//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
202template <typename PointT, typename NormalT> typename pcl::RegionGrowing<PointT, NormalT>::KdTreePtr
204{
205 return (search_);
206}
207
208//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209template <typename PointT, typename NormalT> void
211{
212 search_ = tree;
213}
214
215//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
216template <typename PointT, typename NormalT> typename pcl::RegionGrowing<PointT, NormalT>::NormalPtr
218{
219 return (normals_);
220}
221
222//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223template <typename PointT, typename NormalT> void
225{
226 normals_ = norm;
227}
228
229//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
230template <typename PointT, typename NormalT> void
231pcl::RegionGrowing<PointT, NormalT>::extract (std::vector <pcl::PointIndices>& clusters)
232{
233 clusters_.clear ();
234 clusters.clear ();
235 point_neighbours_.clear ();
236 point_labels_.clear ();
237 num_pts_in_segment_.clear ();
238 number_of_segments_ = 0;
239
240 bool segmentation_is_possible = initCompute ();
241 if ( !segmentation_is_possible )
242 {
243 deinitCompute ();
244 return;
245 }
246
247 segmentation_is_possible = prepareForSegmentation ();
248 if ( !segmentation_is_possible )
249 {
250 deinitCompute ();
251 return;
252 }
253
254 findPointNeighbours ();
255 applySmoothRegionGrowingAlgorithm ();
256 assembleRegions ();
257
258 clusters.resize (clusters_.size ());
259 auto cluster_iter_input = clusters.begin ();
260 for (const auto& cluster : clusters_)
262 if ((cluster.indices.size () >= min_pts_per_cluster_) &&
263 (cluster.indices.size () <= max_pts_per_cluster_))
264 {
265 *cluster_iter_input = cluster;
266 ++cluster_iter_input;
267 }
268 }
269
270 clusters_ = std::vector<pcl::PointIndices> (clusters.begin (), cluster_iter_input);
271 clusters.resize(clusters_.size());
272
273 deinitCompute ();
274}
275
276//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
277template <typename PointT, typename NormalT> bool
279{
280 // if user forgot to pass point cloud or if it is empty
281 if ( input_->points.empty () )
282 return (false);
283
284 // if user forgot to pass normals or the sizes of point and normal cloud are different
285 if ( !normals_ || input_->size () != normals_->size () )
286 return (false);
287
288 // if residual test is on then we need to check if all needed parameters were correctly initialized
289 if (residual_flag_)
290 {
291 if (residual_threshold_ <= 0.0f)
292 return (false);
293 }
294
295 // if curvature test is on ...
296 // if (curvature_flag_)
297 // {
298 // in this case we do not need to check anything that related to it
299 // so we simply commented it
300 // }
301
302 // from here we check those parameters that are always valuable
303 if (neighbour_number_ == 0)
304 return (false);
305
306 // if user didn't set search method
307 if (!search_)
308 search_.reset (new pcl::search::KdTree<PointT>);
309
310 if (indices_)
311 {
312 if (indices_->empty ())
313 PCL_ERROR ("[pcl::RegionGrowing::prepareForSegmentation] Empty given indices!\n");
314 search_->setInputCloud (input_, indices_);
315 }
316 else
317 search_->setInputCloud (input_);
318
319 return (true);
320}
321
322//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
323template <typename PointT, typename NormalT> void
325{
326 pcl::Indices neighbours;
327 std::vector<float> distances;
328
329 point_neighbours_.resize (input_->size (), neighbours);
330 if (input_->is_dense)
331 {
332 for (const auto& point_index: (*indices_))
333 {
334 neighbours.clear ();
335 search_->nearestKSearch (point_index, neighbour_number_, neighbours, distances);
336 point_neighbours_[point_index].swap (neighbours);
337 }
338 }
339 else
340 {
341 for (const auto& point_index: (*indices_))
342 {
343 if (!pcl::isFinite ((*input_)[point_index]))
344 continue;
345 neighbours.clear ();
346 search_->nearestKSearch (point_index, neighbour_number_, neighbours, distances);
347 point_neighbours_[point_index].swap (neighbours);
348 }
349 }
350}
351
352//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
353template <typename PointT, typename NormalT> void
355{
356 int num_of_pts = static_cast<int> (indices_->size ());
357 point_labels_.resize (input_->size (), -1);
358
359 std::vector< std::pair<float, int> > point_residual;
360 std::pair<float, int> pair;
361 point_residual.resize (num_of_pts, pair);
362
363 if (normal_flag_)
364 {
365 for (int i_point = 0; i_point < num_of_pts; i_point++)
366 {
367 const auto point_index = (*indices_)[i_point];
368 point_residual[i_point].first = (*normals_)[point_index].curvature;
369 point_residual[i_point].second = point_index;
370 }
371 std::sort (point_residual.begin (), point_residual.end (), comparePair);
372 }
373 else
374 {
375 for (int i_point = 0; i_point < num_of_pts; i_point++)
376 {
377 const auto point_index = (*indices_)[i_point];
378 point_residual[i_point].first = 0;
379 point_residual[i_point].second = point_index;
380 }
381 }
382 int seed_counter = 0;
383 int seed = point_residual[seed_counter].second;
384
385 int segmented_pts_num = 0;
386 int number_of_segments = 0;
387 while (segmented_pts_num < num_of_pts)
388 {
389 int pts_in_segment;
390 pts_in_segment = growRegion (seed, number_of_segments);
391 segmented_pts_num += pts_in_segment;
392 num_pts_in_segment_.push_back (pts_in_segment);
393 number_of_segments++;
394
395 //find next point that is not segmented yet
396 for (int i_seed = seed_counter + 1; i_seed < num_of_pts; i_seed++)
397 {
398 int index = point_residual[i_seed].second;
399 if (point_labels_[index] == -1)
400 {
401 seed = index;
402 seed_counter = i_seed;
403 break;
404 }
405 }
406 }
407}
408
409//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
410template <typename PointT, typename NormalT> int
411pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
412{
413 std::queue<int> seeds;
414 seeds.push (initial_seed);
415 point_labels_[initial_seed] = segment_number;
416
417 int num_pts_in_segment = 1;
418
419 while (!seeds.empty ())
420 {
421 int curr_seed;
422 curr_seed = seeds.front ();
423 seeds.pop ();
424
425 std::size_t i_nghbr = 0;
426 while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
427 {
428 int index = point_neighbours_[curr_seed][i_nghbr];
429 if (point_labels_[index] != -1)
430 {
431 i_nghbr++;
432 continue;
433 }
434
435 bool is_a_seed = false;
436 bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
437
438 if (!belongs_to_segment)
439 {
440 i_nghbr++;
441 continue;
442 }
443
444 point_labels_[index] = segment_number;
445 num_pts_in_segment++;
446
447 if (is_a_seed)
448 {
449 seeds.push (index);
450 }
451
452 i_nghbr++;
453 }// next neighbour
454 }// next seed
455
456 return (num_pts_in_segment);
457}
458
459//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
460template <typename PointT, typename NormalT> bool
462{
463 is_a_seed = true;
464
465 float cosine_threshold = std::cos (theta_threshold_);
466 float data[4];
467
468 data[0] = (*input_)[point].data[0];
469 data[1] = (*input_)[point].data[1];
470 data[2] = (*input_)[point].data[2];
471 data[3] = (*input_)[point].data[3];
472 Eigen::Map<Eigen::Vector3f> initial_point (static_cast<float*> (data));
473 Eigen::Map<Eigen::Vector3f> initial_normal (static_cast<float*> ((*normals_)[point].normal));
474
475 //check the angle between normals
476 if (smooth_mode_flag_)
477 {
478 Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> ((*normals_)[nghbr].normal));
479 float dot_product = std::abs (nghbr_normal.dot (initial_normal));
480 if (dot_product < cosine_threshold)
481 {
482 return (false);
483 }
484 }
485 else
486 {
487 Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> ((*normals_)[nghbr].normal));
488 Eigen::Map<Eigen::Vector3f> initial_seed_normal (static_cast<float*> ((*normals_)[initial_seed].normal));
489 float dot_product = std::abs (nghbr_normal.dot (initial_seed_normal));
490 if (dot_product < cosine_threshold)
491 return (false);
492 }
493
494 // check the curvature if needed
495 if (curvature_flag_ && (*normals_)[nghbr].curvature > curvature_threshold_)
496 {
497 is_a_seed = false;
498 }
499
500 // check the residual if needed
501 float data_1[4];
502
503 data_1[0] = (*input_)[nghbr].data[0];
504 data_1[1] = (*input_)[nghbr].data[1];
505 data_1[2] = (*input_)[nghbr].data[2];
506 data_1[3] = (*input_)[nghbr].data[3];
507 Eigen::Map<Eigen::Vector3f> nghbr_point (static_cast<float*> (data_1));
508 float residual = std::abs (initial_normal.dot (initial_point - nghbr_point));
509 if (residual_flag_ && residual > residual_threshold_)
510 is_a_seed = false;
511
512 return (true);
513}
514
515//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
516template <typename PointT, typename NormalT> void
518{
519 const auto number_of_segments = num_pts_in_segment_.size ();
520 const auto number_of_points = input_->size ();
521
522 pcl::PointIndices segment;
523 clusters_.resize (number_of_segments, segment);
524
525 for (std::size_t i_seg = 0; i_seg < number_of_segments; i_seg++)
526 {
527 clusters_[i_seg].indices.resize ( num_pts_in_segment_[i_seg], 0);
528 }
529
530 std::vector<int> counter(number_of_segments, 0);
531
532 for (std::size_t i_point = 0; i_point < number_of_points; i_point++)
533 {
534 const auto segment_index = point_labels_[i_point];
535 if (segment_index != -1)
536 {
537 const auto point_index = counter[segment_index];
538 clusters_[segment_index].indices[point_index] = i_point;
539 counter[segment_index] = point_index + 1;
540 }
541 }
542
543 number_of_segments_ = number_of_segments;
544}
545
546//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
547template <typename PointT, typename NormalT> void
549{
550 cluster.indices.clear ();
551
552 bool segmentation_is_possible = initCompute ();
553 if ( !segmentation_is_possible )
554 {
555 deinitCompute ();
556 return;
557 }
558
559 // first of all we need to find out if this point belongs to cloud
560 bool point_was_found = false;
561 for (const auto& point : (*indices_))
562 if (point == index)
563 {
564 point_was_found = true;
565 break;
566 }
567
568 if (point_was_found)
569 {
570 if (clusters_.empty ())
571 {
572 point_neighbours_.clear ();
573 point_labels_.clear ();
574 num_pts_in_segment_.clear ();
575 number_of_segments_ = 0;
576
577 segmentation_is_possible = prepareForSegmentation ();
578 if ( !segmentation_is_possible )
579 {
580 deinitCompute ();
581 return;
582 }
583
584 findPointNeighbours ();
585 applySmoothRegionGrowingAlgorithm ();
586 assembleRegions ();
587 }
588 // if we have already made the segmentation, then find the segment
589 // to which this point belongs
590 for (const auto& i_segment : clusters_)
591 {
592 const auto it = std::find (i_segment.indices.cbegin (), i_segment.indices.cend (), index);
593 if (it != i_segment.indices.cend())
594 {
595 // if segment was found
596 cluster.indices.clear ();
597 cluster.indices.reserve (i_segment.indices.size ());
598 std::copy (i_segment.indices.begin (), i_segment.indices.end (), std::back_inserter (cluster.indices));
599 break;
600 }
601 }// next segment
602 }// end if point was found
603
604 deinitCompute ();
605}
606
607//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
608template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
610{
612
613 if (!clusters_.empty ())
614 {
615 colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
616
617 srand (static_cast<unsigned int> (time (nullptr)));
618 std::vector<unsigned char> colors;
619 for (std::size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
620 {
621 colors.push_back (static_cast<unsigned char> (rand () % 256));
622 colors.push_back (static_cast<unsigned char> (rand () % 256));
623 colors.push_back (static_cast<unsigned char> (rand () % 256));
624 }
625
626 colored_cloud->width = input_->width;
627 colored_cloud->height = input_->height;
628 colored_cloud->is_dense = input_->is_dense;
629 for (const auto& i_point: *input_)
630 {
631 pcl::PointXYZRGB point;
632 point.x = *(i_point.data);
633 point.y = *(i_point.data + 1);
634 point.z = *(i_point.data + 2);
635 point.r = 255;
636 point.g = 0;
637 point.b = 0;
638 colored_cloud->points.push_back (point);
639 }
640
641 int next_color = 0;
642 for (const auto& i_segment : clusters_)
643 {
644 for (const auto& index : (i_segment.indices))
645 {
646 (*colored_cloud)[index].r = colors[3 * next_color];
647 (*colored_cloud)[index].g = colors[3 * next_color + 1];
648 (*colored_cloud)[index].b = colors[3 * next_color + 2];
649 }
650 next_color++;
651 }
652 }
653
654 return (colored_cloud);
655}
656
657//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
658template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
660{
662
663 if (!clusters_.empty ())
664 {
665 colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGBA>);
666
667 srand (static_cast<unsigned int> (time (nullptr)));
668 std::vector<unsigned char> colors;
669 for (std::size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
670 {
671 colors.push_back (static_cast<unsigned char> (rand () % 256));
672 colors.push_back (static_cast<unsigned char> (rand () % 256));
673 colors.push_back (static_cast<unsigned char> (rand () % 256));
674 }
675
676 colored_cloud->width = input_->width;
677 colored_cloud->height = input_->height;
678 colored_cloud->is_dense = input_->is_dense;
679 for (const auto& i_point: *input_)
680 {
681 pcl::PointXYZRGBA point;
682 point.x = *(i_point.data);
683 point.y = *(i_point.data + 1);
684 point.z = *(i_point.data + 2);
685 point.r = 255;
686 point.g = 0;
687 point.b = 0;
688 point.a = 0;
689 colored_cloud->points.push_back (point);
690 }
691
692 int next_color = 0;
693 for (const auto& i_segment : clusters_)
694 {
695 for (const auto& index : (i_segment.indices))
696 {
697 (*colored_cloud)[index].r = colors[3 * next_color];
698 (*colored_cloud)[index].g = colors[3 * next_color + 1];
699 (*colored_cloud)[index].b = colors[3 * next_color + 2];
700 }
701 next_color++;
702 }
703 }
704
705 return (colored_cloud);
706}
707
708#define PCL_INSTANTIATE_RegionGrowing(T) template class PCL_EXPORTS pcl::RegionGrowing<T, pcl::Normal>;
709
PointCloud represents the base class in PCL for storing collections of 3D points.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
std::uint32_t width
The point cloud width (if organized as an image-structure).
std::uint32_t height
The point cloud height (if organized as an image-structure).
shared_ptr< PointCloud< PointT > > Ptr
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
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.
~RegionGrowing() override
This destructor destroys the cloud, normals and search method used for finding KNN.
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.
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.
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
Definition types.h:120
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
A point structure representing Euclidean xyz coordinates, and the RGBA color.
A point structure representing Euclidean xyz coordinates, and the RGB color.