FeatureLearningWidgetController.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::FeatureLearningWidgetController
17  * \author Julian Zimmer ( urdbu 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 <mutex>
26 #include <string>
27 
29 
31 
32 #include <VisionX/interface/components/Calibration.h>
35 
36 #include <Calibration/StereoCalibration.h>
37 #include <DataStructures/DynamicArray.h>
38 #include <Image/ImageProcessor.h>
39 #include <Image/PrimitivesDrawer.h>
40 
41 using namespace armarx;
42 using namespace visionx;
43 
45 {
46  qRegisterMetaType<CByteImage**>("CByteImage**");
47 
48  QPointer<QWidget> widgetPointer = getWidget();
49  this->widgetPointer = widgetPointer.data();
50 
51  widget.setupUi(widgetPointer);
52 
53 
54  proxyFinder = new armarx::IceProxyFinder<ImageProviderInterfacePrx>(widgetPointer);
55  proxyFinder->setSearchMask("*Provider|*Result");
56  //ui.horizontalLayout->addWidget(proxyFinder);
57  widget.chooseProviderLayout->addWidget(proxyFinder);
58 
59  imageViewer = new SelectableImageViewer();
60  QSizePolicy sizePoli(QSizePolicy::Expanding, QSizePolicy::Expanding);
61  sizePoli.setVerticalStretch(15);
62  imageViewer->setSizePolicy(sizePoli);
63 
64  widget.imageViewerLayout_2->addWidget(imageViewer);
65  imageViewer->show();
66 }
67 
69 {
70 }
71 
72 void
74 {
75 }
76 
77 void
79 {
80 }
81 
82 void
84 {
85  proxyFinder->setIceManager(this->getIceManager(),
86  proxyFinder->getSelectedProxyName().isEmpty());
87 
88  points = Eigen::ArrayX2f::Zero(4, 2);
89  numSelectedPoints = 0;
90 
91 
92  connect(imageViewer,
93  SIGNAL(selected(int, float, float)),
94  this,
95  SLOT(addPolygonPoint(int, float, float)));
96  connect(widget.connectButton, SIGNAL(clicked(bool)), this, SLOT(connectButtonClicked(bool)));
97  connect(widget.loadFeaturesButton,
98  SIGNAL(clicked(bool)),
99  this,
100  SLOT(loadFeaturesButtonClicked(bool)));
101  connect(widget.saveFeaturesButton,
102  SIGNAL(clicked(bool)),
103  this,
104  SLOT(saveFeaturesButtonClicked(bool)));
105  connect(
106  widget.pausePlayButton, SIGNAL(clicked(bool)), this, SLOT(pausePlayButtonClicked(bool)));
107  connect(
108  widget.disconnectButton, SIGNAL(clicked(bool)), this, SLOT(disconnectButtonClicked(bool)));
109  connect(widget.addFeaturesButton,
110  SIGNAL(clicked(bool)),
111  this,
112  SLOT(addFeaturesButtonClicked(bool)));
113  connect(widget.clearFeaturesButton,
114  SIGNAL(clicked(bool)),
115  this,
116  SLOT(clearFeaturesButtonClicked(bool)));
117  connect(widget.thresholdSpinBox,
118  SIGNAL(valueChanged(double)),
119  this,
120  SLOT(thresholdChanged(double)));
121  connect(
122  widget.maxFeatureSpinBox, SIGNAL(valueChanged(int)), this, SLOT(maxFeaturesChanged(int)));
123 
124 
125  connected = false;
126  isPaused = true;
127 }
128 
129 void
131 {
132  objectFeatureSet = new CTexturedFeatureSet("objectFeatureSet");
133  viewFeatureSet = new CTexturedFeatureSet("viewFeatureSet");
134 
135  featureCalculator = new CHarrisSIFTFeatureCalculator(0.001, 1, 3500);
136  // featureCalculator->SetNumberOfLevels(1);
137 }
138 
139 //add the features from the current region to the selection
140 int
141 FeatureLearningWidgetController::addFeatures()
142 {
143  int numAdded = 0;
144  for (int i = 0; i < viewFeatureSet->GetSize(); i++)
145  {
146  CFeatureEntry* copiedEntry = viewFeatureSet->GetFeature(i)->Clone();
147  Math2d::ApplyHomography(homography, copiedEntry->point, copiedEntry->point);
148  bool addedSuccessfully = objectFeatureSet->AddFeature(copiedEntry, false);
149  if (addedSuccessfully)
150  {
151  numAdded++;
152  }
153  }
154  return numAdded;
155 }
156 
157 void
158 FeatureLearningWidgetController::clearFeatures()
159 {
160  objectFeatureSet->Clear();
161 }
162 
163 //load a feature set from a .dat file
164 void
165 FeatureLearningWidgetController::loadFeatureSet(QString filePath)
166 {
167  std::string filePathStr = filePath.toStdString();
168  const char* filePathCStr = filePathStr.c_str();
169  if (!objectFeatureSet->LoadFromFile(filePathCStr))
170  {
171  ARMARX_ERROR << " could not load feature set from file " << filePath;
172  widget.lastActionInfoLabel->setText("Loading features failed!");
173  }
174  else
175  {
176  ARMARX_INFO << "loaded feature set with " << objectFeatureSet->GetSize() << " features";
177 
178  QDir currentDir;
179  mySettings.setValue("default_load_dir", currentDir.absoluteFilePath(filePath));
180 
181  widget.lastActionInfoLabel->setText("Loaded feature set with " +
182  QString::number(objectFeatureSet->GetSize()) +
183  " features");
184 
185  float x = fabsf(2.f * objectFeatureSet->m_3dPoint2.x);
186  float y = fabsf(2.f * objectFeatureSet->m_3dPoint2.y);
187  float z = fabsf(2.f * objectFeatureSet->m_3dPoint2.z);
188 
189  int xInt = (int)x;
190  int yInt = (int)y;
191  int zInt = (int)z;
192 
193  widget.widthLineEdit->setText(QString::number(xInt));
194  widget.heightLineEdit->setText(QString::number(yInt));
195  widget.depthLineEdit->setText(QString::number(zInt));
196  }
197 
198  points = Eigen::ArrayX2f::Zero(4, 2);
199  numSelectedPoints = 0;
200 }
201 
202 //save a feature set to a .dat file
203 void
204 FeatureLearningWidgetController::saveFeatureSet(QString filePath, float w, float h, float d)
205 {
206  ARMARX_CHECK_EXPRESSION(objectFeatureSet->GetSize() > 0);
207  ARMARX_CHECK_EXPRESSION(w > 0.f);
208  ARMARX_CHECK_EXPRESSION(h > 0.f);
209  ARMARX_CHECK_EXPRESSION(d > 0.f);
210 
211  Math3d::SetVec(objectFeatureSet->m_3dPoint1, -w / 2.0f, -h / 2.0f, -d / 2.0f);
212  Math3d::SetVec(objectFeatureSet->m_3dPoint2, w / 2.0f, -h / 2.0f, -d / 2.0f);
213  Math3d::SetVec(objectFeatureSet->m_3dPoint3, w / 2.0f, h / 2.0f, -d / 2.0f);
214  Math3d::SetVec(objectFeatureSet->m_3dPoint4, -w / 2.0f, h / 2.0f, -d / 2.0f);
215 
216  std::string filePathStr = filePath.toStdString();
217  const char* filePathCStr = filePathStr.c_str();
218 
219 
220  if (!objectFeatureSet->SaveToFile(filePathCStr))
221  {
222  ARMARX_ERROR << " could not save feature set to file " << filePath;
223  widget.lastActionInfoLabel->setText("Saving features failed!");
224  }
225  else
226  {
227  ARMARX_INFO << " saved feature set with " << objectFeatureSet->GetSize()
228  << " features to file " << filePathCStr;
229 
230 
231  std::string matPath = filePath.toStdString();
232  const unsigned int n = matPath.find_last_of(".dat");
233  matPath.resize(n - 2);
234  matPath += "mat";
235 
236  CFloatMatrix* object = createCuboid(w, h, d);
237  object->SaveToFile(matPath.c_str());
238  delete object;
239 
240  QDir currentDir;
241  mySettings.setValue("default_save_dir", currentDir.absoluteFilePath(filePath));
242  widget.lastActionInfoLabel->setText(
243  "Saved " + QString::number(objectFeatureSet->GetSize()) + " features into file");
244  }
245 }
246 
247 void
249 {
250 }
251 
252 void
254 {
255  points = Eigen::ArrayX2f::Zero(4, 2);
256 
257  if (connected)
258  {
259  for (int i = 0; i < numImages; i++)
260  {
261  delete cameraImages[i];
262  }
263 
264  delete[] cameraImages;
265 
266  delete visualizationImage;
267  delete grayImage;
268  }
269 
270  delete featureCalculator;
271 
272  delete objectFeatureSet;
273  delete viewFeatureSet;
274 
275  // releaseImageProvider(imageProviderName);
276 }
277 
278 static bool
279 SameSide(const Vec2d& p1, const Vec2d& p2, const Vec2d& a, const Vec2d& b)
280 {
281  double ba0 = b.x - a.x;
282  double ba1 = b.y - a.y;
283 
284  double p1a0 = p1.x - a.x;
285  double p1a1 = p1.y - a.y;
286 
287  double p2a0 = p2.x - a.x;
288  double p2a1 = p2.y - a.y;
289 
290  double cp1 = ba0 * p1a1 - ba1 * p1a0;
291  double cp2 = ba0 * p2a1 - ba1 * p2a0;
292 
293  return cp1 * cp2 >= 0;
294 }
295 
296 static bool
297 PointInPoly(const Vec2d& p, const Vec2d& a, const Vec2d& b, const Vec2d& c)
298 {
299  return SameSide(p, a, b, c) && SameSide(p, b, a, c) && SameSide(p, c, a, b);
300 }
301 
302 static double
303 DistancePointStraightLine(const Vec2d& a, const Vec2d& b, const Vec2d p)
304 {
305  Vec2d n = {b.y - a.y, a.x - b.x};
306  Math2d::NormalizeVec(n);
307 
308  return std::fabs(Math2d::ScalarProduct(n, p) - Math2d::ScalarProduct(n, a));
309 }
310 
311 //calculate features for the current region
312 void
313 FeatureLearningWidgetController::updateFeatures()
314 {
315  if (numSelectedPoints == 0)
316  {
317  viewFeatureSet->Clear();
318  return;
319  }
320 
321  // wait until region is selected
322  if (numSelectedPoints < 4)
323  {
324  return;
325  }
326 
327  Vec2d sourcePoints[4];
328 
329  for (int i = 0; i < numSelectedPoints; i++)
330  {
331  sourcePoints[i].x = points(i, 0) * grayImage->width;
332  sourcePoints[i].y = points(i, 1) * grayImage->height;
333  }
334 
335  const float w = widget.widthLineEdit->text().toFloat();
336  const float h = widget.heightLineEdit->text().toFloat();
337 
338  Vec2d targetPoints[4];
339  Math2d::SetVec(targetPoints[0], 0, 0);
340  Math2d::SetVec(targetPoints[1], w, 0);
341  Math2d::SetVec(targetPoints[2], w, h);
342  Math2d::SetVec(targetPoints[3], 0, h);
343 
344  LinearAlgebra::DetermineHomography(sourcePoints, targetPoints, 4, homography, true);
345 
346  objectFeatureSet->SetCornerPoints(
347  targetPoints[0], targetPoints[1], targetPoints[2], targetPoints[3]);
348 
349  featureCalculatorMutex.lock();
350  CDynamicArray dynamic_array(featureCalculator->GetMaxInterestPoints());
351  const int nFeatures = featureCalculator->CalculateFeatures(grayImage, &dynamic_array);
352  featureCalculatorMutex.unlock();
353  viewFeatureSet->Clear();
354 
355  for (int i = 0; i < nFeatures; i++)
356  {
357  CFeatureEntry* pFeatureEntry = (CFeatureEntry*)dynamic_array.GetElement(i);
358 
359  if (PointInPoly(pFeatureEntry->point, sourcePoints[0], sourcePoints[1], sourcePoints[2]) ||
360  PointInPoly(pFeatureEntry->point, sourcePoints[2], sourcePoints[3], sourcePoints[0]))
361  {
362  const double dThreshold = 10;
363 
364  if (DistancePointStraightLine(sourcePoints[0], sourcePoints[1], pFeatureEntry->point) >
365  dThreshold &&
366  DistancePointStraightLine(sourcePoints[1], sourcePoints[2], pFeatureEntry->point) >
367  dThreshold &&
368  DistancePointStraightLine(sourcePoints[2], sourcePoints[3], pFeatureEntry->point) >
369  dThreshold &&
370  DistancePointStraightLine(sourcePoints[3], sourcePoints[0], pFeatureEntry->point) >
371  dThreshold)
372  {
373  viewFeatureSet->AddFeature(pFeatureEntry->Clone(), false);
374  }
375  }
376  }
377 
378  ARMARX_LOG << deactivateSpam(2.f) << "Features in polygon " << viewFeatureSet->GetSize();
379 }
380 
381 void
382 FeatureLearningWidgetController::updateSelection()
383 {
384  Vec2d sourcePoints[4];
385 
386  //Depending on the size of the widget, the image gets scaled up or down
387  //The dimensions of the visualization image have to be regarded, to find the position of the mouse click on the image
388  //Vec2d scaledImageDimensions = imageViewer->getScaledImageDimensions();
389  for (int i = 0; i < numSelectedPoints; i++)
390  {
391  float relativeX = points(i, 0);
392  float relativeY = points(i, 1);
393 
394  sourcePoints[i].x = relativeX * visualizationImage->width;
395  sourcePoints[i].y = relativeY * visualizationImage->height;
396  //sourcePoints[i].x = points(i, 0);
397  //sourcePoints[i].y = points(i, 1);
398  }
399 
400  if (numSelectedPoints >= 1)
401  {
402  PrimitivesDrawer::DrawCircle(visualizationImage, sourcePoints[0], 3, 255, 0, 0, -1);
403  //ARMARX_INFO << deactivateSpam(2.f) << "DRAWING POINT 1 AT (" << sourcePoints[0].x << ", " << sourcePoints[0].y << ")";
404  }
405  if (numSelectedPoints >= 2)
406  {
407  PrimitivesDrawer::DrawCircle(visualizationImage, sourcePoints[1], 3, 255, 0, 0, -1);
408  PrimitivesDrawer::DrawLine(visualizationImage, sourcePoints[0], sourcePoints[1], 0, 0, 255);
409  //ARMARX_INFO << deactivateSpam(2.f) << "DRAWING POINT 2 AT (" << sourcePoints[1].x << ", " << sourcePoints[1].y << ")";
410  }
411  if (numSelectedPoints >= 3)
412  {
413  PrimitivesDrawer::DrawCircle(visualizationImage, sourcePoints[2], 3, 255, 0, 0, -1);
414  PrimitivesDrawer::DrawLine(visualizationImage, sourcePoints[1], sourcePoints[2], 0, 0, 255);
415  //ARMARX_INFO << deactivateSpam(2.f) << "DRAWING POINT 3 AT (" << sourcePoints[2].x << ", " << sourcePoints[2].y << ")";
416  }
417  if (numSelectedPoints >= 4)
418  {
419  PrimitivesDrawer::DrawCircle(visualizationImage, sourcePoints[3], 3, 255, 0, 0, -1);
420  PrimitivesDrawer::DrawLine(visualizationImage, sourcePoints[2], sourcePoints[3], 0, 0, 255);
421  PrimitivesDrawer::DrawLine(visualizationImage, sourcePoints[3], sourcePoints[0], 0, 0, 255);
422  //ARMARX_INFO << deactivateSpam(2.f) << "DRAWING POINT 4 AT (" << sourcePoints[3].x << ", " << sourcePoints[3].y << ")";
423  }
424 
425 
426  // draw features
427  if (numSelectedPoints >= 4)
428  {
429  for (int i = 0; i < viewFeatureSet->GetSize(); i++)
430  {
431  const CFeatureEntry* pFeatureEntry = viewFeatureSet->GetFeature(i);
432  PrimitivesDrawer::DrawCircle(
433  visualizationImage, pFeatureEntry->point, 2, 0, 255, 0, -1);
434  }
435  }
436 }
437 
438 void
440 {
441 
442  //std::unique_lock<std::mutex> lock(imageMutex, std::try_to_lock);
443  std::unique_lock lock(imageMutex);
444 
445  if (!lock.owns_lock())
446  {
447  ARMARX_INFO << deactivateSpam(3) << "unable to process next image(" << lock.owns_lock()
448  << ")";
449  return;
450  }
451 
452  if (!connected)
453  {
454  ARMARX_INFO << deactivateSpam(3) << "Not connected to any image provider";
455  return;
456  }
457 
458  armarx::MetaInfoSizeBasePtr info;
459  IceUtil::Time timeReceived;
460  if (!isPaused)
461  {
462  //only update current image, if unpaused
463  if (!waitForImages(imageProviderName))
464  {
465  ARMARX_WARNING << "Timeout while waiting for images";
466  return;
467  }
468  if (getImages(imageProviderName, cameraImages, info) != numImages)
469  {
470  ARMARX_WARNING << "Unable to transfer or read images";
471  return;
472  }
473  timeReceived = TimeUtil::GetTime();
474  }
475 
476  //create grayscale image for feature calculation and color image for the visualization
477  ::ImageProcessor::ConvertImage(cameraImages[0], grayImage);
478  ::ImageProcessor::CopyImage(cameraImages[0], visualizationImage);
479 
480  updateFeatures();
481  updateSelection();
482 
483  //update the availability of the buttons etc.
484  updateFeaturesUI();
485 
486 
487  CByteImage** images = new CByteImage* {visualizationImage};
488  imageViewer->setImages(
489  1, images, IceUtil::Time::microSeconds(info->timeProvided), timeReceived);
490 }
491 
492 void
494 {
495  if (!connected)
496  {
497  return;
498  }
499 
500  if (numSelectedPoints >= 4)
501  {
502  numSelectedPoints = 0;
503  }
504 
505  points(numSelectedPoints, 0) = x;
506  points(numSelectedPoints, 1) = y;
507 
508  numSelectedPoints++;
509 }
510 
511 void
513 {
514  reconnect();
515 }
516 
517 //opens a QDialog with the last used load location and calls the feature loading function
518 void
520 {
521  QString previousLoadDirectory = mySettings.value("default_load_dir").toString();
522  if (previousLoadDirectory == "")
523  {
524  QString previousSaveDirectory = mySettings.value("default_save_dir").toString();
525  if (previousSaveDirectory == "")
526  {
527  previousLoadDirectory = "~";
528  }
529  else
530  {
531  previousLoadDirectory = previousSaveDirectory;
532  }
533  }
534  QString filePath = QFileDialog::getOpenFileName(
535  widgetPointer, "Load Features", previousLoadDirectory, "(*.dat)");
536  loadFeatureSet(filePath);
537 }
538 
539 //checks if features are selected and opens a QDialog to choose the save location
540 void
542 {
543  if (objectFeatureSet->GetSize() < 1)
544  {
545  QMessageBox emptyFeatureSetBox;
546  emptyFeatureSetBox.setText("Cannot save empty feature set!");
547  emptyFeatureSetBox.setWindowTitle("Feature set empty");
548  emptyFeatureSetBox.exec();
549  return;
550  }
551  float width = widget.widthLineEdit->text().toFloat();
552  float height = widget.heightLineEdit->text().toFloat();
553  float depth = widget.depthLineEdit->text().toFloat();
554 
555  if (width <= 0.f || height <= 0.f || depth <= 0.f)
556  {
557  QMessageBox invalidDimensionsBox;
558  invalidDimensionsBox.setText("Cannot save feature set with object dimensions <= 0!");
559  invalidDimensionsBox.setWindowTitle("Invalid object dimensions");
560  invalidDimensionsBox.exec();
561  return;
562  }
563 
564  QString previousSaveDirectory = mySettings.value("default_save_dir").toString();
565  if (previousSaveDirectory == "")
566  {
567  QString previousLoadDirectory = mySettings.value("default_load_dir").toString();
568  if (previousLoadDirectory == "")
569  {
570  previousSaveDirectory = "~";
571  }
572  else
573  {
574  previousSaveDirectory = previousLoadDirectory;
575  }
576  }
577  QString filePath = QFileDialog::getSaveFileName(
578  widgetPointer, "Save Features", previousSaveDirectory, "(*.dat)");
579  if (filePath.right(4) != ".dat")
580  {
581  filePath += ".dat";
582  }
583  saveFeatureSet(filePath, width, height, depth);
584 }
585 
586 void
588 {
589  if (!connected)
590  {
591  isPaused = false;
592  }
593  else
594  {
595  isPaused = !isPaused;
596  }
597  updateImageMonitorUI();
598 }
599 
600 //disconncts and connects again
601 void
603 {
604  std::unique_lock lock(imageMutex);
605 
606  disconnectFromProvider();
607 
608  // connect to provider
609  try
610  {
611  connectToProvider();
612  }
613  catch (...)
614  {
616  }
617 }
618 
619 //trying to connect to the image provider
620 void
621 FeatureLearningWidgetController::connectToProvider()
622 {
623  if (connected)
624  {
625  return;
626  }
627 
628 
629  imageProviderName = proxyFinder->getSelectedProxyName().toStdString();
630  ARMARX_INFO << "Trying to connect to provider " << imageProviderName;
631 
632  try
633  {
634  usingImageProvider(imageProviderName);
635  }
636  catch (Ice::NotRegisteredException& e)
637  {
638  ARMARX_ERROR << "Cannot connect to the given image provider called " << imageProviderName;
639 
640  QMessageBox cannotConnectToProviderBox;
641  QString cannotConnectToProviderString =
642  "Cannot connect to the given image provider called " +
643  QString::fromStdString(imageProviderName);
644  cannotConnectToProviderBox.setText(cannotConnectToProviderString);
645  cannotConnectToProviderBox.setWindowTitle("Cannot connect to Image Provider");
646  cannotConnectToProviderBox.exec();
647  return;
648  }
649  catch (armarx::LocalException& e)
650  {
651  ARMARX_ERROR << "Image Provider field is empty, cannot connect!" << imageProviderName;
652 
653  QMessageBox noProviderGivenBox;
654  QString cannotConnectToProviderString =
655  "Cannot connect to an image provider since the field is empty.";
656  noProviderGivenBox.setText(cannotConnectToProviderString);
657  noProviderGivenBox.setWindowTitle("No Provider given");
658  noProviderGivenBox.exec();
659  return;
660  }
661 
662  ARMARX_INFO << getName() << " connecting to " << imageProviderName;
663 
664  // connect to proxy
665  imageProviderInfo =
666  getImageProvider(imageProviderName, visionx::tools::typeNameToImageType("rgb"));
667 
668  // update members
669  imageProviderPrx = imageProviderInfo.proxy;
670  numImages = imageProviderInfo.numberImages;
671 
672  StereoCalibrationProviderInterfacePrx calibrationProvider =
673  StereoCalibrationProviderInterfacePrx::checkedCast(imageProviderInfo.proxy);
674 
675  if (!calibrationProvider)
676  {
677  ARMARX_WARNING << "image provider does not have a stereo calibration interface";
678  }
679  else
680  {
681  undistortImages = calibrationProvider->getImagesAreUndistorted();
682  if (!undistortImages)
683  {
684  ARMARX_ERROR << "Images expected to be undistorted, but the calibration returns that "
685  "the images are distorted";
686  }
687  // visionx::StereoCalibration stereoCalibration = calibrationProvider->getStereoCalibration();
688  // CStereoCalibration* ivtStereoCalibration = visionx::tools::convert(stereoCalibration);
689  }
690 
691 
692  // create images
693  {
694  std::unique_lock lock(imageMutex);
695  cameraImages = new CByteImage*[numImages];
696 
697  for (int i = 0; i < numImages; i++)
698  {
699  cameraImages[i] = visionx::tools::createByteImage(imageProviderInfo);
700  }
701  }
702 
703  visualizationImage = visionx::tools::createByteImage(imageProviderInfo);
704  grayImage = new CByteImage(imageProviderInfo.imageFormat.dimension.width,
705  imageProviderInfo.imageFormat.dimension.height,
706  CByteImage::eGrayScale);
707 
708 
709  timeProvided = IceUtil::Time::seconds(0);
710 
711  isPaused = false;
712  connected = true;
713  updateImageMonitorUI();
714  updateFeaturesUI();
715 
716 
717  emit imageProviderConnected(true);
718 }
719 
720 //disconnecting the image provider
721 void
722 FeatureLearningWidgetController::disconnectFromProvider()
723 {
724  if (!connected)
725  {
726  return;
727  }
728  ARMARX_INFO << "Disconnecting from provider";
729  {
730  std::unique_lock lock(imageMutex);
731  // clear images
732  if (cameraImages)
733  {
734  for (int i = 0; i < numImages; i++)
735  {
736  delete cameraImages[i];
737  }
738 
739  delete[] cameraImages;
740  }
741  delete visualizationImage;
742  delete grayImage;
743  }
744 
745  releaseImageProvider(imageProviderName);
746 
747  imageProviderPrx = 0;
748 
749  connected = false;
750  isPaused = true;
751  numSelectedPoints = 0;
752 
753  QString emptyFeaturesInfoText = "";
754  widget.lastActionInfoLabel->setText(emptyFeaturesInfoText);
755 
756  updateImageMonitorUI();
757  updateFeaturesUI();
758 
759  emit imageProviderConnected(false);
760 }
761 
762 void
763 FeatureLearningWidgetController::updatePausePlayButtonText()
764 {
765  if (isPaused)
766  {
767  widget.pausePlayButton->setText("Play");
768  return;
769  }
770  widget.pausePlayButton->setText("Pause");
771 }
772 
773 void
774 FeatureLearningWidgetController::updateImageMonitorUI()
775 {
776  updatePausePlayButtonText();
777 
778  widget.disconnectButton->setEnabled(connected);
779  widget.pausePlayButton->setEnabled(connected);
780 
781  if (connected)
782  {
783  QString providerName = imageProviderName.c_str();
784  QString statusString = "Status: connected to image provider " + providerName;
785  if (isPaused)
786  {
787  statusString = statusString + " - PAUSED";
788  }
789  widget.imageMonitorStatusLabel->setText(statusString);
790  }
791  else
792  {
793  widget.imageMonitorStatusLabel->setText("Status: not connected");
794  }
795 }
796 
797 void
799 {
800  disconnectFromProvider();
801 }
802 
803 void
805 {
806  int numFeaturesAdded = addFeatures();
807  QString featuresString = " features";
808  if (numFeaturesAdded == 1)
809  {
810  featuresString = " feature";
811  }
812  QString addedFeaturesText =
813  "Added " + QString::number(numFeaturesAdded) + featuresString + " to the selection";
814  widget.lastActionInfoLabel->setText(addedFeaturesText);
815  updateFeaturesUI();
816 }
817 
818 void
820 {
821  clearFeatures();
822  QString clearedFeaturesText = "Cleared the selected features";
823  widget.lastActionInfoLabel->setText(clearedFeaturesText);
824  updateFeaturesUI();
825 }
826 
827 //updates the information about the features on the right part of the ui
828 void
829 FeatureLearningWidgetController::updateFeaturesUI()
830 {
831  if (!connected)
832  {
833  widget.addFeaturesButton->setEnabled(false);
834  widget.clearFeaturesButton->setEnabled(false);
835  widget.featuresInRegionLabel->setText("");
836  widget.featuresSelectedLabel->setText("");
837  return;
838  }
839  widget.addFeaturesButton->setEnabled(true);
840  widget.clearFeaturesButton->setEnabled(true);
841  QString featuresInRegionString = "Features in Region: ";
842  if (numSelectedPoints == 4)
843  {
844  featuresInRegionString += QString::number(viewFeatureSet->GetSize());
845  }
846  widget.featuresInRegionLabel->setText(featuresInRegionString);
847 
848  QString featuresSelectedString =
849  "Features selected: " + QString::number(objectFeatureSet->GetSize());
850  widget.featuresSelectedLabel->setText(featuresSelectedString);
851 }
852 
853 CFloatMatrix*
854 FeatureLearningWidgetController::createCuboid(float w, float h, float d)
855 {
856  CFloatMatrix* object = new CFloatMatrix(6, 36);
857 
858  int offset = 0;
859  addRectangle(object, offset, 0, 0, 0, w, 0, 0, w, h, 0, 0, h, 0, 0, 0, -1);
860  addRectangle(object, offset, 0, 0, d, w, 0, d, w, h, d, 0, h, d, 0, 0, 1);
861  addRectangle(object, offset, 0, 0, 0, 0, 0, d, 0, h, d, 0, h, 0, -1, 0, 0);
862  addRectangle(object, offset, w, 0, 0, w, 0, d, w, h, d, w, h, 0, 1, 0, 0);
863  addRectangle(object, offset, 0, 0, 0, 0, 0, d, w, 0, d, w, 0, 0, 0, -1, 0);
864  addRectangle(object, offset, 0, h, 0, 0, h, d, w, h, d, w, h, 0, 0, 1, 0);
865 
866  for (int i = 0; i < 36; i++)
867  {
868  const int offset = 6 * i;
869  object->data[offset + 3] -= w / 2.0;
870  object->data[offset + 4] -= h / 2.0;
871  object->data[offset + 5] -= d / 2.0;
872  }
873 
874  return object;
875 }
876 
877 void
878 FeatureLearningWidgetController::addRectangle(CFloatMatrix* object,
879  int& offset,
880  float x1,
881  float y1,
882  float z1,
883  float x2,
884  float y2,
885  float z2,
886  float x3,
887  float y3,
888  float z3,
889  float x4,
890  float y4,
891  float z4,
892  float n1,
893  float n2,
894  float n3)
895 {
896  addTriangle(object, offset, x1, y1, z1, x2, y2, z2, x3, y3, z3, n1, n2, n3);
897  addTriangle(object, offset, x4, y4, z4, x1, y1, z1, x3, y3, z3, n1, n2, n3);
898 }
899 
900 void
901 FeatureLearningWidgetController::addTriangle(CFloatMatrix* object,
902  int& offset,
903  float x1,
904  float y1,
905  float z1,
906  float x2,
907  float y2,
908  float z2,
909  float x3,
910  float y3,
911  float z3,
912  float n1,
913  float n2,
914  float n3)
915 {
916  float* data = object->data;
917 
918  data[offset + 0] = n1;
919  data[offset + 1] = n2;
920  data[offset + 2] = n3;
921  data[offset + 3] = x1;
922  data[offset + 4] = y1;
923  data[offset + 5] = z1;
924  offset += 6;
925 
926  data[offset + 0] = n1;
927  data[offset + 1] = n2;
928  data[offset + 2] = n3;
929  data[offset + 3] = x2;
930  data[offset + 4] = y2;
931  data[offset + 5] = z2;
932  offset += 6;
933 
934  data[offset + 0] = n1;
935  data[offset + 1] = n2;
936  data[offset + 2] = n3;
937  data[offset + 3] = x3;
938  data[offset + 4] = y3;
939  data[offset + 5] = z3;
940  offset += 6;
941 }
942 
943 void
945 {
946  std::lock_guard g{featureCalculatorMutex};
947  featureCalculator->SetThreshold(threshold);
948 }
949 
950 void
952 {
953  std::lock_guard g{featureCalculatorMutex};
954  featureCalculator->SetMaxInterestPoints(maxFeatures);
955 }
armarx::FeatureLearningWidgetController::reconnect
void reconnect()
Definition: FeatureLearningWidgetController.cpp:602
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
armarx::FeatureLearningWidgetController::saveFeaturesButtonClicked
void saveFeaturesButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:541
armarx::FeatureLearningWidgetController::clearFeaturesButtonClicked
void clearFeaturesButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:819
armarx::FeatureLearningWidgetController::loadFeaturesButtonClicked
void loadFeaturesButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:519
armarx::FeatureLearningWidgetController::connectButtonClicked
void connectButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:512
armarx::FeatureLearningWidgetController::loadSettings
virtual void loadSettings(QSettings *settings) override
Definition: FeatureLearningWidgetController.cpp:73
armarx::FeatureLearningWidgetController::saveSettings
virtual void saveSettings(QSettings *settings) override
Definition: FeatureLearningWidgetController.cpp:78
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::FeatureLearningWidgetController::pausePlayButtonClicked
void pausePlayButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:587
armarx::FeatureLearningWidgetController::addPolygonPoint
void addPolygonPoint(int, float x, float y)
Definition: FeatureLearningWidgetController.cpp:493
visionx::tools::createByteImage
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
armarx::FeatureLearningWidgetController::thresholdChanged
void thresholdChanged(double threshold)
Definition: FeatureLearningWidgetController.cpp:944
armarx::FeatureLearningWidgetController::onConnectImageProcessor
virtual void onConnectImageProcessor() override
Definition: FeatureLearningWidgetController.cpp:130
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
IceProxyFinder.h
armarx::FeatureLearningWidgetController::onInitImageProcessor
virtual void onInitImageProcessor() override
Definition: FeatureLearningWidgetController.cpp:83
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::FeatureLearningWidgetController::process
virtual void process() override
Definition: FeatureLearningWidgetController.cpp:439
armarx::FeatureLearningWidgetController::disconnectButtonClicked
void disconnectButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:798
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
ARMARX_LOG
#define ARMARX_LOG
Definition: Logging.h:165
GfxTL::Vec2d
VectorXD< 2, double > Vec2d
Definition: VectorXD.h:736
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
ExpressionException.h
armarx::SelectableImageViewer
A clickable, i.e. selectable, visionx::ImageViewerArea.
Definition: SelectableImageViewer.h:44
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::FeatureLearningWidgetController::onExitImageProcessor
virtual void onExitImageProcessor() override
Definition: FeatureLearningWidgetController.cpp:253
armarx::FeatureLearningWidgetController::FeatureLearningWidgetController
FeatureLearningWidgetController()
Controller Constructor.
Definition: FeatureLearningWidgetController.cpp:44
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::FeatureLearningWidgetController::onDisconnectImageProcessor
virtual void onDisconnectImageProcessor() override
Definition: FeatureLearningWidgetController.cpp:248
armarx::IceProxyFinder< ImageProviderInterfacePrx >
visionx::tools::typeNameToImageType
ImageType typeNameToImageType(const std::string &imageTypeName)
Converts an image type name as string into an ImageType integer.
Definition: TypeMapping.cpp:42
ImageUtil.h
TypeMapping.h
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::FeatureLearningWidgetController::addFeaturesButtonClicked
void addFeaturesButtonClicked(bool toggled)
Definition: FeatureLearningWidgetController.cpp:804
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::FeatureLearningWidgetController::maxFeaturesChanged
void maxFeaturesChanged(int maxFeatures)
Definition: FeatureLearningWidgetController.cpp:951
FeatureLearningWidgetController.h
armarx::FeatureLearningWidgetController::~FeatureLearningWidgetController
virtual ~FeatureLearningWidgetController()
Controller destructor.
Definition: FeatureLearningWidgetController.cpp:68