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