HsvColorSegmentationWidgetController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * \package VisionX::gui-plugins::HsvColorSegmentationWidgetController
17  * \author Rainer Kartmann ( rainer dot kartmann at student dot kit dot edu )
18  * \date 2018
19  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <pwd.h>
26 
29 
30 #include <QFileDialog>
31 #include <QMessageBox>
32 
33 // ivt
34 #include <Image/PrimitivesDrawer.h>
35 
36 #include <VisionX/interface/core/ImageProviderInterface.h>
38 
39 
40 using namespace armarx;
41 
42 
43 const QStringList HsvColorSegmentationWidgetController::COLOR_PARAMETER_NAMES =
44 {
45  "none", "blue", "blue2", "blue3", "colored", "green", "green2", "green3",
46  "orange", "orange2", "orange3", "red", "red2", "red3", "skin", "white",
47  "yellow", "yellow2", "yellow3"
48 };
49 
50 const std::string HsvColorSegmentationWidgetController::DEFAULT_COLOR_PARAMETER_FILE =
51  // "armarx/VisionX/data/VisionX/examples/colors.txt";
52  "armarx/VisionX/data/VisionX/examples/cebit-colors.txt";
53 
54 
55 
57 {
58  widget.setupUi(getWidget());
59 
60  widget.comboBoxColor->addItems(COLOR_PARAMETER_NAMES);
61  widget.comboBoxColor->setCurrentIndex(0);
62  currentColorIndex = 0;
63 
64  autoValues.resize(NUM_PARAMS, 0);
65 
66 
67  guiAutoCheckBoxes.resize(NUM_PARAMS);
68  guiAutoCheckBoxes[HUE_MID] = widget.checkBoxAutoHue;
69  guiAutoCheckBoxes[HUE_TOL] = widget.checkBoxAutoHueTol;
70  guiAutoCheckBoxes[SAT_MIN] = widget.checkBoxAutoSatMin;
71  guiAutoCheckBoxes[SAT_MAX] = widget.checkBoxAutoSatMax;
72  guiAutoCheckBoxes[VAL_MIN] = widget.checkBoxAutoValMin;
73  guiAutoCheckBoxes[VAL_MAX] = widget.checkBoxAutoValMax;
74 
75  guiValueSpinBoxes.resize(NUM_PARAMS);
76  guiValueSpinBoxes[HUE_MID] = widget.spinBoxHue;
77  guiValueSpinBoxes[HUE_TOL] = widget.spinBoxHueTol;
78  guiValueSpinBoxes[SAT_MIN] = widget.spinBoxSatMin;
79  guiValueSpinBoxes[SAT_MAX] = widget.spinBoxSatMax;
80  guiValueSpinBoxes[VAL_MIN] = widget.spinBoxValMin;
81  guiValueSpinBoxes[VAL_MAX] = widget.spinBoxValMax;
82 
83  guiValueSliders.resize(NUM_PARAMS);
84  guiValueSliders[HUE_MID] = widget.sliderHue;
85  guiValueSliders[HUE_TOL] = widget.sliderHueTol;
86  guiValueSliders[SAT_MIN] = widget.sliderSatMin;
87  guiValueSliders[SAT_MAX] = widget.sliderSatMax;
88  guiValueSliders[VAL_MIN] = widget.sliderValMin;
89  guiValueSliders[VAL_MAX] = widget.sliderValMax;
90 
91 
92  // proxy finder
94  proxyFinder->setSearchMask("*Provider|*Result");
95  widget.layoutChooseProvider->addWidget(proxyFinder);
96 
97 
98  // image viewer input
99  imageViewerInput = new SelectableImageViewer();
100  QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
101  imageViewerInput->setSizePolicy(sizePolicy);
102 
103  widget.layoutImageViewerInput->addWidget(imageViewerInput);
104  imageViewerInput->show();
105 
106 
107  // image viewer output
108  imageViewerOutput = new visionx::ImageViewerArea();
109  //QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
110  imageViewerOutput->setSizePolicy(sizePolicy);
111 
112  widget.layoutImageViewerOutput->addWidget(imageViewerOutput);
113  imageViewerOutput->show();
114 
115 
116  armarx::CMakePackageFinder finder("VisionX");
117  if (finder.packageFound())
118  {
119  ARMARX_INFO << "Adding to datapaths: " << finder.getDataDir();
121  }
122 }
123 
124 
126 {
127 
128 }
129 
130 
132 {
133  widget.lineEditColorParameterFile->setText(settings->value("ColorParameterFile", getDefaultColorParameterFile()).toString());
135 }
136 
138 {
139  settings->setValue("ColorParameterFile", widget.lineEditColorParameterFile->text());
140 }
141 
142 
144 {
145  proxyFinder->setIceManager(this->getIceManager(), proxyFinder->getSelectedProxyName().isEmpty());
146 
147  connected = false;
148  isPaused = true;
149 
150  connect(widget.buttonConnect, SIGNAL(clicked(bool)), this, SLOT(clickedButtonConnect(bool)));
151  connect(widget.buttonDisconnect, SIGNAL(clicked(bool)), this, SLOT(clickedButtonDisconnect(bool)));
152  connect(widget.buttonPlayPause, SIGNAL(clicked(bool)), this, SLOT(clickedButtonPlayPause(bool)));
153 
154  // image viewer selection
155  connect(imageViewerInput, SIGNAL(selected(int, float, float)), this, SLOT(addColorSelection(int, float, float)));
156  connect(widget.buttonClearSelectedPoints, SIGNAL(pressed()), this, SLOT(clearColorSelection()));
157 
158  // COLOR SETTINGS
159 
160  connect(widget.buttonColorSettingsReset, SIGNAL(pressed()), this, SLOT(resetCurrentColorSettings()));
161 
162  // sliders to manual setters
163  connect(widget.sliderHue, SIGNAL(valueChanged(int)), this, SLOT(setManualHueMid(int)));
164  connect(widget.sliderHueTol, SIGNAL(valueChanged(int)), this, SLOT(setManualHueTol(int)));
165  connect(widget.sliderSatMin, SIGNAL(valueChanged(int)), this, SLOT(setManualSatMin(int)));
166  connect(widget.sliderSatMax, SIGNAL(valueChanged(int)), this, SLOT(setManualSatMax(int)));
167  connect(widget.sliderValMin, SIGNAL(valueChanged(int)), this, SLOT(setManualValMin(int)));
168  connect(widget.sliderValMax, SIGNAL(valueChanged(int)), this, SLOT(setManualValMax(int)));
169 
170  // spin boxes to manual setters
171  connect(widget.spinBoxHue, SIGNAL(valueChanged(int)), this, SLOT(setManualHueMid(int)));
172  connect(widget.spinBoxHueTol, SIGNAL(valueChanged(int)), this, SLOT(setManualHueTol(int)));
173  connect(widget.spinBoxSatMin, SIGNAL(valueChanged(int)), this, SLOT(setManualSatMin(int)));
174  connect(widget.spinBoxSatMax, SIGNAL(valueChanged(int)), this, SLOT(setManualSatMax(int)));
175  connect(widget.spinBoxValMin, SIGNAL(valueChanged(int)), this, SLOT(setManualValMin(int)));
176  connect(widget.spinBoxValMax, SIGNAL(valueChanged(int)), this, SLOT(setManualValMax(int)));
177 
178  // check boxes to auto setters
179  connect(widget.checkBoxAutoAll, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAutoAll(bool)));
180  connect(widget.checkBoxAutoHue, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
181  connect(widget.checkBoxAutoHueTol, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
182  connect(widget.checkBoxAutoSatMin, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
183  connect(widget.checkBoxAutoSatMax, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
184  connect(widget.checkBoxAutoValMin, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
185  connect(widget.checkBoxAutoValMax, SIGNAL(toggled(bool)), this, SLOT(onToggledCheckBoxAuto(bool)));
186 
187  connect(widget.spinBoxAddTol, SIGNAL(valueChanged(int)), this, SLOT(onChangedAddTolerance(int)));
188 
189 
190  // color selection
191 
192  connect(widget.comboBoxColor, SIGNAL(currentIndexChanged(int)), this, SLOT(onColorIndexChanged(int)));
193  connect(widget.buttonColorParameterFileSearch, SIGNAL(pressed()), this, SLOT(searchColorParameterFile()));
194  connect(widget.buttonColorParameterFileReset, SIGNAL(pressed()), this, SLOT(resetColorParameterFile()));
195  connect(widget.buttonColorParametersReload, SIGNAL(pressed()), this, SLOT(loadColorParameterSetFromFile()));
196  connect(widget.buttonColorParametersSave, SIGNAL(pressed()), this, SLOT(saveColorParameterSetToFile()));
197 
198 
199  // inner connections
200  connect(this, SIGNAL(imageProviderConnected(bool)), this, SLOT(updateImageMonitorUI()));
201 
202 
205 }
206 
208 {
209 
210 }
211 
213 {
214 
215 }
216 
218 {
219 
220 }
221 
222 
223 void HsvColorSegmentationWidgetController::reconnect()
224 {
225  std::unique_lock lock(imageMutex);
226 
227  disconnectFromProvider();
228 
229  // connect to provider
230  try
231  {
232  connectToProvider();
233  }
234  catch (...)
235  {
237  }
238 }
239 
240 void HsvColorSegmentationWidgetController::connectToProvider()
241 {
242  if (connected)
243  {
244  return;
245  }
246 
247  std::unique_lock lock(imageMutex);
248 
249  imageProviderName = proxyFinder->getSelectedProxyName().toStdString();
250  ARMARX_INFO << "Trying to connect to provider " << imageProviderName;
251 
252  usingImageProvider(imageProviderName);
253 
254  ARMARX_INFO << getName() << " connecting to " << imageProviderName;
255 
256  // connect to proxy
257  imageProviderInfo = getImageProvider(imageProviderName, visionx::tools::typeNameToImageType("rgb"));
258 
259  int width = imageProviderInfo.imageFormat.dimension.width;
260  int height = imageProviderInfo.imageFormat.dimension.height;
261 
262  segmentation = HsvImageSegmentation(imageProviderInfo);
263 
264  bool makeResultImageNamePretty = false;
265  std::string managedIceObjectName;
266  if (makeResultImageNamePretty)
267  {
268  managedIceObjectName = getName();
270  }
271 
272  ARMARX_INFO << "Enabling result images";
273  enableResultImages(numImages, visionx::ImageDimension(width, height), visionx::ImageType::eRgb);
274 
275  if (makeResultImageNamePretty)
276  {
277  setName(managedIceObjectName);
278  }
279 
280  isPaused = false;
281  connected = true;
282 
283  emit imageProviderConnected(true);
284 }
285 
286 void HsvColorSegmentationWidgetController::disconnectFromProvider()
287 {
288  if (!connected)
289  {
290  return;
291  }
292 
293  ARMARX_WARNING << "ImageProcessor does not allow re-enabling result images. "
294  "If you connect to another image provider, there might be "
295  "errors in the result images due to different image formats.";
296 
297  ARMARX_INFO << "Disconnecting from provider " << imageProviderName;
298 
299  std::unique_lock lock(imageMutex);
300  segmentation = HsvImageSegmentation();
301 
302  releaseImageProvider(imageProviderName);
303 
304  imageProviderPrx = 0;
305 
306  connected = false;
307  isPaused = true;
308 
309  emit imageProviderConnected(false);
310 }
311 
312 
314 {
315  std::unique_lock lock(imageMutex);
316 
317  if (!lock.owns_lock())
318  {
319  ARMARX_INFO << deactivateSpam(3) << "unable to process next image(" << lock.owns_lock() << ")";
320  return;
321  }
322 
323  if (!connected)
324  {
325  ARMARX_INFO << deactivateSpam(3) << "Not connected to any image provider";
326  return;
327  }
328 
329  armarx::MetaInfoSizeBasePtr info;
330  IceUtil::Time timeReceived;
331  if (!isPaused)
332  {
333  //only update current image if unpaused
334  if (!waitForImages(imageProviderName))
335  {
336  ARMARX_WARNING << "Timeout while waiting for images";
337  return;
338  }
339 
340  if (getImages(imageProviderName, segmentation.getInputImagesRgb(), info) != numImages)
341  {
342  ARMARX_WARNING << "Unable to transfer or read images";
343  return;
344  }
345  timeReceived = TimeUtil::GetTime();
346  }
347 
348  // perform segmentation
349  segmentation.processInputImages(value(HUE_MID), value(HUE_TOL), value(SAT_MIN),
350  value(SAT_MAX), value(VAL_MIN), value(VAL_MAX));
351 
352  // draw selected points on current input images
353  drawSelectedPoints();
354 
355  // update image viewers
356  imageViewerInput->setImages(numImages, segmentation.getInputVisuImages(), IceUtil::Time::microSeconds(info->timeProvided), timeReceived);
357  imageViewerOutput->setImages(numImages, segmentation.getOutputImagesRgb(), IceUtil::Time::microSeconds(info->timeProvided), timeReceived);
358 
359  // publish results
360  provideResultImages(segmentation.getOutputImagesRgb());
361 }
362 
363 
364 
365 
367 {
368  reconnect();
369 }
370 
372 {
373  disconnectFromProvider();
374 }
375 
377 {
378  if (!connected)
379  {
380  isPaused = false;
381  }
382  else
383  {
384  isPaused = !isPaused;
385  }
387 }
388 
389 void HsvColorSegmentationWidgetController::addColorSelection(int imageIndex, float x, float y)
390 {
391  if (!connected)
392  {
393  return;
394  }
395 
396  // lookup pixel value in respective image
397 
398  int red, green, blue;
399  {
400  std::unique_lock lock(imageMutex);
401 
402  CByteImage* image = segmentation.getInputImagesRgb()[imageIndex];
403  int col = image->width * x;
404  int row = image->height * y;
405 
406  if (image->type != CByteImage::eRGB24)
407  {
408  ARMARX_WARNING << "Input image type is not eRGB24 (is " << image->type
409  << " instead of " << CByteImage::eRGB24 << ")";
410  }
411 
412  int pixelIndex = 0;
413  pixelIndex += row * image->width * image->bytesPerPixel; // skip rows
414  pixelIndex += col * image->bytesPerPixel; // skip columns in row
415 
416  red = image->pixels[pixelIndex];
417  green = image->pixels[pixelIndex + 1];
418  blue = image->pixels[pixelIndex + 2];
419  }
420 
421 
422  // convert to HSV and store point
423 
424  SelectedPoint sp(imageIndex, x, y, red, green, blue);
425 
426  selectedPoints.push_back(sp);
427 
428  // update
429  onSelectedPointsChanged();
430 }
431 
432 
434 {
435  selectedPoints.clear();
436  onSelectedPointsChanged();
437 }
438 
440 {
441  if (dirtyColors.find(widget.comboBoxColor->currentIndex()) == dirtyColors.end())
442  {
443  markCurrentColorDirty();
444  }
445 
446  updateColorVisualization();
447 
448  widget.buttonColorParametersSave->setText("Save");
449 }
450 
452 {
453  saveCurrentColorParameters(currentColorIndex);
454  loadCurrentColorParameters(value);
455  currentColorIndex = value;
456 }
457 
458 
460 {
461  guiAutoCheckBoxes[HUE_MID]->setChecked(false);
463 }
464 
466 {
467  guiAutoCheckBoxes[HUE_TOL]->setChecked(false);
469 }
470 
472 {
473  guiAutoCheckBoxes[SAT_MIN]->setChecked(false);
475 }
476 
478 {
479  guiAutoCheckBoxes[SAT_MAX]->setChecked(false);
481 }
482 
484 {
485  guiAutoCheckBoxes[VAL_MIN]->setChecked(false);
487 }
488 
490 {
491  guiAutoCheckBoxes[VAL_MAX]->setChecked(false);
493 }
494 
496 {
497  widget.checkBoxAutoHue->setChecked(enabled);
498  widget.checkBoxAutoHueTol->setChecked(enabled);
499  widget.checkBoxAutoSatMin->setChecked(enabled);
500  widget.checkBoxAutoSatMax->setChecked(enabled);
501  widget.checkBoxAutoValMin->setChecked(enabled);
502  widget.checkBoxAutoValMax->setChecked(enabled);
503 
505 }
506 
508 {
509  if (enabled)
510  {
511  updateAutoValuesUI();
513  }
514 }
515 
517 {
518  recomputeAutoValues();
519  updateAutoValuesUI();
520 }
521 
523 {
524  loadCurrentColorParameters(widget.comboBoxColor->currentIndex());
525 }
526 
528 {
529  if (showMsgBoxes && !dirtyColors.empty())
530  {
531  QMessageBox msgBox;
532  msgBox.setText("Unsaved changes");
533  std::stringstream infText;
534  infText << "There are colors with unsaved changes: \n\n";
535  for (int i : dirtyColors)
536  {
537  infText << COLOR_PARAMETER_NAMES.at(i).toStdString() << " ";
538  }
539  infText << "\n\nAre you sure to discard these changes?";
540 
541  msgBox.setInformativeText(QString::fromStdString(infText.str()));
542  msgBox.setIcon(QMessageBox::Question);
543  msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
544  msgBox.setDefaultButton(QMessageBox::Discard);
545  int option = msgBox.exec();
546  if (option == QMessageBox::Cancel)
547  {
548  return; // cancel
549  }
550  }
551 
552  std::string fileName = colorParameterFile();
553  if (!ArmarXDataPath::getAbsolutePath(fileName, fileName))
554  {
555  ARMARX_WARNING << "Could not find color parameter file in ArmarXDataPath: " << fileName;
556  }
557 
558  bool success = colorParameterSet.LoadFromFile(fileName.c_str());
559  if (!success)
560  {
561  if (showMsgBoxes)
562  {
563  std::stringstream text;
564  text << "Failed to load color parameters from file:\n\n"
565  << "" << fileName << "\n\n"
566  << "Please check whether the file exists and is readable.";
567 
568  QMessageBox msgBox;
569  msgBox.setText("Could not load color parameters.");
570  msgBox.setInformativeText(QString::fromStdString(text.str()));
571  msgBox.setIcon(QMessageBox::Warning);
572  msgBox.exec();
573  }
574 
575 
576  return;
577  }
578 
579  widget.lineEditColorParameterFile->setText(QString::fromStdString(fileName));
580  loadCurrentColorParameters(widget.comboBoxColor->currentIndex());
581 
582  markAllColorsClean();
583 }
584 
586 {
587  saveCurrentColorParameters(widget.comboBoxColor->currentIndex());
588 
589  bool success = colorParameterSet.SaveToFile(colorParameterFile().c_str());
590  if (!success)
591  {
592  std::stringstream text;
593  text << "Failed to save color parameters to file:\n\n"
594  << "" << colorParameterFile() << "\n\n"
595  << "Please check whether the file is writable.";
596 
597  QMessageBox msgBox;
598  msgBox.setText("Could not save color parameters.");
599  msgBox.setInformativeText(QString::fromStdString(text.str()));
600  msgBox.setIcon(QMessageBox::Warning);
601  msgBox.exec();
602 
603  return;
604  }
605 
606  markAllColorsClean();
607  widget.buttonColorParametersSave->setText("Saved");
608 }
609 
611 {
612  QString selectedFile = QFileDialog::getOpenFileName(
613  widget.buttonColorParameterFileSearch,
614  tr("Choose Color Parameter File"),
615  widget.lineEditColorParameterFile->text());
616 
617  if (!selectedFile.isNull())
618  {
619  widget.lineEditColorParameterFile->setText(selectedFile);
620  }
621 }
622 
624 {
625  widget.lineEditColorParameterFile->setText(getDefaultColorParameterFile());
626 }
627 
628 
629 int HsvColorSegmentationWidgetController::value(int param)
630 {
631  return guiValueSpinBoxes[param]->value();
632 }
633 
634 int HsvColorSegmentationWidgetController::hueMin()
635 {
636  return std::max(0, value(HUE_MID) - value(HUE_TOL));
637 }
638 
639 int HsvColorSegmentationWidgetController::hueMax()
640 {
641  return std::min(179, value(HUE_MID) + value(HUE_TOL));
642 }
643 
644 int HsvColorSegmentationWidgetController::satMid()
645 {
646  return 0.5 * (value(SAT_MIN) + value(SAT_MAX));
647 }
648 
649 int HsvColorSegmentationWidgetController::valMid()
650 {
651  return 0.5 * (value(VAL_MIN) + value(VAL_MAX));
652 }
653 
654 bool HsvColorSegmentationWidgetController::isAutoEnabled(int param)
655 {
656  return guiAutoCheckBoxes[param]->isChecked();
657 }
658 
659 int HsvColorSegmentationWidgetController::additionalTolerance()
660 {
661  return widget.spinBoxAddTol->value();
662 }
663 
664 std::string HsvColorSegmentationWidgetController::colorParameterFile()
665 {
666  return widget.lineEditColorParameterFile->text().toStdString();
667 }
668 
669 void HsvColorSegmentationWidgetController::recomputeAutoValues()
670 {
671  for (int i = 0; i < NUM_PARAMS; ++i)
672  {
673  autoValues[i] = 0;
674  }
675 
676  if (selectedPoints.empty())
677  {
678  return; // all 0
679  }
680 
681  // compute minima and maxima
682 
683  // trigger min() in first element by setting mins to 255
684  int hueMin = 179;
685  int hueMax = 0;
686  autoValues[SAT_MIN] = 255;
687  autoValues[VAL_MIN] = 255;
688 
689  auto setMin = [](int& target, int compare)
690  {
692  };
693  auto setMax = [](int& target, int compare)
694  {
696  };
697 
698  for (SelectedPoint& p : selectedPoints)
699  {
700  setMin(hueMin, p.hue);
701  setMax(hueMax, p.hue);
702  setMin(autoValues[SAT_MIN], p.sat);
703  setMax(autoValues[SAT_MAX], p.sat);
704  setMin(autoValues[VAL_MIN], p.val);
705  setMax(autoValues[VAL_MAX], p.val);
706  }
707 
708  // correct hue mid and tol
709 
710  int hueMid = (hueMin + hueMax) / 2;
711  int hueTol = std::max(hueMax - hueMid, hueMid - hueMin);
712 
713  autoValues[HUE_MID] = hueMid;
714  autoValues[HUE_TOL] = hueTol;
715 
716 
717  // add / subtract additional tolerance
718  int tolerance = additionalTolerance();
719 
720  auto clampedAdd = [](int& target, int addSub, int maxMin)
721  {
722  if (addSub > 0)
723  {
724  target = std::min(target + addSub, maxMin);
725  }
726  else if (addSub < 0)
727  {
728  target = std::max(target + addSub, maxMin);
729  }
730  };
731 
732  clampedAdd(autoValues[HUE_TOL], 2 * tolerance, 179);
733 
734  clampedAdd(autoValues[SAT_MIN], - tolerance, 0);
735  clampedAdd(autoValues[SAT_MAX], tolerance, 255);
736 
737  clampedAdd(autoValues[VAL_MIN], - tolerance, 0);
738  clampedAdd(autoValues[VAL_MAX], tolerance, 255);
739 
740 }
741 
742 void HsvColorSegmentationWidgetController::onSelectedPointsChanged()
743 {
744  recomputeAutoValues();
745  updateAutoValuesUI();
746 
747  std::stringstream num;
748  num << selectedPoints.size();
749  widget.labelSelectedPointsNum->setText(QString(num.str().c_str()));
750 
752 }
753 
754 void HsvColorSegmentationWidgetController::drawSelectedPoints()
755 {
756  CByteImage** inputVisuImages = segmentation.getInputVisuImages();
757 
758  int radius = 20;
759  for (SelectedPoint& sp : selectedPoints)
760  {
761  CByteImage* image = inputVisuImages[sp.imageIndex];
762  PrimitivesDrawer::DrawCircle(
763  image, sp.xRel * image->width, sp.yRel * image->height, radius,
764  sp.red, sp.green, sp.blue, -1); // fill
765 
766  PrimitivesDrawer::DrawCircle(
767  image, sp.xRel * image->width, sp.yRel * image->height, radius,
768  0, 0, 0, 2); // border
769  }
770 }
771 
772 
773 void HsvColorSegmentationWidgetController::saveCurrentColorParameters(int colorIndex)
774 {
775  std::string colorName = COLOR_PARAMETER_NAMES.at(colorIndex).toStdString();
776 
777  ObjectColor objectColor = CColorParameterSet::Translate(colorName.c_str());
778 
779  colorParameterSet.SetColorParameters(objectColor,
780  value(HUE_MID), value(HUE_TOL),
781  value(SAT_MIN), value(SAT_MAX),
782  value(VAL_MIN), value(VAL_MAX));
783 }
784 
785 void HsvColorSegmentationWidgetController::loadCurrentColorParameters(int colorIndex)
786 {
787  // setting the new values will cause the new color to be marked dirty
788  // we have to check beforehand and restore the marker afterwards
789  bool isDirty = dirtyColors.find(colorIndex) != dirtyColors.end();
790 
791  std::string colorName = COLOR_PARAMETER_NAMES.at(colorIndex).toStdString();
792 
793  ObjectColor objectColor = CColorParameterSet::Translate(colorName.c_str());
794 
795  const int* params = colorParameterSet.GetColorParameters(objectColor);
796 
797  widget.spinBoxHue->setValue(params[0]);
798  widget.spinBoxHueTol->setValue(params[1]);
799  widget.spinBoxSatMin->setValue(params[2]);
800  widget.spinBoxSatMax->setValue(params[3]);
801  widget.spinBoxValMin->setValue(params[4]);
802  widget.spinBoxValMax->setValue(params[5]);
803 
804  widget.checkBoxAutoAll->setChecked(false);
805 
806  if (isDirty)
807  {
808  markCurrentColorDirty();
809  }
810  else
811  {
812  markCurrentColorClean();
813  }
814 }
815 
816 
817 void HsvColorSegmentationWidgetController::updatePausePlayButtonText()
818 {
819  const char* text = isPaused ? "Play" : "Pause";
820  widget.buttonPlayPause->setText(text);
821 }
822 
824 {
825  updatePausePlayButtonText();
826 
827  widget.buttonDisconnect->setEnabled(connected);
828  widget.buttonPlayPause->setEnabled(connected);
829 
830  QString statusString;
831  if (connected)
832  {
833  std::stringstream ss;
834  ss << "Status: connected to image provider \n" << imageProviderName;
835  ss << " (" << numImages << " imgs, " << imageWidth << "x" << imageHeight << ")";
836 
837  if (isPaused)
838  {
839  ss << " - PAUSED";
840  }
841  statusString = QString::fromStdString(ss.str());
842  }
843  else
844  {
845  statusString = "Status: not connected";
846  }
847  widget.labelImageMonitorStatus->setText(statusString);
848 }
849 
850 void HsvColorSegmentationWidgetController::setUiParamValue(int param, int value)
851 {
852  guiValueSpinBoxes[param]->setValue(value);
853  guiValueSliders[param]->setValue(value);
854 }
855 
856 void HsvColorSegmentationWidgetController::updateAutoValuesUI()
857 {
858  for (int i = 0; i < NUM_PARAMS; ++i)
859  {
860  if (isAutoEnabled(i))
861  {
862  setUiParamValue(i, autoValues[i]);
863  guiAutoCheckBoxes[i]->setChecked(true);
864  }
865  }
866 }
867 
868 void HsvColorSegmentationWidgetController::updateColorVisualization()
869 {
870  // mid color preview
871 
872  QPalette previewPalette = widget.labelColorPreview->palette();
873  previewPalette.setColor(QPalette::Background, QColor::fromHsv(value(HUE_MID), satMid(), valMid()));
874  widget.labelColorPreview->setPalette(previewPalette);
875 
876 
877  // gradients
878 
879  // create gradians
880  QLinearGradient gradHue = QLinearGradient(0, 0, 0, widget.labelGradHue->height());
881  QLinearGradient gradSat = QLinearGradient(0, 0, 0, widget.labelGradSat->height());
882  QLinearGradient gradVal = QLinearGradient(0, 0, 0, widget.labelGradVal->height());
883 
884  // set gradians
885  int numHueSamples = 10;
886  int hMin = hueMin();
887  int hMax = hueMax();
888  for (int i = 0; i <= numHueSamples; ++i)
889  {
890  float interpol = float(i) / numHueSamples;
891  int value = int(hMin * (1 - interpol) + hMax * interpol);
892  // Qt uses a hue range of 0-359
893  gradHue.setColorAt(interpol, QColor::fromHsv(2 * value, 255, 255));
894  }
895 
896  gradSat.setColorAt(0, QColor::fromHsv(value(HUE_MID), value(SAT_MIN), 255));
897  gradSat.setColorAt(1, QColor::fromHsv(value(HUE_MID), value(SAT_MAX), 255));
898 
899  gradVal.setColorAt(0, QColor::fromHsv(0, 0, value(VAL_MIN)));
900  gradVal.setColorAt(1, QColor::fromHsv(0, 0, value(VAL_MAX)));
901 
902 
903  // assignGradients
904  auto setGradient = [](QLabel * label, const QLinearGradient & gradient)
905  {
906  QPalette palette = label->palette();
907  palette.setBrush(QPalette::Background, gradient);
908  label->setPalette(palette);
909  };
910 
911  setGradient(widget.labelGradHue, gradHue);
912  setGradient(widget.labelGradSat, gradSat);
913  setGradient(widget.labelGradVal, gradVal);
914 }
915 
916 void HsvColorSegmentationWidgetController::markCurrentColorDirty()
917 {
918  int idx = widget.comboBoxColor->currentIndex();
919  QString newText = COLOR_PARAMETER_NAMES.at(idx) + "*";
920  widget.comboBoxColor->setItemText(idx, newText);
921 
922  dirtyColors.insert(idx);
923 }
924 
925 void HsvColorSegmentationWidgetController::markCurrentColorClean()
926 {
927  int idx = widget.comboBoxColor->currentIndex();
928  widget.comboBoxColor->setItemText(idx, COLOR_PARAMETER_NAMES.at(idx));
929  dirtyColors.erase(idx);
930 }
931 
932 void HsvColorSegmentationWidgetController::markAllColorsClean()
933 {
934  for (int i = 0; i < widget.comboBoxColor->count(); ++i)
935  {
936  widget.comboBoxColor->setItemText(i, COLOR_PARAMETER_NAMES.at(i));
937  }
938  dirtyColors.clear();
939 }
940 
941 void HsvColorSegmentationWidgetController::rgbToHsv(int r, int g, int b, int& h, int& s, int& v)
942 {
943  // let ivt convert an 1x1 pixel image...
944 
945  CByteImage rgb(1, 1, CByteImage::eRGB24);
946  CByteImage hsv(1, 1, CByteImage::eRGB24);
947 
948  rgb.pixels[0] = r;
949  rgb.pixels[1] = g;
950  rgb.pixels[2] = b;
951 
952  ::ImageProcessor::CalculateHSVImage(&rgb, &hsv);
953 
954  h = hsv.pixels[0];
955  s = hsv.pixels[1];
956  v = hsv.pixels[2];
957 }
958 
959 std::string HsvColorSegmentationWidgetController::getHomeDirectory()
960 {
961  // check HOME environment variable
962  char* homeDir = getenv("HOME");
963 
964  if (!homeDir)
965  {
966  // HOME not set
967  passwd* pw = getpwuid(getuid());
968  homeDir = pw->pw_dir;
969  }
970 
971  return std::string(homeDir);
972 }
973 
974 QString HsvColorSegmentationWidgetController::getDefaultColorParameterFile()
975 {
976  std::stringstream path;
977  path << getHomeDirectory();
978  path << "/" << DEFAULT_COLOR_PARAMETER_FILE;
979 
980  return QString::fromStdString(path.str());
981 }
982 
983 
armarx::HsvColorSegmentationWidgetController::onInitImageProcessor
virtual void onInitImageProcessor() override
Setup the vision component.
Definition: HsvColorSegmentationWidgetController.cpp:143
armarx::ManagedIceObject::setName
void setName(std::string name)
Override name of well-known object.
Definition: ManagedIceObject.cpp:426
armarx::HsvImageSegmentation::processInputImages
void processInputImages(int hue, int hueTol, int satMin, int satMax, int valMin, int valMax)
Processes the current input images.
Definition: HsvImageSegmentation.cpp:81
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:353
armarx::HsvColorSegmentationWidgetController::onExitImageProcessor
virtual void onExitImageProcessor() override
Exit the ImapeProcessor component.
Definition: HsvColorSegmentationWidgetController.cpp:217
armarx::CMakePackageFinder::packageFound
bool packageFound() const
Returns whether or not this package was found with cmake.
Definition: CMakePackageFinder.cpp:485
armarx::HsvColorSegmentationWidgetController::saveColorParameterSetToFile
void saveColorParameterSetToFile()
Definition: HsvColorSegmentationWidgetController.cpp:585
armarx::HsvColorSegmentationWidgetController::GetWidgetName
static QString GetWidgetName()
Returns the Widget name displayed in the ArmarXGui to create an instance of this class.
Definition: HsvColorSegmentationWidgetController.h:106
armarx::HsvColorSegmentationWidgetController::onToggledCheckBoxAutoAll
void onToggledCheckBoxAutoAll(bool enabled)
Definition: HsvColorSegmentationWidgetController.cpp:495
visionx::ImageProcessor::getImageProvider
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
Definition: ImageProcessor.cpp:152
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:688
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:53
visionx::ImageProviderInfo::imageFormat
ImageFormatInfo imageFormat
Image format struct that contains all necessary image information.
Definition: ImageProcessor.h:496
visionx::ImageViewerArea
Definition: ImageViewerArea.h:38
armarx::HsvColorSegmentationWidgetController::setManualHueMid
void setManualHueMid(int value)
Definition: HsvColorSegmentationWidgetController.cpp:459
armarx::HsvColorSegmentationWidgetController::updateImageMonitorUI
void updateImageMonitorUI()
Definition: HsvColorSegmentationWidgetController.cpp:823
armarx::HsvColorSegmentationWidgetController::onColorIndexChanged
void onColorIndexChanged(int value)
Definition: HsvColorSegmentationWidgetController.cpp:451
visionx::ImageViewerArea::setImages
void setImages(int numberImages, CByteImage **images, IceUtil::Time imageTimestamp, IceUtil::Time receiveTimestamp)
Definition: ImageViewerArea.cpp:80
armarx::HsvImageSegmentation
The HsvImageSegmentation class.
Definition: HsvImageSegmentation.h:24
armarx::HsvColorSegmentationWidgetController::setManualValMax
void setManualValMax(int value)
Definition: HsvColorSegmentationWidgetController.cpp:489
armarx::HsvColorSegmentationWidgetController::searchColorParameterFile
void searchColorParameterFile()
Definition: HsvColorSegmentationWidgetController.cpp:610
armarx::HsvColorSegmentationWidgetController::process
virtual void process() override
Process the vision component.
Definition: HsvColorSegmentationWidgetController.cpp:313
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::HsvColorSegmentationWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: HsvColorSegmentationWidgetController.cpp:137
armarx::HsvColorSegmentationWidgetController::~HsvColorSegmentationWidgetController
virtual ~HsvColorSegmentationWidgetController()
Controller destructor.
Definition: HsvColorSegmentationWidgetController.cpp:125
armarx::HsvColorSegmentationWidgetController::addColorSelection
void addColorSelection(int imageIndex, float x, float y)
Definition: HsvColorSegmentationWidgetController.cpp:389
armarx::HsvColorSegmentationWidgetController::setManualSatMax
void setManualSatMax(int value)
Definition: HsvColorSegmentationWidgetController.cpp:477
armarx::HsvColorSegmentationWidgetController::onDisconnectImageProcessor
virtual void onDisconnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component looses network ...
Definition: HsvColorSegmentationWidgetController.cpp:212
armarx::HsvColorSegmentationWidgetController::resetCurrentColorSettings
void resetCurrentColorSettings()
Definition: HsvColorSegmentationWidgetController.cpp:522
armarx::HsvColorSegmentationWidgetController::clickedButtonPlayPause
void clickedButtonPlayPause(bool toggled)
Definition: HsvColorSegmentationWidgetController.cpp:376
armarx::CMakePackageFinder::getDataDir
std::string getDataDir() const
Definition: CMakePackageFinder.h:176
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
visionx::ImageProcessor::usingImageProvider
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
Definition: ImageProcessor.cpp:117
armarx::HsvColorSegmentationWidgetController::onChangedAddTolerance
void onChangedAddTolerance(int value)
Definition: HsvColorSegmentationWidgetController.cpp:516
armarx::HsvColorSegmentationWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: HsvColorSegmentationWidgetController.cpp:131
armarx::HsvColorSegmentationWidgetController::clearColorSelection
void clearColorSelection()
Definition: HsvColorSegmentationWidgetController.cpp:433
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::HsvColorSegmentationWidgetController::loadColorParameterSetFromFile
void loadColorParameterSetFromFile(bool showMsgBoxes=true)
Loads the color parameter set from file and update the gui.
Definition: HsvColorSegmentationWidgetController.cpp:527
visionx::ImageProcessor::getImages
int getImages(CByteImage **ppImages)
Poll images from provider.
Definition: ImageProcessor.cpp:351
armarx::HsvImageSegmentation::getOutputImagesRgb
CByteImage ** getOutputImagesRgb() const
Get the output images in RGB (from gray scale).
Definition: HsvImageSegmentation.cpp:71
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::red
QColor red()
Definition: StyleSheets.h:76
armarx::HsvColorSegmentationWidgetController::imageProviderConnected
void imageProviderConnected(bool connected)
armarx::detail::compare
int compare(const T &lhs, const T &rhs)
Definition: TreeWidgetBuilder.h:278
armarx::HsvImageSegmentation::getInputVisuImages
CByteImage ** getInputVisuImages() const
Get input visualization images.
Definition: HsvImageSegmentation.cpp:61
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
HsvColorSegmentationWidgetController.h
armarx::SelectableImageViewer
A clickable, i.e. selectable, visionx::ImageViewerArea.
Definition: SelectableImageViewer.h:44
CMakePackageFinder.h
option
#define option(type, fn)
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::HsvColorSegmentationWidgetController::setManualHueTol
void setManualHueTol(int value)
Definition: HsvColorSegmentationWidgetController.cpp:465
float
#define float
Definition: 16_Level.h:22
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ArmarXDataPath::addDataPaths
static void addDataPaths(const std::string &dataPathList)
Definition: ArmarXDataPath.cpp:559
visionx::ImageProcessor::enableResultImages
void enableResultImages(int numberImages, ImageDimension imageDimension, ImageType imageType, const std::string &name="")
Enables visualization.
Definition: ImageProcessor.cpp:227
armarx::IceProxyFinder< visionx::ImageProviderInterfacePrx >
armarx::HsvColorSegmentationWidgetController::HsvColorSegmentationWidgetController
HsvColorSegmentationWidgetController()
Controller Constructor.
Definition: HsvColorSegmentationWidgetController.cpp:56
armarx::HsvColorSegmentationWidgetController::onToggledCheckBoxAuto
void onToggledCheckBoxAuto(bool enabled)
Definition: HsvColorSegmentationWidgetController.cpp:507
visionx::tools::typeNameToImageType
ImageType typeNameToImageType(const std::string &imageTypeName)
Converts an image type name as string into an ImageType integer.
Definition: TypeMapping.cpp:42
armarx::viz::toString
const char * toString(InteractionFeedbackType type)
Definition: Interaction.h:27
armarx::HsvColorSegmentationWidgetController::setManualSatMin
void setManualSatMin(int value)
Definition: HsvColorSegmentationWidgetController.cpp:471
visionx::ImageProcessor::provideResultImages
void provideResultImages(CByteImage **images, armarx::MetaInfoSizeBasePtr info=nullptr)
sends result images for visualization
Definition: ImageProcessor.cpp:245
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:92
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
TypeMapping.h
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:111
visionx::ImageProcessor::releaseImageProvider
void releaseImageProvider(std::string providerName)
Definition: ImageProcessor.cpp:137
armarx::HsvColorSegmentationWidgetController::setManualValMin
void setManualValMin(int value)
Definition: HsvColorSegmentationWidgetController.cpp:483
armarx::HsvImageSegmentation::getInputImagesRgb
CByteImage ** getInputImagesRgb() const
Get the input images (RGB) (buffer).
Definition: HsvImageSegmentation.cpp:51
armarx::HsvColorSegmentationWidgetController::onColorSettingsChanged
void onColorSettingsChanged()
Definition: HsvColorSegmentationWidgetController.cpp:439
min
T min(T t1, T t2)
Definition: gdiam.h:42
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:141
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::HsvColorSegmentationWidgetController::resetColorParameterFile
void resetColorParameterFile()
Definition: HsvColorSegmentationWidgetController.cpp:623
ArmarXDataPath.h
armarx::HsvColorSegmentationWidgetController::clickedButtonDisconnect
void clickedButtonDisconnect(bool toggled)
Definition: HsvColorSegmentationWidgetController.cpp:371
armarx::HsvColorSegmentationWidgetController::clickedButtonConnect
void clickedButtonConnect(bool toggled)
Definition: HsvColorSegmentationWidgetController.cpp:366
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::HsvColorSegmentationWidgetController::onConnectImageProcessor
virtual void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
Definition: HsvColorSegmentationWidgetController.cpp:207
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::status::success
@ success
armarx::green
QColor green()
Definition: StyleSheets.h:72
visionx::ImageProcessor::waitForImages
bool waitForImages(int milliseconds=1000)
Wait for new images.
Definition: ImageProcessor.cpp:275