ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
RegionGrowingSegmentation.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <Utils/cc2sm.h>
11 #include <Utils/sm2cc.h>
12 
13 #include "PclUtils/PCLModules.h"
15 #ifdef LP_PCL_PATCH_ENABLED
16 #include <Utils/copy.h>
17 #endif
18 
19 // CV_DB_LIB
20 #include <ecvPointCloud.h>
21 
22 // ECV_PLUGINS
23 #include <ecvMainAppInterface.h>
24 
25 // QT
26 #include <QMainWindow>
27 
28 // SYSTEM
29 #include <iostream>
30 #include <sstream>
31 
34  tr("Region Growing Segmentation"),
35  tr("Region Growing Segmentation"),
36  tr("Region Growing Segmentation from clouds"),
37  ":/toolbar/PclAlgorithms/icons/Regiongrowing.png")),
38  m_dialog(nullptr),
39  m_basedRgb(false),
40  m_k_search(50),
41  m_min_cluster_size(50),
42  m_max_cluster_size(100000),
43  m_neighbour_number(30),
44  m_smoothness_theta(0.052359878f),
45  m_curvature(1.0f),
46  m_min_cluster_size_rgb(100),
47  m_neighbors_distance(10.0f),
48  m_point_color_diff(6.0f),
49  m_region_color_diff(5.0f) {}
50 
52  // we must delete parent-less dialogs ourselves!
53  if (m_dialog && m_dialog->parent() == nullptr) delete m_dialog;
54 }
55 
57  // do we have a selected cloud?
58  int have_cloud = isFirstSelectedCcPointCloud();
59  if (have_cloud != 1) return -11;
60 
61  return 1;
62 }
63 
65  // initialize the dialog object
66  if (!m_dialog)
68  m_app ? m_app->getActiveWindow() : 0);
69 
71  if (cloud->hasColors() || cloud->hasScalarFields()) {
72  m_dialog->rgRGBTab->setEnabled(true);
73  m_basedRgb = true;
74  } else {
75  m_dialog->rgRGBTab->setEnabled(false);
76  m_basedRgb = false;
77  }
78 
79  if (!m_dialog->exec()) return 0;
80 
81  return 1;
82 }
83 
85  if (!m_dialog) return;
86 
87  switch (m_dialog->rgTab->currentIndex()) {
88  // Basic Region Growing Segmentation
89  case 0: {
91  m_dialog->min_cluster_size_input->text().toInt();
93  m_dialog->max_cluster_size_input->text().toInt();
94  m_neighbour_number = m_dialog->neighbour_num_input->text().toUInt();
96  m_dialog->smoothness_theta_input->text().toFloat();
97  m_curvature = m_dialog->curvature_input->text().toFloat();
98  m_basedRgb = false;
99  } break;
100  // Region Growing Segmentation Based on RGB
101  case 1: {
103  m_dialog->min_cluster_size2_input->text().toInt();
105  m_dialog->neighbours_dist_input->text().toFloat();
107  m_dialog->point_color_diff_input->text().toFloat();
109  m_dialog->region_color_diff_input->text().toFloat();
110  m_basedRgb = true;
111  } break;
112  }
113 }
114 
116 
119  if (!cloud) return -1;
120 
121  PCLCloud::Ptr sm_cloud = cc2smReader(cloud).getAsSM();
122  if (!sm_cloud) return -1;
123 
124  // initialize all possible clouds
125  std::vector<pcl::PointIndices> clusters;
126  PointCloudT::Ptr xyzCloud(new PointCloudT);
127  PointCloudRGB::Ptr rgbCloud(new PointCloudRGB);
128  PointCloudRGB::Ptr cloudSegmented(new PointCloudRGB);
129 
130  std::stringstream name;
131  if (m_basedRgb) // Region Growing Segmentation Based on RGB
132  {
133  FROM_PCL_CLOUD(*sm_cloud, *rgbCloud);
134  int result = PCLModules::GetRegionGrowingRGB(
135  rgbCloud, clusters, cloudSegmented, m_min_cluster_size_rgb,
137  if (result < 0) return -1;
138  name << "RGB_RegionGrowing_clusters_" << clusters.size();
139  } else // Basic Region Growing Segmentation
140  {
141  FROM_PCL_CLOUD(*sm_cloud, *xyzCloud);
142  int result = PCLModules::GetRegionGrowing(
143  xyzCloud, clusters, cloudSegmented, m_k_search,
146  if (result < 0) return -1;
147  name << "Basic_RegionGrowing_clusters_" << clusters.size();
148  }
149 
150  PCLCloud out_cloud_sm;
151  TO_PCL_CLOUD(*cloudSegmented, out_cloud_sm);
152 
153  if (out_cloud_sm.height * out_cloud_sm.width == 0) {
154  // cloud is empty
155  return -53;
156  }
157 
158  ccPointCloud* out_cloud_cc = pcl2cc::Convert(out_cloud_sm);
159  if (!out_cloud_cc) {
160  // conversion failed (not enough memory?)
161  return -1;
162  }
163 
164  out_cloud_cc->setName(name.str().c_str());
165  // copy global shift & scale
166  out_cloud_cc->setGlobalScale(cloud->getGlobalScale());
167  out_cloud_cc->setGlobalShift(cloud->getGlobalShift());
168 
169  cloud->setEnabled(false);
170  if (cloud->getParent()) cloud->getParent()->addChild(out_cloud_cc);
171 
172  emit newEntity(out_cloud_cc);
173 
174  return 1;
175 }
176 
178  switch (errorCode) {
179  // THESE CASES CAN BE USED TO OVERRIDE OR ADD FILTER-SPECIFIC ERRORS
180  // CODES ALSO IN DERIVED CLASSES DEFULAT MUST BE ""
181 
182  case -51:
183  return tr(
184  "Selected entity does not have any suitable scalar field "
185  "or RGB");
186  case -52:
187  return tr(
188  "Wrong Parameters. One or more parameters cannot be "
189  "accepted");
190  case -53:
191  return tr(
192  "Region Growing Segmentation does not returned any point. "
193  "Try relaxing your parameters");
194  }
195 
196  return BasePclModule::getErrorMessage(errorCode);
197 }
std::string name
core::Tensor result
Definition: VtkUtils.cpp:76
Base abstract class for each implemented PCL filter.
Definition: BasePclModule.h:53
int isFirstSelectedCcPointCloud()
Returns 1 if the first selected object is a ccPointCloud.
void newEntity(ccHObject *)
Signal emitted when a new entity is created by the filter.
ecvMainAppInterface * m_app
Associated application interface.
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
ccPointCloud * getSelectedEntityAsCCPointCloud() const
Returns the first selected entity as a ccPointCloud.
RegionGrowingSegmentationDlg * m_dialog
virtual QString getErrorMessage(int errorCode)
Returns the error message corresponding to a given error code.
virtual int compute()
Performs the actual filter job.
virtual void getParametersFromDialog()
Collects parameters from the filter dialog (if openDialog is successful)
virtual int checkSelected()
Checks if current selection is compliant with the filter.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool hasColors() const override
Returns whether colors are enabled or not.
bool hasScalarFields() const override
Returns whether one or more scalar fields are instantiated.
virtual void setGlobalScale(double scale)
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
virtual QWidget * getActiveWindow()=0
PCL filter description.
Definition: BasePclModule.h:26