ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
qCanupoClassifDialog.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 
8 #include "qCanupoClassifDialog.h"
9 
10 // local
11 #include "classifier.h"
12 #include "qCanupoTools.h"
13 
14 // CV_DB_LIB
15 #include <ecvMainAppInterface.h>
16 #include <ecvPointCloud.h>
17 
18 // Qt
19 #include <QApplication>
20 #include <QComboBox>
21 #include <QFileDialog>
22 #include <QFileInfo>
23 #include <QMainWindow>
24 #include <QPushButton>
25 #include <QSettings>
26 #include <QThread>
27 
30  : QDialog(app ? app->getMainWindow() : 0),
31  Ui::CanupoClassifDialog(),
32  m_app(app),
33  m_cloud(cloud) {
34  setupUi(this);
35 
36 #ifndef COMPILE_PRIVATE_CANUPO
37  generateRoughnessSFsCheckBox->setVisible(false);
38 #endif
39 
40  int maxThreadCount = QThread::idealThreadCount();
41  maxThreadCountSpinBox->setRange(1, maxThreadCount);
42  maxThreadCountSpinBox->setSuffix(QString(" / %1").arg(maxThreadCount));
43 
45 
46  if (cloud) {
47  // check if a the cloud has an active SF!
48  useSFCheckBox->setEnabled(cloud->getCurrentDisplayedScalarField() != 0);
49  }
50 
51  if (m_app) {
52  // add list of clouds to the combo-boxes
53  ccHObject::Container clouds;
54  if (m_app->dbRootObject())
55  m_app->dbRootObject()->filterChildren(clouds, true,
57 
58  for (size_t i = 0; i < clouds.size(); ++i) {
59  if (clouds[i]->isA(CV_TYPES::POINT_CLOUD)) // as filterChildren
60  // only test 'isKindOf'
61  cpOtherCloudComboBox->addItem(
62  qCanupoTools::GetEntityName(clouds[i]),
63  QVariant(clouds[i]->getUniqueID()));
64  }
65  }
66 
67  connect(browseToolButton, SIGNAL(clicked()), this,
68  SLOT(browseClassifierFile()));
69  connect(mscBrowseToolButton, SIGNAL(clicked()), this,
70  SLOT(browseMscFile()));
71 
72  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
73 }
74 
76  if (!useConfThresholdGroupBox->isChecked()) return 0.0;
77 
78  // confidence threshold between 0 and 1
79  assert(pokDoubleSpinBox->value() >= 0 && pokDoubleSpinBox->value() <= 1.0);
80  return pokDoubleSpinBox->value();
81 }
82 
84  return useConfThresholdGroupBox->isChecked() && useSFCheckBox->isChecked();
85 }
86 
88  return maxThreadCountSpinBox->value();
89 }
90 
93  if (cpUseCloudRadioButton->isChecked()) {
94  return ORIGINAL;
95  } else if (cpSubsampleRadioButton->isChecked()) {
96  return SUBSAMPLED;
97  } else if (cpUseOtherCloudRadioButton->isChecked()) {
98  return OTHER;
99  } else if (cpMscFileRadioButton->isChecked()) {
100  return MSC_FILE;
101  }
102 
103  assert(false);
104  return ORIGINAL;
105 }
106 
108  return mscFileLineEdit->text();
109 }
110 
112  if (cpUseCloudRadioButton->isChecked()) {
113  return m_cloud;
114  } else if (cpUseOtherCloudRadioButton->isChecked()) {
115  // return the cloud currently selected in the combox box
116  return qCanupoTools::GetCloudFromCombo(cpOtherCloudComboBox,
117  m_app->dbRootObject());
118  } else {
119  return 0;
120  }
121 }
122 
124  QSettings settings("qCanupo");
125  settings.beginGroup("Classif");
126 
127  // read out parameters
128  // double minScale =
129  // settings.value("MinScale",minScaleDoubleSpinBox->value()).toDouble();
130  // double step =
131  // settings.value("Step",stepScaleDoubleSpinBox->value()).toDouble(); double
132  // maxScale =
133  // settings.value("MaxScale",maxScaleDoubleSpinBox->value()).toDouble();
134 
135  double subsampleRadius = settings.value("SubsampleRadius",
136  cpSubsamplingDoubleSpinBox->value())
137  .toDouble();
138  bool subsampleEnabled = settings.value("SubsampleEnabled",
139  cpSubsampleRadioButton->isChecked())
140  .toBool();
141 
142  QString currentPath =
143  settings.value("CurrentPath", QApplication::applicationDirPath())
144  .toString();
145  QString mscCurrentPath =
146  settings.value("MscCurrentPath", QApplication::applicationDirPath())
147  .toString();
148 
149  bool useConfThreshold =
150  settings.value("UseConfThreshold",
151  useConfThresholdGroupBox->isChecked())
152  .toBool();
153  double pok = settings.value("Pok", pokDoubleSpinBox->value()).toDouble();
154  bool useSF = settings.value("UseSF", useSFCheckBox->isChecked()).toBool();
155  bool additionalSF =
156  settings.value("AdditionalSF",
157  generateAdditionalSFsCheckBox->isChecked())
158  .toBool();
159  bool roughnessSF = settings.value("RoughnessSF",
160  generateRoughnessSFsCheckBox->isChecked())
161  .toBool();
162  int maxThreadCount =
163  settings.value("MaxThreadCount", maxThreadCountSpinBox->maximum())
164  .toInt();
165 
166  // apply parameters
167 
168  // minScaleDoubleSpinBox->setValue(minScale);
169  // stepScaleDoubleSpinBox->setValue(step);
170  // maxScaleDoubleSpinBox->setValue(maxScale);
171 
172  cpSubsamplingDoubleSpinBox->setValue(subsampleRadius);
173  if (subsampleEnabled) cpSubsampleRadioButton->setChecked(true);
174 
175  classifFileLineEdit->setText(currentPath);
176  mscFileLineEdit->setText(mscCurrentPath);
177 
178  useConfThresholdGroupBox->setChecked(useConfThreshold);
179  pokDoubleSpinBox->setValue(pok);
180  useSFCheckBox->setChecked(useSF);
181  generateAdditionalSFsCheckBox->setChecked(additionalSF);
182  generateRoughnessSFsCheckBox->setChecked(roughnessSF);
183  maxThreadCountSpinBox->setValue(maxThreadCount);
184 }
185 
187  QSettings settings("qCanupo");
188  settings.beginGroup("Classif");
189 
190  // save parameters
191  // settings.setValue("MinScale",minScaleDoubleSpinBox->value());
192  // settings.setValue("Step",stepScaleDoubleSpinBox->value());
193  // settings.setValue("MaxScale",maxScaleDoubleSpinBox->value());
194 
195  settings.setValue("SubsampleRadius", cpSubsamplingDoubleSpinBox->value());
196  settings.setValue("SubsampleEnabled", cpSubsampleRadioButton->isChecked());
197 
198  QString currentPath = QFileInfo(classifFileLineEdit->text()).absolutePath();
199  settings.setValue("CurrentPath", currentPath);
200 
201  settings.setValue("UseConfThreshold",
202  useConfThresholdGroupBox->isChecked());
203  settings.setValue("Pok", pokDoubleSpinBox->value());
204  settings.setValue("UseSF", useSFCheckBox->isChecked());
205  settings.setValue("AdditionalSF",
206  generateAdditionalSFsCheckBox->isChecked());
207  settings.setValue("RoughnessSF", generateRoughnessSFsCheckBox->isChecked());
208 
209  settings.setValue("MaxThreadCount", maxThreadCountSpinBox->value());
210 }
211 
213  // select file to open
214  QSettings settings("qCanupo");
215  settings.beginGroup("Classif");
216  QString currentPath =
217  settings.value("MscCurrentPath", mscFileLineEdit->text())
218  .toString();
219 
220  QString filename = QFileDialog::getOpenFileName(this, "Load MSC file",
221  currentPath, "*.msc");
222  if (filename.isEmpty()) return;
223 
224  // we update current file path
225  mscFileLineEdit->setText(filename);
226  currentPath = QFileInfo(filename).absolutePath();
227  settings.setValue("MscCurrentPath", currentPath);
228 }
229 
231  // select file to open
232  QString filename;
233  QSettings settings("qCanupo");
234  settings.beginGroup("Classif");
235  QString currentPath =
236  settings.value("CurrentPath", classifFileLineEdit->text())
237  .toString();
238 
239  filename = QFileDialog::getOpenFileName(this, "Load classifier file",
240  currentPath, "*.prm");
241  if (filename.isEmpty()) return;
242 
243  // we update current file path
244  classifFileLineEdit->setText(filename);
245  currentPath = QFileInfo(filename).absolutePath();
246  settings.setValue("CurrentPath", currentPath);
247 
248  // and we try to load the file header (to display some info)
249  std::vector<Classifier> classifiers;
250  std::vector<PointCoordinateType> scales;
251  QString error;
252  Classifier::FileHeader header;
253  if (Classifier::Load(filename, classifiers, scales, error, &header, true)) {
254  // display classifier file description
255  QStringList fileDesc;
256  fileDesc << QString("File: %1").arg(QFileInfo(filename).fileName());
257  fileDesc << QString("Classifier(s) in file: %1")
258  .arg(header.classifierCount);
259 
260  assert(header.descID != 0);
263  QString descriptorName =
264  computer ? computer->getName() : QString("INVALID");
265  fileDesc << QString("Descriptor ID: %1 (%2)")
266  .arg(header.descID)
267  .arg(descriptorName);
268 
269  fileDesc << QString("Dimensions per scale: %1").arg(header.dimPerScale);
270  fileDesc << QString("Scales: %1").arg(scales.size());
271  QString scalesStr(" [ ");
272  for (size_t i = 0; i < scales.size(); ++i)
273  scalesStr.append(QString("%1 ").arg(
274  scales[scales.size() - 1 -
275  i])); // reverse order as scales are sorted from
276  // biggest to smallest
277  scalesStr.append("]");
278  fileDesc << scalesStr;
279 
280  classifInfoTextEdit->setText(fileDesc.join("\n"));
281 
282  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
283  } else {
284  classifInfoTextEdit->setText(
285  "Error: failed to open/read the input file");
286  buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
287  }
288 }
std::string filename
static bool Load(QString filename, std::vector< Classifier > &classifiers, std::vector< float > &scales, QString &error, FileHeader *header=0, bool headerOnly=false)
Loads a CANUPO's classifier file (.prm)
Definition: classifier.cpp:157
Generic parameters 'computer' class (at a given scale)
static ScaleParamsComputer * GetByID(unsigned descID)
Vault: returns the computer corresponding to the given ID.
virtual QString getName() const =0
Returns the associated descriptor name.
unsigned filterChildren(Container &filteredChildren, bool recursive=false, CV_CLASS_ENUM filter=CV_TYPES::OBJECT, bool strict=false) const
Collects the children corresponding to a certain pattern.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
Definition: ecvHObject.h:337
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
Main application interface (for plugins)
virtual ccHObject * dbRootObject()=0
Returns DB root (as a ccHObject)
ccPointCloud * m_cloud
Associated cloud.
void loadParamsFromPersistentSettings()
Loads parameters from persistent settings.
ccPointCloud * getCorePointsCloud()
Get core points cloud (if any)
QString getMscFilename() const
Returns MSC file name (if source == MSC_FILE)
void saveParamsToPersistentSettings()
Saves parameters to persistent settings.
ecvMainAppInterface * m_app
Gives access to the application (data-base, UI, etc.)
qCanupoClassifDialog(ccPointCloud *cloud, ecvMainAppInterface *app)
Default constructor.
CORE_CLOUD_SOURCES getCorePointsCloudSource() const
Returns the selected source for core points.
double getConfidenceTrehshold() const
Returns the confidence threshold.
int getMaxThreadCount() const
Returns the max number of threads to use.
CORE_CLOUD_SOURCES
"Sources" of core points
static ccPointCloud * GetCloudFromCombo(QComboBox *comboBox, ccHObject *dbRoot)
static QString GetEntityName(ccHObject *obj)
Returns a long description of a given entity (name + [ID])
static void error(char *msg)
Definition: lsd.c:159
@ POINT_CLOUD
Definition: CVTypes.h:104
ScaleParamsComputer * computer
Classifier's file header info.
Definition: classifier.h:52
unsigned classifierCount
Definition: classifier.h:53