Point Cloud Library (PCL) 1.15.1-dev
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/auto.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 (indices_)
307 {
308 if (indices_->empty ())
309 PCL_ERROR ("[pcl::RegionGrowing::prepareForSegmentation] Empty given indices!\n");
310 if (!search_)
311 search_.reset (pcl::search::autoSelectMethod<PointT>(input_, indices_, true, pcl::search::Purpose::many_knn_search));
312 else
313 search_->setInputCloud (input_, indices_);
314 }
315 else
316 {
317 if (!search_)
318 search_.reset (pcl::search::autoSelectMethod<PointT>(input_, true, pcl::search::Purpose::many_knn_search));
319 else
320 search_->setInputCloud (input_);
321 }
322
323 return (true);
324}
325
326//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
327template <typename PointT, typename NormalT> void
329{
330 pcl::Indices neighbours;
331 std::vector<float> distances;
332
333 point_neighbours_.resize (input_->size (), neighbours);
334 if (input_->is_dense)
335 {
336 for (const auto& point_index: (*indices_))
337 {
338 neighbours.clear ();
339 search_->nearestKSearch ((*input_)[point_index], neighbour_number_, neighbours, distances);
340 point_neighbours_[point_index].swap (neighbours);
341 }
342 }
343 else
344 {
345 for (const auto& point_index: (*indices_))
346 {
347 if (!pcl::isFinite ((*input_)[point_index]))
348 continue;
349 neighbours.clear ();
350 search_->nearestKSearch ((*input_)[point_index], neighbour_number_, neighbours, distances);
351 point_neighbours_[point_index].swap (neighbours);
352 }
353 }
354}
355
356//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
357template <typename PointT, typename NormalT> void
359{
360 int num_of_pts = static_cast<int> (indices_->size ());
361 point_labels_.resize (input_->size (), -1);
362
363 std::vector< std::pair<float, int> > point_residual;
364 std::pair<float, int> pair;
365 point_residual.resize (num_of_pts, pair);
366
367 if (normal_flag_)
368 {
369 for (int i_point = 0; i_point < num_of_pts; i_point++)
370 {
371 const auto point_index = (*indices_)[i_point];
372 point_residual[i_point].first = (*normals_)[point_index].curvature;
373 point_residual[i_point].second = point_index;
374 }
375 std::sort (point_residual.begin (), point_residual.end (), comparePair);
376 }
377 else
378 {
379 for (int i_point = 0; i_point < num_of_pts; i_point++)
380 {
381 const auto point_index = (*indices_)[i_point];
382 point_residual[i_point].first = 0;
383 point_residual[i_point].second = point_index;
384 }
385 }
386 int seed_counter = 0;
387 int seed = point_residual[seed_counter].second;
388
389 int segmented_pts_num = 0;
390 int number_of_segments = 0;
391 while (segmented_pts_num < num_of_pts)
392 {
393 int pts_in_segment;
394 pts_in_segment = growRegion (seed, number_of_segments);
395 segmented_pts_num += pts_in_segment;
396 num_pts_in_segment_.push_back (pts_in_segment);
397 number_of_segments++;
398
399 //find next point that is not segmented yet
400 for (int i_seed = seed_counter + 1; i_seed < num_of_pts; i_seed++)
401 {
402 int index = point_residual[i_seed].second;
403 if (point_labels_[index] == -1)
404 {
405 seed = index;
406 seed_counter = i_seed;
407 break;
408 }
409 }
410 }
411}
412
413//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
414template <typename PointT, typename NormalT> int
415pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
416{
417 std::queue<int> seeds;
418 seeds.push (initial_seed);
419 point_labels_[initial_seed] = segment_number;
420
421 int num_pts_in_segment = 1;
422
423 while (!seeds.empty ())
424 {
425 int curr_seed;
426 curr_seed = seeds.front ();
427 seeds.pop ();
428
429 std::size_t i_nghbr = 0;
430 while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
431 {
432 int index = point_neighbours_[curr_seed][i_nghbr];
433 if (point_labels_[index] != -1)
434 {
435 i_nghbr++;
436 continue;
437 }
438
439 bool is_a_seed = false;
440 bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
441
442 if (!belongs_to_segment)
443 {
444 i_nghbr++;
445 continue;
446 }
447
448 point_labels_[index] = segment_number;
449 num_pts_in_segment++;
450
451 if (is_a_seed)
452 {
453 seeds.push (index);
454 }
455
456 i_nghbr++;
457 }// next neighbour
458 }// next seed
459
460 return (num_pts_in_segment);
461}
462
463//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
464template <typename PointT, typename NormalT> bool
466{
467 is_a_seed = true;
468
469 float cosine_threshold = std::cos (theta_threshold_);
470 float data[4];
471
472 data[0] = (*input_)[point].data[0];
473 data[1] = (*input_)[point].data[1];
474 data[2] = (*input_)[point].data[2];
475 data[3] = (*input_)[point].data[3];
476 Eigen::Map<Eigen::Vector3f> initial_point (static_cast<float*> (data));
477 Eigen::Map<Eigen::Vector3f> initial_normal (static_cast<float*> ((*normals_)[point].normal));
478
479 //check the angle between normals
480 if (smooth_mode_flag_)
481 {
482 Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> ((*normals_)[nghbr].normal));
483 float dot_product = std::abs (nghbr_normal.dot (initial_normal));
484 if (dot_product < cosine_threshold)
485 {
486 return (false);
487 }
488 }
489 else
490 {
491 Eigen::Map<Eigen::Vector3f> nghbr_normal (static_cast<float*> ((*normals_)[nghbr].normal));
492 Eigen::Map<Eigen::Vector3f> initial_seed_normal (static_cast<float*> ((*normals_)[initial_seed].normal));
493 float dot_product = std::abs (nghbr_normal.dot (initial_seed_normal));
494 if (dot_product < cosine_threshold)
495 return (false);
496 }
497
498 // check the curvature if needed
499 if (curvature_flag_ && (*normals_)[nghbr].curvature > curvature_threshold_)
500 {
501 is_a_seed = false;
502 }
503
504 // check the residual if needed
505 float data_1[4];
506
507 data_1[0] = (*input_)[nghbr].data[0];
508 data_1[1] = (*input_)[nghbr].data[1];
509 data_1[2] = (*input_)[nghbr].data[2];
510 data_1[3] = (*input_)[nghbr].data[3];
511 Eigen::Map<Eigen::Vector3f> nghbr_point (static_cast<float*> (data_1));
512 float residual = std::abs (initial_normal.dot (initial_point - nghbr_point));
513 if (residual_flag_ && residual > residual_threshold_)
514 is_a_seed = false;
515
516 return (true);
517}
518
519//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
520template <typename PointT, typename NormalT> void
522{
523 const auto number_of_segments = num_pts_in_segment_.size ();
524 const auto number_of_points = input_->size ();
525
526 pcl::PointIndices segment;
527 clusters_.resize (number_of_segments, segment);
528
529 for (std::size_t i_seg = 0; i_seg < number_of_segments; i_seg++)
530 {
531 clusters_[i_seg].indices.resize ( num_pts_in_segment_[i_seg], 0);
532 }
533
534 std::vector<int> counter(number_of_segments, 0);
535
536 for (std::size_t i_point = 0; i_point < number_of_points; i_point++)
537 {
538 const auto segment_index = point_labels_[i_point];
539 if (segment_index != -1)
540 {
541 const auto point_index = counter[segment_index];
542 clusters_[segment_index].indices[point_index] = i_point;
543 counter[segment_index] = point_index + 1;
544 }
545 }
546
547 number_of_segments_ = number_of_segments;
548}
549
550//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
551template <typename PointT, typename NormalT> void
553{
554 cluster.indices.clear ();
555
556 bool segmentation_is_possible = initCompute ();
557 if ( !segmentation_is_possible )
558 {
559 deinitCompute ();
560 return;
561 }
562
563 // first of all we need to find out if this point belongs to cloud
564 bool point_was_found = false;
565 for (const auto& point : (*indices_))
566 if (point == index)
567 {
568 point_was_found = true;
569 break;
570 }
571
572 if (point_was_found)
573 {
574 if (clusters_.empty ())
575 {
576 point_neighbours_.clear ();
577 point_labels_.clear ();
578 num_pts_in_segment_.clear ();
579 number_of_segments_ = 0;
580
581 segmentation_is_possible = prepareForSegmentation ();
582 if ( !segmentation_is_possible )
583 {
584 deinitCompute ();
585 return;
586 }
587
588 findPointNeighbours ();
589 applySmoothRegionGrowingAlgorithm ();
590 assembleRegions ();
591 }
592 // if we have already made the segmentation, then find the segment
593 // to which this point belongs
594 for (const auto& i_segment : clusters_)
595 {
596 const auto it = std::find (i_segment.indices.cbegin (), i_segment.indices.cend (), index);
597 if (it != i_segment.indices.cend())
598 {
599 // if segment was found
600 cluster.indices.clear ();
601 cluster.indices.reserve (i_segment.indices.size ());
602 std::copy (i_segment.indices.begin (), i_segment.indices.end (), std::back_inserter (cluster.indices));
603 break;
604 }
605 }// next segment
606 }// end if point was found
607
608 deinitCompute ();
609}
610
611//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
612template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGB>::Ptr
614{
616
617 if (!clusters_.empty ())
618 {
619 colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
620
621 srand (static_cast<unsigned int> (time (nullptr)));
622 std::vector<unsigned char> colors;
623 for (std::size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
624 {
625 colors.push_back (static_cast<unsigned char> (rand () % 256));
626 colors.push_back (static_cast<unsigned char> (rand () % 256));
627 colors.push_back (static_cast<unsigned char> (rand () % 256));
628 }
629
630 colored_cloud->width = input_->width;
631 colored_cloud->height = input_->height;
632 colored_cloud->is_dense = input_->is_dense;
633 for (const auto& i_point: *input_)
634 {
635 pcl::PointXYZRGB point;
636 point.x = *(i_point.data);
637 point.y = *(i_point.data + 1);
638 point.z = *(i_point.data + 2);
639 point.r = 255;
640 point.g = 0;
641 point.b = 0;
642 colored_cloud->points.push_back (point);
643 }
644
645 int next_color = 0;
646 for (const auto& i_segment : clusters_)
647 {
648 for (const auto& index : (i_segment.indices))
649 {
650 (*colored_cloud)[index].r = colors[3 * next_color];
651 (*colored_cloud)[index].g = colors[3 * next_color + 1];
652 (*colored_cloud)[index].b = colors[3 * next_color + 2];
653 }
654 next_color++;
655 }
656 }
657
658 return (colored_cloud);
659}
660
661//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
662template <typename PointT, typename NormalT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr
664{
666
667 if (!clusters_.empty ())
668 {
669 colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGBA>);
670
671 srand (static_cast<unsigned int> (time (nullptr)));
672 std::vector<unsigned char> colors;
673 for (std::size_t i_segment = 0; i_segment < clusters_.size (); i_segment++)
674 {
675 colors.push_back (static_cast<unsigned char> (rand () % 256));
676 colors.push_back (static_cast<unsigned char> (rand () % 256));
677 colors.push_back (static_cast<unsigned char> (rand () % 256));
678 }
679
680 colored_cloud->width = input_->width;
681 colored_cloud->height = input_->height;
682 colored_cloud->is_dense = input_->is_dense;
683 for (const auto& i_point: *input_)
684 {
685 pcl::PointXYZRGBA point;
686 point.x = *(i_point.data);
687 point.y = *(i_point.data + 1);
688 point.z = *(i_point.data + 2);
689 point.r = 255;
690 point.g = 0;
691 point.b = 0;
692 point.a = 0;
693 colored_cloud->points.push_back (point);
694 }
695
696 int next_color = 0;
697 for (const auto& i_segment : clusters_)
698 {
699 for (const auto& index : (i_segment.indices))
700 {
701 (*colored_cloud)[index].r = colors[3 * next_color];
702 (*colored_cloud)[index].g = colors[3 * next_color + 1];
703 (*colored_cloud)[index].b = colors[3 * next_color + 2];
704 }
705 next_color++;
706 }
707 }
708
709 return (colored_cloud);
710}
711
712#define PCL_INSTANTIATE_RegionGrowing(T) template class PCL_EXPORTS pcl::RegionGrowing<T, pcl::Normal>;
713
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.
Defines all the PCL implemented PointT point type structures.
@ many_knn_search
The search method will mainly be used for nearestKSearch where k is larger than 1.
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:56
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.