LVRLabelDialog.cpp
Go to the documentation of this file.
1 
34 #include "LVRLabelDialog.hpp"
35 #include "LVRPointCloudItem.hpp"
36 #include "LVRItemTypes.hpp"
37 
38 #include <vtkSmartPointer.h>
39 #include <vtkCubeSource.h>
40 
41 #include <boost/make_shared.hpp>
42 
43 #include <QMessageBox>
44 #include <QFont>
45 #include <QFileDialog>
46 #include <QInputDialog>
47 #include <QColorDialog>
48 #include <QButtonGroup>
49 #include <vtkSelectEnclosedPoints.h>
50 #include <vtkPolyDataMapper.h>
51 #include <vtkPointData.h>
52 #include <vector>
53 #include <algorithm>
54 
55 #include <vtkLookupTable.h>
56 #include <vtkExtractGeometry.h>
58 
59 #include <fstream>
60 using std::ifstream;
61 using std::ofstream;
62 
63 namespace lvr2
64 {
65 
66 LVRLabelDialog::LVRLabelDialog(QTreeWidget* treeWidget) :
67  m_treeWidget(treeWidget)
68 {
69  m_dialog = new QDialog(treeWidget);
70  m_ui = new Ui_LabelDialog;
71  m_ui->setupUi(m_dialog);
72  // m_ui->treeWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
73  QObject::connect(m_ui->newLabelButton, SIGNAL(pressed()), this, SLOT(addNewLabel()));
74  QObject::connect(m_ui->loadLabeledPoints, SIGNAL(pressed()), this, SLOT(loadLabels()));
75  QObject::connect(m_ui->newInstanceButton, SIGNAL(pressed()), this, SLOT(addNewInstance()));
76  QObject::connect(m_ui->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(cellSelected(QTreeWidgetItem*, int)));
77  QObject::connect(m_ui->selectedLabelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxIndexChanged(int)));
78  QObject::connect(m_ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(visibilityChanged(QTreeWidgetItem*, int)));
79 // QObject::connect(m_ui->labelSelectedPoints, SIGNAL(pressed()), this, SLOT(labelPoints()));
80 //
81 }
82 
84 {
85  delete m_ui;
86  delete m_dialog;
87  // TODO Auto-generated destructor stub
88 }
89 
91 {
92 
93 
94 }
95 void LVRLabelDialog::visibilityChanged(QTreeWidgetItem* changedItem, int column)
96 {
97  if(column != LABEL_VISIBLE_COLUMN)
98  {
99  return;
100  }
101 
102  //check if Instance or whole label changed
103  if (changedItem->parent())
104  {
105  //parent exists item is an instance
106  Q_EMIT(hidePoints(changedItem->data(LABEL_ID_COLUMN,0).toInt(), changedItem->checkState(LABEL_VISIBLE_COLUMN)));
107  } else
108  {
109  //Check if unlabeled item
110  for (int i = 0; i < changedItem->childCount(); i++)
111  {
112  QTreeWidgetItem* childItem = changedItem->child(i);
113 
114  //sets child elements checkbox on toplevel box value if valuechanged a singal will be emitted and handeled
115  childItem->setCheckState(LABEL_VISIBLE_COLUMN, changedItem->checkState(LABEL_VISIBLE_COLUMN));
116  }
117  }
118 
119 
120 }
121 
122 void LVRLabelDialog::cellSelected(QTreeWidgetItem* item, int column)
123 {
124  if(column == LABEL_NAME_COLUMN)
125  {
126  //Edit Label name
127  bool accepted;
128  QString label_name = QInputDialog::getText(m_dialog, tr("Select Label Name"),
129  tr("Label name:"), QLineEdit::Normal,
130  item->text(LABEL_NAME_COLUMN), &accepted);
131  if (accepted && !label_name.isEmpty())
132  {
133  item->setText(LABEL_NAME_COLUMN, label_name);
134  if (!item->parent())
135  {
136  //Toplevel item nothing else to do
137  return;
138  }
139  int comboBoxPos = m_ui->selectedLabelComboBox->findData(item->data(LABEL_ID_COLUMN, 0).toInt());
140  if (comboBoxPos >= 0)
141  {
142  m_ui->selectedLabelComboBox->setItemText(comboBoxPos, label_name);
143 
144  }
145  return;
146  }
147  }else if(column == LABEL_ID_COLUMN)
148  {
149  //Change
150  QColor label_color = QColorDialog::getColor(Qt::red, m_dialog, tr("Choose Label Color"));
151  if (label_color.isValid())
152  {
153  item->setData(LABEL_ID_COLUMN, 1, label_color);
154  if(item->parent())
155  {
156  //Update Color In picker
157  Q_EMIT(labelAdded(item));
158  return;
159  }
160  else
161  {
162  //ask if all childs Should be updated
163  QMessageBox colorUpdateDialog;
164  colorUpdateDialog.setText("Labelclass default color changed. Shall all instance colors be updated?");
165  colorUpdateDialog.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
166  colorUpdateDialog.setDefaultButton(QMessageBox::Yes);
167  int returnValue = colorUpdateDialog.exec();
168  if (returnValue == QMessageBox::Yes)
169  {
170  //update All Childs
171  for (int i = 0; i < item->childCount(); i++)
172  {
173  item->child(i)->setData(LABEL_ID_COLUMN, 1, label_color);
174  Q_EMIT(labelAdded(item->child(i)));
175  }
176  }
177 
178  }
179  }
180  }
181 }
182 
183 void LVRLabelDialog::updatePointCount(uint16_t id, int selectedPointCount)
184 {
185 
186 
187  int topItemCount = m_ui->treeWidget->topLevelItemCount();
188  for (int i = 0; i < topItemCount; i++)
189  {
190  QTreeWidgetItem* topLevelItem = m_ui->treeWidget->topLevelItem(i);
191  int childCount = topLevelItem->childCount();
192  for (int j = 0; j < childCount; j++)
193  {
194  if(id == topLevelItem->child(j)->data(LABEL_ID_COLUMN, 0).toInt())
195  {
196  int pointCountDifference = selectedPointCount - topLevelItem->child(j)->text(LABELED_POINT_COLUMN).toInt();
197  topLevelItem->child(j)->setText(LABELED_POINT_COLUMN, QString::number(selectedPointCount));
198  //Add points to toplevel points
199  topLevelItem->setText(LABELED_POINT_COLUMN, QString::number(pointCountDifference + topLevelItem->text(LABELED_POINT_COLUMN).toInt()));
200  return;
201  }
202  }
203  }
204 }
205 
207 {
208 
209  //TODO: What should be done if elements exists?
210  QString fileName = QFileDialog::getOpenFileName(m_dialog,
211  tr("Open HDF5 File"), QDir::homePath(), tr("HDF5 files (*.h5)"));
212  if(!QFile::exists(fileName))
213  {
214  return;
215  }
216 
217  HDF5Kernel kernel(fileName.toStdString());
218  std::vector<std::string> pointCloudNames;
219  kernel.subGroupNames("pointclouds", pointCloudNames);
220  for (auto pointcloudName : pointCloudNames)
221  {
222  //pointclouds
223  boost::filesystem::path classGroup = (boost::filesystem::path("pointclouds") / boost::filesystem::path(pointcloudName) / boost::filesystem::path("labels"));
224  std::vector<std::string> labelClasses;
225  kernel.subGroupNames(classGroup.string(), labelClasses);
226  for (auto labelClass : labelClasses)
227  {
228  //Get TopLevel Item for tree view
229  QTreeWidgetItem * item = new QTreeWidgetItem();
230  item->setText(0, QString::fromStdString(labelClass));
231  item->setText(LABELED_POINT_COLUMN, QString::number(0));
232  item->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
233 
234  if (m_ui->treeWidget->topLevelItemCount() == 0)
235  {
236  m_ui->newInstanceButton->setEnabled(true);
237  }
238  m_ui->treeWidget->addTopLevelItem(item);
239 
240 
241  //pointclouds/$name/labels/$labelname
242  boost::filesystem::path instanceGroup = (classGroup / boost::filesystem::path(labelClass));
243  std::vector<std::string> labelInstances;
244  kernel.subGroupNames(instanceGroup.string(), labelInstances);
245  for (auto instance : labelInstances)
246  {
247 
248  int id = 0;
249  boost::filesystem::path finalGroup = instanceGroup;
250  //pointclouds/$name/labels/$labelname/instance
251  finalGroup = (instanceGroup / boost::filesystem::path(instance));
252  if (labelClass != "Unlabeled")
253  {
254  id = m_id_hack++;
255 
256  }
257 
258  //Get Color and IDs
259  boost::shared_array<int> rgbData;
260  std::vector<size_t> rgbDim;
261  boost::shared_array<int> idData;
262  std::vector<size_t> idDim;
263  idData = kernel.loadArray<int>(finalGroup.string(), "IDs", idDim);
264  rgbData = kernel.loadArray<int>(finalGroup.string(), "Color", rgbDim);
265 
266  //Add Child to top Level
267  QTreeWidgetItem * childItem = new QTreeWidgetItem();
268  childItem->setText(LABELED_POINT_COLUMN, QString::number(0));
269  childItem->setText(0, QString::fromStdString(instance));
270  QColor label_color(rgbData[0], rgbData[1], rgbData[2]);
271  childItem->setData(LABEL_ID_COLUMN, 1, label_color);
272  childItem->setData(LABEL_ID_COLUMN, 0, id);
273  item->addChild(childItem);
274  Q_EMIT(labelAdded(childItem));
275  std::vector<int> out(idData.get(), idData.get() + idDim[0]);
276  Q_EMIT(labelLoaded(id, out));
277  if (labelClass != "Unlabeled")
278  {
279  m_ui->selectedLabelComboBox->addItem(childItem->text(LABEL_NAME_COLUMN), id);
280  }
281  }
282  }
283  }
284 }
285 void LVRLabelDialog::responseLabels(std::vector<uint16_t> labeledPoints)
286 {
287  std::map<uint16_t,std::vector<int>> idMap;
288 
289  for (int i = 0; i < labeledPoints.size(); i++)
290  {
291 
292  if(idMap.find(labeledPoints[i]) == idMap.end())
293  {
294  //first occurence of id add new entry
295  idMap[labeledPoints[i]] = {};
296  }
297  idMap[labeledPoints[i]].push_back(i);
298  }
299 
300  QFileDialog dialog;
301  dialog.setDirectory(QDir::homePath());
302  dialog.setFileMode(QFileDialog::AnyFile);
303  QString strFile = dialog.getSaveFileName(m_dialog, "Creat New HDF5 File","","");
304 
305  HDF5Kernel label_hdf5kernel((strFile + QString(".h5")).toStdString());
306  int topItemCount = m_ui->treeWidget->topLevelItemCount();
307 
308 
309  //TODO This should be for all Pointclouds
310  boost::filesystem::path pointcloudName(m_points.begin()->first);
311  auto points = m_points.begin()->second;
312 
313  double* pointsData = new double[points->GetNumberOfPoints() * 3];
314  // const size_t point_number = points->GetNumberOfPoints();
315  // std::array<std::array<float, 3>, point_number> test;
316 
317  for (int i = 0; i < points->GetNumberOfPoints(); i++)
318  {
319  auto point = points->GetPoint(i);
320  pointsData[(3 * i)] = point[0];
321  pointsData[(3 * i) + 1] = point[1];
322  pointsData[(3 * i) + 2] = point[2];
323 
324  }
325 
326  std::vector<size_t> pointsDimension = {3, points->GetNumberOfPoints()};
327  boost::shared_array<double> sharedPoints(pointsData);
328 
329  //Unlabeled top item
330  QTreeWidgetItem* unlabeledItem;
331 
332  boost::filesystem::path pointGroup = (boost::filesystem::path("pointclouds") / pointcloudName);
333  label_hdf5kernel.saveDoubleArray(pointGroup.string(), "Points" , pointsDimension, sharedPoints);
334  for (int i = 0; i < topItemCount; i++)
335  {
336  QTreeWidgetItem* topLevelItem = m_ui->treeWidget->topLevelItem(i);
337  if(topLevelItem->text(LABEL_NAME_COLUMN) == "Unlabeled")
338  {
339  unlabeledItem = topLevelItem;
340  }
341  boost::filesystem::path topLabel = topLevelItem->text(LABEL_NAME_COLUMN).toStdString();
342  int childCount = topLevelItem->childCount();
343  for (int j = 0; j < childCount; j++)
344  {
345  int childID = topLevelItem->child(j)->data(LABEL_ID_COLUMN, 0).toInt();
346  int* sharedArrayData = new int[idMap[childID].size()];
347  std::memcpy(sharedArrayData, idMap[childID].data(), idMap[childID].size() * sizeof(int));
348  boost::shared_array<int> data(sharedArrayData);
349  std::vector<size_t> dimension = {idMap[childID].size()};
350  if(idMap.find(childID) != idMap.end())
351  {
352  boost::filesystem::path childLabel = (topLevelItem->child(j)->text(LABEL_NAME_COLUMN)).toStdString();
353  boost::filesystem::path completeGroup = (pointGroup / boost::filesystem::path("labels") / topLabel / childLabel);
354 
355  label_hdf5kernel.saveArray(completeGroup.string(), "IDs" , dimension, data);
356  int* rgbSharedData = new int[3];
357  (topLevelItem->child(j)->data(LABEL_ID_COLUMN, 1)).value<QColor>().getRgb(&rgbSharedData[0], &rgbSharedData[1], &rgbSharedData[2]);
358  boost::shared_array<int> rgbData(rgbSharedData);
359  std::vector<size_t> rgbDimension = {3};
360  label_hdf5kernel.saveArray(completeGroup.string(), "Color" , rgbDimension, rgbData);
361  }
362  }
363  }
364 }
365 
366 
368 {
369  //Ask For the Label name
370  bool accepted;
371  QString label_name = QInputDialog::getText(m_dialog, tr("Select Label Name"),
372  tr("Label name:"), QLineEdit::Normal,
373  tr("LabelName") , &accepted);
374  if (!accepted || label_name.isEmpty())
375  {
376  //No valid Input
377  return;
378  }
379 
380  QColor label_color = QColorDialog::getColor(Qt::red, m_dialog, tr("Choose default Label Color for label Class(willbe used for first isntance)"));
381  if (!label_color.isValid())
382  {
383  //Non Valid Color Return
384  return;
385  }
386 
387  if (m_ui->treeWidget->topLevelItemCount() == 0)
388  {
389 
390  //Setting up Top Label
391  QTreeWidgetItem * item = new QTreeWidgetItem();
392  item->setText(0, "Unlabeled");
393  item->setText(LABELED_POINT_COLUMN, QString::number(0));
394  item->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
395  item->setData(LABEL_ID_COLUMN, 1, QColor(Qt::red));
396 
397  //Setting up new child item
398  QTreeWidgetItem * childItem = new QTreeWidgetItem();
399  childItem->setText(LABEL_NAME_COLUMN, QString("Unlabeled") + QString::number(1));
400  childItem->setText(LABELED_POINT_COLUMN, QString::number(0));
401  childItem->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
402  childItem->setData(LABEL_ID_COLUMN, 1, QColor(Qt::red));
403  childItem->setData(LABEL_ID_COLUMN, 0, 0);
404  item->addChild(childItem);
405  m_ui->treeWidget->addTopLevelItem(item);
406  //Added first Top Level item enable instance button
407  m_ui->newInstanceButton->setEnabled(true);
408  Q_EMIT(labelAdded(childItem));
409  }
410 
411  int id = m_id_hack++;
412  //Setting up new Toplevel item
413  QTreeWidgetItem * item = new QTreeWidgetItem();
414  item->setText(0, label_name);
415  item->setText(LABELED_POINT_COLUMN, QString::number(0));
416  item->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
417  item->setData(LABEL_ID_COLUMN, 1, label_color);
418 
419  //Setting up new child item
420  QTreeWidgetItem * childItem = new QTreeWidgetItem();
421  childItem->setText(LABEL_NAME_COLUMN, label_name + QString::number(1));
422  childItem->setText(LABELED_POINT_COLUMN, QString::number(0));
423  childItem->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
424  childItem->setData(LABEL_ID_COLUMN, 1, label_color);
425  childItem->setData(LABEL_ID_COLUMN, 0, id);
426  item->addChild(childItem);
427  m_ui->treeWidget->addTopLevelItem(item);
428 
429  //Add label to combo box
430  m_ui->selectedLabelComboBox->addItem(childItem->text(LABEL_NAME_COLUMN), id);
431 
432  Q_EMIT(labelAdded(childItem));
433 }
434 
436 {
437  QInputDialog topLevelDialog;
438  QStringList topLabels;
439  if (m_ui->treeWidget->topLevelItemCount() == 0)
440  {
441  return;
442  }
443 
444  for (int i = 0; i < m_ui->treeWidget->topLevelItemCount(); i++)
445  {
446  if (m_ui->treeWidget->topLevelItem(i)->text(LABEL_NAME_COLUMN) != "Unlabeled")
447  {
448  topLabels << m_ui->treeWidget->topLevelItem(i)->text(LABEL_NAME_COLUMN);
449  }
450  }
451  topLevelDialog.setComboBoxItems(topLabels);
452  topLevelDialog.setWindowTitle("Create new Instance");
453  if (QDialog::Accepted != topLevelDialog.exec())
454  {
455  return;
456  }
457 
458  QString choosenLabel = topLevelDialog.textValue();
459  QList<QTreeWidgetItem*> selectedTopLevelItem = m_ui->treeWidget->findItems(choosenLabel, Qt::MatchExactly);
460  if (selectedTopLevelItem.count() != 1)
461  {
462  return;
463  }
464 
465 
466 
467  bool accepted;
468  QString instance_name = QInputDialog::getText(m_dialog, tr("Choose Name for new Instance"),
469  tr("Instance name:"), QLineEdit::Normal,
470  QString(choosenLabel + QString::number(selectedTopLevelItem[0]->childCount() + 1)) , &accepted);
471  if (!accepted || instance_name.isEmpty())
472  {
473  //No valid Input
474  return;
475  }
476 
477  QColor label_color = QColorDialog::getColor(selectedTopLevelItem[0]->data(3,1).value<QColor>(), m_dialog, tr("Choose Label Color for first instance"));
478  if (!label_color.isValid())
479  {
480  //Non Valid Color Return
481  return;
482  }
483 
484  int id = m_id_hack++;
485  QTreeWidgetItem * childItem = new QTreeWidgetItem();
486  childItem->setText(LABEL_NAME_COLUMN, instance_name);
487  childItem->setText(LABELED_POINT_COLUMN, QString::number(0));
488  childItem->setCheckState(LABEL_VISIBLE_COLUMN, Qt::Checked);
489  childItem->setData(LABEL_ID_COLUMN, 1, label_color);
490  childItem->setData(LABEL_ID_COLUMN, 0, id);
491  selectedTopLevelItem[0]->addChild(childItem);
492 
493 
494  //Add label to combo box
495  m_ui->selectedLabelComboBox->addItem(childItem->text(LABEL_NAME_COLUMN), id);
496  Q_EMIT(labelAdded(childItem));
497 
498 }
499 
501 {
502  Q_EMIT(labelChanged(m_ui->selectedLabelComboBox->itemData(index).toInt()));
503 }
504 
505 void LVRLabelDialog::setPoints(const std::string pointcloudName, const vtkSmartPointer<vtkPolyData> points)
506 {
507  m_points[pointcloudName] = points;
508 }
509 }
510 
511  /* namespace lvr2 */
512 
513 
void labelLoaded(int, std::vector< int >)
void responseLabels(std::vector< uint16_t >)
#define LABEL_VISIBLE_COLUMN
#define LABEL_NAME_COLUMN
void updatePointCount(uint16_t, int)
virtual void saveDoubleArray(const std::string &groupName, const std::string &datasetName, const std::vector< size_t > &dimensions, const boost::shared_array< double > &data) const
Definition: HDF5Kernel.cpp:447
void labelChanged(uint16_t)
void cellSelected(QTreeWidgetItem *, int)
virtual void subGroupNames(const std::string &group, std::vector< string > &subGroupNames) const
Definition: HDF5Kernel.cpp:474
void hidePoints(int, bool)
void labelAdded(QTreeWidgetItem *)
LVRLabelDialog(QTreeWidget *parent)
void comboBoxIndexChanged(int index)
void setPoints(const std::string, const vtkSmartPointer< vtkPolyData > points)
__kf_device__ Vec3f tr(const float4 &v)
Definition: device.hpp:79
#define LABELED_POINT_COLUMN
void saveArray(const std::string &groupName, const std::string &datasetName, const size_t &size, const boost::shared_array< T > data) const
Ui_LabelDialog * m_ui
#define LABEL_ID_COLUMN
std::map< std::string, vtkSmartPointer< vtkPolyData > > m_points
void visibilityChanged(QTreeWidgetItem *, int)


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:08