27 #include <QFileDialog>
28 #include <QMessageBox>
34 #include <VisionX/interface/core/ImageProviderInterface.h>
37 #include <Image/PrimitivesDrawer.h>
43 const QStringList HsvColorSegmentationWidgetController::COLOR_PARAMETER_NAMES = {
"none",
63 const std::string HsvColorSegmentationWidgetController::DEFAULT_COLOR_PARAMETER_FILE =
65 "armarx/VisionX/data/VisionX/examples/cebit-colors.txt";
71 widget.comboBoxColor->addItems(COLOR_PARAMETER_NAMES);
72 widget.comboBoxColor->setCurrentIndex(0);
73 currentColorIndex = 0;
75 autoValues.resize(NUM_PARAMS, 0);
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;
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;
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;
105 proxyFinder->setSearchMask(
"*Provider|*Result");
106 widget.layoutChooseProvider->addWidget(proxyFinder);
111 QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
112 imageViewerInput->setSizePolicy(sizePolicy);
114 widget.layoutImageViewerInput->addWidget(imageViewerInput);
115 imageViewerInput->show();
121 imageViewerOutput->setSizePolicy(sizePolicy);
123 widget.layoutImageViewerOutput->addWidget(imageViewerOutput);
124 imageViewerOutput->show();
142 widget.lineEditColorParameterFile->setText(
143 settings->value(
"ColorParameterFile", getDefaultColorParameterFile()).
toString());
150 settings->setValue(
"ColorParameterFile", widget.lineEditColorParameterFile->text());
157 proxyFinder->getSelectedProxyName().isEmpty());
169 connect(imageViewerInput,
170 SIGNAL(selected(
int,
float,
float)),
173 connect(widget.buttonClearSelectedPoints, SIGNAL(pressed()),
this, SLOT(
clearColorSelection()));
177 connect(widget.buttonColorSettingsReset,
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)));
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)));
219 connect(widget.comboBoxColor,
220 SIGNAL(currentIndexChanged(
int)),
223 connect(widget.buttonColorParameterFileSearch,
227 connect(widget.buttonColorParameterFileReset,
231 connect(widget.buttonColorParametersReload,
235 connect(widget.buttonColorParametersSave,
265 HsvColorSegmentationWidgetController::reconnect()
267 std::unique_lock lock(imageMutex);
269 disconnectFromProvider();
283 HsvColorSegmentationWidgetController::connectToProvider()
290 std::unique_lock lock(imageMutex);
292 imageProviderName = proxyFinder->getSelectedProxyName().toStdString();
293 ARMARX_INFO <<
"Trying to connect to provider " << imageProviderName;
303 int width = imageProviderInfo.
imageFormat.dimension.width;
304 int height = imageProviderInfo.
imageFormat.dimension.height;
308 bool makeResultImageNamePretty =
false;
309 std::string managedIceObjectName;
310 if (makeResultImageNamePretty)
312 managedIceObjectName =
getName();
317 enableResultImages(numImages, visionx::ImageDimension(width, height), visionx::ImageType::eRgb);
319 if (makeResultImageNamePretty)
331 HsvColorSegmentationWidgetController::disconnectFromProvider()
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.";
342 ARMARX_INFO <<
"Disconnecting from provider " << imageProviderName;
344 std::unique_lock lock(imageMutex);
349 imageProviderPrx = 0;
360 std::unique_lock lock(imageMutex);
362 if (!lock.owns_lock())
375 armarx::MetaInfoSizeBasePtr info;
403 drawSelectedPoints();
408 IceUtil::Time::microSeconds(info->timeProvided),
412 IceUtil::Time::microSeconds(info->timeProvided),
428 disconnectFromProvider();
440 isPaused = !isPaused;
457 std::unique_lock lock(imageMutex);
460 int col = image->width * x;
461 int row = image->height * y;
463 if (image->type != CByteImage::eRGB24)
465 ARMARX_WARNING <<
"Input image type is not eRGB24 (is " << image->type <<
" instead of "
466 << CByteImage::eRGB24 <<
")";
470 pixelIndex += row * image->width * image->bytesPerPixel;
471 pixelIndex += col * image->bytesPerPixel;
473 red = image->pixels[pixelIndex];
474 green = image->pixels[pixelIndex + 1];
475 blue = image->pixels[pixelIndex + 2];
481 SelectedPoint sp(imageIndex, x, y,
red,
green, blue);
483 selectedPoints.push_back(sp);
486 onSelectedPointsChanged();
492 selectedPoints.clear();
493 onSelectedPointsChanged();
499 if (dirtyColors.find(widget.comboBoxColor->currentIndex()) == dirtyColors.end())
501 markCurrentColorDirty();
504 updateColorVisualization();
506 widget.buttonColorParametersSave->setText(
"Save");
512 saveCurrentColorParameters(currentColorIndex);
513 loadCurrentColorParameters(value);
514 currentColorIndex = value;
520 guiAutoCheckBoxes[HUE_MID]->setChecked(
false);
527 guiAutoCheckBoxes[HUE_TOL]->setChecked(
false);
534 guiAutoCheckBoxes[SAT_MIN]->setChecked(
false);
541 guiAutoCheckBoxes[SAT_MAX]->setChecked(
false);
548 guiAutoCheckBoxes[VAL_MIN]->setChecked(
false);
555 guiAutoCheckBoxes[VAL_MAX]->setChecked(
false);
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);
577 updateAutoValuesUI();
585 recomputeAutoValues();
586 updateAutoValuesUI();
592 loadCurrentColorParameters(widget.comboBoxColor->currentIndex());
598 if (showMsgBoxes && !dirtyColors.empty())
601 msgBox.setText(
"Unsaved changes");
602 std::stringstream infText;
603 infText <<
"There are colors with unsaved changes: \n\n";
604 for (
int i : dirtyColors)
606 infText << COLOR_PARAMETER_NAMES.at(i).toStdString() <<
" ";
608 infText <<
"\n\nAre you sure to discard these changes?";
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)
621 std::string fileName = colorParameterFile();
624 ARMARX_WARNING <<
"Could not find color parameter file in ArmarXDataPath: " << fileName;
627 bool success = colorParameterSet.LoadFromFile(fileName.c_str());
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.";
638 msgBox.setText(
"Could not load color parameters.");
639 msgBox.setInformativeText(QString::fromStdString(text.str()));
640 msgBox.setIcon(QMessageBox::Warning);
648 widget.lineEditColorParameterFile->setText(QString::fromStdString(fileName));
649 loadCurrentColorParameters(widget.comboBoxColor->currentIndex());
651 markAllColorsClean();
657 saveCurrentColorParameters(widget.comboBoxColor->currentIndex());
659 bool success = colorParameterSet.SaveToFile(colorParameterFile().c_str());
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.";
668 msgBox.setText(
"Could not save color parameters.");
669 msgBox.setInformativeText(QString::fromStdString(text.str()));
670 msgBox.setIcon(QMessageBox::Warning);
676 markAllColorsClean();
677 widget.buttonColorParametersSave->setText(
"Saved");
683 QString selectedFile = QFileDialog::getOpenFileName(widget.buttonColorParameterFileSearch,
684 tr(
"Choose Color Parameter File"),
685 widget.lineEditColorParameterFile->text());
687 if (!selectedFile.isNull())
689 widget.lineEditColorParameterFile->setText(selectedFile);
696 widget.lineEditColorParameterFile->setText(getDefaultColorParameterFile());
700 HsvColorSegmentationWidgetController::value(
int param)
702 return guiValueSpinBoxes[param]->value();
706 HsvColorSegmentationWidgetController::hueMin()
708 return std::max(0, value(HUE_MID) - value(HUE_TOL));
712 HsvColorSegmentationWidgetController::hueMax()
714 return std::min(179, value(HUE_MID) + value(HUE_TOL));
718 HsvColorSegmentationWidgetController::satMid()
720 return 0.5 * (value(SAT_MIN) + value(SAT_MAX));
724 HsvColorSegmentationWidgetController::valMid()
726 return 0.5 * (value(VAL_MIN) + value(VAL_MAX));
730 HsvColorSegmentationWidgetController::isAutoEnabled(
int param)
732 return guiAutoCheckBoxes[param]->isChecked();
736 HsvColorSegmentationWidgetController::additionalTolerance()
738 return widget.spinBoxAddTol->value();
742 HsvColorSegmentationWidgetController::colorParameterFile()
744 return widget.lineEditColorParameterFile->text().toStdString();
748 HsvColorSegmentationWidgetController::recomputeAutoValues()
750 for (
int i = 0; i < NUM_PARAMS; ++i)
755 if (selectedPoints.empty())
765 autoValues[SAT_MIN] = 255;
766 autoValues[VAL_MIN] = 255;
771 for (SelectedPoint& p : selectedPoints)
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);
783 int hueMid = (hueMin + hueMax) / 2;
784 int hueTol =
std::max(hueMax - hueMid, hueMid - hueMin);
786 autoValues[HUE_MID] = hueMid;
787 autoValues[HUE_TOL] = hueTol;
791 int tolerance = additionalTolerance();
793 auto clampedAdd = [](
int&
target,
int addSub,
int maxMin)
805 clampedAdd(autoValues[HUE_TOL], 2 * tolerance, 179);
807 clampedAdd(autoValues[SAT_MIN], -tolerance, 0);
808 clampedAdd(autoValues[SAT_MAX], tolerance, 255);
810 clampedAdd(autoValues[VAL_MIN], -tolerance, 0);
811 clampedAdd(autoValues[VAL_MAX], tolerance, 255);
815 HsvColorSegmentationWidgetController::onSelectedPointsChanged()
817 recomputeAutoValues();
818 updateAutoValuesUI();
820 std::stringstream num;
821 num << selectedPoints.size();
822 widget.labelSelectedPointsNum->setText(QString(num.str().c_str()));
828 HsvColorSegmentationWidgetController::drawSelectedPoints()
833 for (SelectedPoint& sp : selectedPoints)
835 CByteImage* image = inputVisuImages[sp.imageIndex];
836 PrimitivesDrawer::DrawCircle(image,
837 sp.xRel * image->width,
838 sp.yRel * image->height,
845 PrimitivesDrawer::DrawCircle(
846 image, sp.xRel * image->width, sp.yRel * image->height, radius, 0, 0, 0, 2);
851 HsvColorSegmentationWidgetController::saveCurrentColorParameters(
int colorIndex)
853 std::string colorName = COLOR_PARAMETER_NAMES.at(colorIndex).toStdString();
855 ObjectColor objectColor = CColorParameterSet::Translate(colorName.c_str());
857 colorParameterSet.SetColorParameters(objectColor,
867 HsvColorSegmentationWidgetController::loadCurrentColorParameters(
int colorIndex)
871 bool isDirty = dirtyColors.find(colorIndex) != dirtyColors.end();
873 std::string colorName = COLOR_PARAMETER_NAMES.at(colorIndex).toStdString();
875 ObjectColor objectColor = CColorParameterSet::Translate(colorName.c_str());
877 const int* params = colorParameterSet.GetColorParameters(objectColor);
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]);
886 widget.checkBoxAutoAll->setChecked(
false);
890 markCurrentColorDirty();
894 markCurrentColorClean();
899 HsvColorSegmentationWidgetController::updatePausePlayButtonText()
901 const char* text = isPaused ?
"Play" :
"Pause";
902 widget.buttonPlayPause->setText(text);
908 updatePausePlayButtonText();
910 widget.buttonDisconnect->setEnabled(connected);
911 widget.buttonPlayPause->setEnabled(connected);
913 QString statusString;
916 std::stringstream ss;
917 ss <<
"Status: connected to image provider \n" << imageProviderName;
918 ss <<
" (" << numImages <<
" imgs, " << imageWidth <<
"x" << imageHeight <<
")";
924 statusString = QString::fromStdString(ss.str());
928 statusString =
"Status: not connected";
930 widget.labelImageMonitorStatus->setText(statusString);
934 HsvColorSegmentationWidgetController::setUiParamValue(
int param,
int value)
936 guiValueSpinBoxes[param]->setValue(value);
937 guiValueSliders[param]->setValue(value);
941 HsvColorSegmentationWidgetController::updateAutoValuesUI()
943 for (
int i = 0; i < NUM_PARAMS; ++i)
945 if (isAutoEnabled(i))
947 setUiParamValue(i, autoValues[i]);
948 guiAutoCheckBoxes[i]->setChecked(
true);
954 HsvColorSegmentationWidgetController::updateColorVisualization()
958 QPalette previewPalette = widget.labelColorPreview->palette();
959 previewPalette.setColor(QPalette::Background,
960 QColor::fromHsv(
value(HUE_MID), satMid(), valMid()));
961 widget.labelColorPreview->setPalette(previewPalette);
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());
972 int numHueSamples = 10;
975 for (
int i = 0; i <= numHueSamples; ++i)
977 float interpol =
float(i) / numHueSamples;
978 int value = int(hMin * (1 - interpol) + hMax * interpol);
980 gradHue.setColorAt(interpol, QColor::fromHsv(2 * value, 255, 255));
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));
986 gradVal.setColorAt(0, QColor::fromHsv(0, 0,
value(VAL_MIN)));
987 gradVal.setColorAt(1, QColor::fromHsv(0, 0,
value(VAL_MAX)));
991 auto setGradient = [](QLabel* label,
const QLinearGradient& gradient)
993 QPalette palette = label->palette();
994 palette.setBrush(QPalette::Background, gradient);
995 label->setPalette(palette);
998 setGradient(widget.labelGradHue, gradHue);
999 setGradient(widget.labelGradSat, gradSat);
1000 setGradient(widget.labelGradVal, gradVal);
1004 HsvColorSegmentationWidgetController::markCurrentColorDirty()
1006 int idx = widget.comboBoxColor->currentIndex();
1007 QString newText = COLOR_PARAMETER_NAMES.at(idx) +
"*";
1008 widget.comboBoxColor->setItemText(idx, newText);
1010 dirtyColors.insert(idx);
1014 HsvColorSegmentationWidgetController::markCurrentColorClean()
1016 int idx = widget.comboBoxColor->currentIndex();
1017 widget.comboBoxColor->setItemText(idx, COLOR_PARAMETER_NAMES.at(idx));
1018 dirtyColors.erase(idx);
1022 HsvColorSegmentationWidgetController::markAllColorsClean()
1024 for (
int i = 0; i < widget.comboBoxColor->count(); ++i)
1026 widget.comboBoxColor->setItemText(i, COLOR_PARAMETER_NAMES.at(i));
1028 dirtyColors.clear();
1032 HsvColorSegmentationWidgetController::rgbToHsv(
int r,
int g,
int b,
int& h,
int&
s,
int&
v)
1036 CByteImage rgb(1, 1, CByteImage::eRGB24);
1037 CByteImage hsv(1, 1, CByteImage::eRGB24);
1043 ::ImageProcessor::CalculateHSVImage(&rgb, &hsv);
1051 HsvColorSegmentationWidgetController::getHomeDirectory()
1054 char* homeDir = getenv(
"HOME");
1059 passwd* pw = getpwuid(getuid());
1060 homeDir = pw->pw_dir;
1063 return std::string(homeDir);
1067 HsvColorSegmentationWidgetController::getDefaultColorParameterFile()
1069 std::stringstream path;
1070 path << getHomeDirectory();
1071 path <<
"/" << DEFAULT_COLOR_PARAMETER_FILE;
1073 return QString::fromStdString(path.str());