ImageMonitorWidgetController.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 ObserverTest::
17* @author ( at kit dot edu)
18* @date
19* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23
25
26
27// STD/STL
28#include <cmath>
29#include <filesystem>
30#include <iomanip>
31
32// Qt
33#include <QApplication>
34
35// IVT
36#include <Image/ImageProcessor.h>
37
38// Somox
39#include <SimoxUtility/algorithm/string.h>
40
41// ArmarXCore
44
45// RobotAPI
47
48// VisionX
51
52#include "ImageViewerArea.h"
53using namespace armarx;
54
55namespace
56{
57 /**
58 * @brief Helper function to determine the correct camera ID
59 *
60 * For example, if there are two image sources and the depth index is not set, then the first
61 * camera is "left" and the second "right". If there are more than two cameras, they are just
62 * called "camX" where X is the ID. If the depth index is set, then that camera will be called
63 * "depth". For two image sources, the other one will then be called "rgb". Only one image
64 * source will yield in no ID at all.
65 *
66 * @param index Index of the camera
67 * @param index_count Number of cameras (or indices) in total
68 * @param depth_index Index of the depth camera
69 * @return Human readable string representation of the configuration
70 */
71 std::string
72 getHumanReadableCameraID(unsigned int index, unsigned int index_count, int depth_index);
73
74 /**
75 * @brief Helper function to create a date string
76 * @return
77 */
78 std::string getDateString();
79} // namespace
80
81namespace visionx
82{
84 {
85 providerName = "";
86 frameRate = -1.0f;
87
88 // Qt Moc does not seem to accept outputDirectory being a std::filesystem::path().
89 {
90 if (const char* home = std::getenv("HOME"))
91 {
92 // ToDo: Replace with XDG_PICTURES_DIR standards when available.
93 outputDirectory = std::filesystem::path(home) / "Pictures";
94 }
95 else
96 {
97 outputDirectory = std::filesystem::absolute(".");
98 }
99 }
100
101 imageBufferSize = 100;
102 bufferFps = 5;
103 controlsHidden = false;
104 depthImageIndex = -1;
105 maxDepthmm = 5000;
106 compressionType = eNoCompression;
108 }
109
111 // displayDelayFilter(20)
112 displayDelayFilter(IceUtil::Time::seconds(3), 100)
113 {
114 }
115
116 // *******************************************************
117 // Inherited from ArmarXWidgetController
118 // *******************************************************
119 QPointer<QWidget>
121 {
122 if (!widget)
123 {
124 widget = new ImageMonitorWidget(this);
125 }
126
127 return qobject_cast<QWidget*>(widget);
128 }
129
130 // *******************************************************
131 // Inherited from ImageProcessorBase
132 // *******************************************************
133 void
135 {
136 getWidget()->show();
137 std::unique_lock lock(imageMutex);
138 images = nullptr;
139 connected = false;
140 playing = false;
141 writeImageBuffer = false;
142 lastBufferTime = IceUtil::Time::now();
143 imageBuffer.resize(10);
144
145 // signals / slots
146 connect(this, SIGNAL(imageProviderConnected(bool)), widget, SLOT(setConnected(bool)));
147 connect(this,
148 SIGNAL(statisticsUpdated(const QString&)),
149 widget,
150 SLOT(updateStatistics(const QString&)));
151 connect(this, SIGNAL(recordingBufferEmpty(bool)), widget, SLOT(updateRecordButton(bool)));
152 }
153
154 void
156 {
157 if (properties.providerName != "" /*&& !connected*/)
158 {
159 applyProperties(properties);
160 }
161 }
162
163 void
165 {
166 disconnectFromProvider();
167 }
168
169 void
171 {
172 if (!connected)
173 {
174 usleep(10000);
175 return;
176 }
177
178 updateStatistics();
179
180 if (!playing)
181 {
182 usleep(10000);
183 return;
184 }
185
186 std::unique_lock lock(imageMutex);
187 unsigned int retrievedImages = 0;
188 const bool sourceFps = this->properties.frameRate < 0.0f;
189
190 // Fetch images and visualise
191 {
192 if (sourceFps && !this->waitForImages(this->properties.providerName))
193 {
194 ARMARX_VERBOSE << "Timeout or error in wait for images" << armarx::flush;
195 return;
196 }
197
198 armarx::MetaInfoSizeBasePtr info;
199 retrievedImages = static_cast<unsigned int>(
200 this->getImages(this->properties.providerName, this->images, info));
201 timeReceived = TimeUtil::GetTime();
202 if (sourceFps)
203 {
204 this->timeProvided = IceUtil::Time::microSeconds(info->timeProvided);
205 }
206
207 std::vector<CByteImage*> deleteList;
208 std::vector<CByteImage*> selectedImages;
209
210 for (unsigned int i = 0;
211 i < static_cast<unsigned int>(retrievedImages) && i < this->numberImages;
212 ++i)
213 {
214 CByteImage* currentImage;
215
216 if (i == static_cast<unsigned int>(this->properties.depthImageIndex) &&
217 this->properties.recordDepthRaw)
218 {
219 currentImage = new CByteImage(this->images[i]);
220 ::ImageProcessor::CopyImage(this->images[i], currentImage);
221 deleteList.push_back(currentImage);
222 }
223 else
224 {
225 currentImage = this->images[i];
226 }
227
228 if (this->properties.imagesToShow.size() == 0 or
229 (this->properties.imagesToShow.size() > 0 and
230 this->properties.imagesToShow.count(i) > 0))
231 {
232 if (i == static_cast<unsigned int>(this->properties.depthImageIndex))
233 {
234 this->convertToHeatMapDepthImage(currentImage);
235 }
236
237 selectedImages.push_back(currentImage);
238 }
239 }
240
241 if (selectedImages.size() > 0)
242 {
243 this->widget->drawImages(static_cast<int>(selectedImages.size()),
244 &selectedImages[0],
245 this->timeProvided,
246 timeReceived);
247 }
248
249 for (CByteImage* image : deleteList)
250 {
251 delete image;
252 }
253
254 if (!sourceFps)
255 {
256 this->fpsCounter.assureFPS(this->properties.frameRate);
257 }
258 }
259
260 if (writeImageBuffer && retrievedImages > 0)
261 {
262 if ((imageBuffer.size()) != static_cast<unsigned int>(properties.imageBufferSize) &&
263 properties.imageBufferSize > 0)
264 {
265 imageBuffer.resize(static_cast<unsigned int>(properties.imageBufferSize));
266 }
267
268 IceUtil::Time timePassed = IceUtil::Time::now() - lastBufferTime;
269
270 if (timePassed.toMilliSeconds() > 1000.f / properties.bufferFps)
271 {
272 ImageContainer newImages;
273
274 for (unsigned int i = 0; i < retrievedImages; i++)
275 {
276 newImages.push_back(CByteImagePtr(new CByteImage(images[i])));
277 ::ImageProcessor::CopyImage(images[i], newImages[i].get());
278 }
279
280 imageBuffer.push_front(newImages);
281 lastBufferTime = IceUtil::Time::now();
282 }
283 }
284
285 if (this->recordingTask && this->writeRecordingBuffer)
286 {
287 std::vector<CByteImage*> tmpImages(this->numberImages);
288 for (unsigned int i = 0; i < this->numberImages; ++i)
289 {
290 tmpImages.at(i) = new CByteImage(this->images[i]);
291 ::ImageProcessor::CopyImage(this->images[i], tmpImages[i]);
292 }
293 lock.unlock();
294 std::unique_lock lock2(this->recordingBufferMutex);
295 this->recordingBuffer.push(tmpImages);
296 }
297 }
298
299 void
301 {
302 properties.providerName = settings->value("providerName", "").toString().toStdString();
303 properties.frameRate = settings->value("frameRate", -1).toInt();
304 properties.outputDirectory = settings->value("outputPath", ".").toString().toStdString();
305 properties.imageBufferSize = settings->value("imageBufferSize", 99).toInt();
306 properties.bufferFps = settings->value("bufferFps", 5.0f).toFloat();
307 auto imagesToShowStringList = settings->value("imagesToShow", 0).toStringList();
308 properties.imagesToShow.clear();
309 for (QString& s : imagesToShowStringList)
310 {
311 properties.imagesToShow.insert(s.toULong());
312 }
313 properties.controlsHidden = settings->value("controlsHidden", false).toBool();
314 properties.depthImageIndex = settings->value("depthImageIndex", -1).toInt();
315 properties.maxDepthmm = settings->value("maxDepthmm", 5000).toInt();
316 properties.recordDepthRaw = settings->value("recordDepthRaw", true).toBool();
317 properties.recordingMethods = settings->value("recordingMethods", 0).toStringList();
318 properties.compressionType =
319 static_cast<CompressionType>(settings->value("compressionType", 0).toInt());
320 properties.compressionQuality = settings->value("compressionQuality", 0).toInt();
321
322 ARMARX_INFO << "bufferFps: " << properties.bufferFps;
323 }
324
325 void
327 {
328 settings->setValue("providerName", QString(properties.providerName.c_str()));
329 settings->setValue("frameRate", properties.frameRate);
330 settings->setValue("outputPath", QString(properties.outputDirectory.c_str()));
331 settings->setValue("imageBufferSize", properties.imageBufferSize);
332 settings->setValue("bufferFps", QString::number(static_cast<double>(properties.bufferFps)));
333 QStringList l;
334 for (auto number : properties.imagesToShow)
335 {
336 l << QString::number(number);
337 }
338 settings->setValue("imagesToShow", l);
339 settings->setValue("controlsHidden", properties.controlsHidden);
340 settings->setValue("depthImageIndex", properties.depthImageIndex);
341 settings->setValue("maxDepthmm", properties.maxDepthmm);
342 settings->setValue("recordDepthRaw", properties.recordDepthRaw);
343 settings->setValue("recordingMethods", properties.recordingMethods);
344
345 settings->setValue("compressionType", (int)properties.compressionType);
346 settings->setValue("compressionQuality", (int)properties.compressionQuality);
347 }
348
349 // *******************************************************
350 // properties handling
351 // *******************************************************
352 void
354 {
355 ARMARX_INFO << "Applying properties";
356 std::unique_lock lock(imageMutex);
357
358 disconnectFromProvider();
359
360 // update properties
361 this->properties = properties;
362
363 // connect to provider
364 try
365 {
366 connectToProvider();
367 }
368 catch (...)
369 {
371 }
372 }
373
376 {
377 return properties;
378 }
379
382 {
383 return getImageTransferStats(properties.providerName);
384 }
385
386 const ImageContainer&
388 unsigned int& realPosition)
389 {
390 int posInBuffer = static_cast<int>(imageBuffer.size()) - 1 - static_cast<int>(position);
391
392 if (posInBuffer < 0)
393 {
394 posInBuffer = 0;
395 }
396
397 if (static_cast<unsigned int>(posInBuffer) >= imageBuffer.size())
398 {
399 posInBuffer = static_cast<int>(imageBuffer.size()) - 1;
400 }
401
402 if (imageBuffer.size() == 0)
403 {
404 throw LocalException("ImageBuffer size is 0");
405 }
406
407 realPosition = static_cast<unsigned int>(posInBuffer);
408 return imageBuffer[static_cast<unsigned int>(posInBuffer)];
409 }
410
411 // *******************************************************
412 // private methods
413 // *******************************************************
414 void
415 ImageMonitorWidgetController::connectToProvider()
416 {
417 if (connected)
418 {
419 return;
420 }
421
422 // TODO: using image provider can be done only here???? Why???
424
425 ARMARX_INFO << getName() << " connecting to " << properties.providerName;
426
427 // connect to proxy
428 imageProviderInfo =
430
431 // update members
432 imageProviderPrx = imageProviderInfo.proxy;
433 numberImages = static_cast<unsigned int>(imageProviderInfo.numberImages);
434
435 // create images
436 {
437 std::unique_lock lock(imageMutex);
438 images = new CByteImage*[numberImages];
439
440 for (unsigned int i = 0; i < numberImages; i++)
441 {
442 images[i] = tools::createByteImage(imageProviderInfo);
443 }
444 }
445
446 timeProvided = IceUtil::Time::seconds(0);
447 ImageProcessor::setCompressionType(properties.compressionType,
448 properties.compressionQuality);
449 connected = true;
450
451
452 emit imageProviderConnected(true);
453 }
454
455 void
456 ImageMonitorWidgetController::disconnectFromProvider()
457 {
458 if (!connected)
459 {
460 return;
461 }
462 {
463 std::unique_lock lock(imageMutex);
464 // clear images
465 if (images)
466 {
467 for (unsigned int i = 0; i < numberImages; i++)
468 {
469 delete images[i];
470 }
471
472 delete[] images;
473 }
474 }
475 releaseImageProvider(properties.providerName);
476 // release provider
477 imageProviderPrx = nullptr;
478
479 connected = false;
480
481 emit imageProviderConnected(false);
482 }
483
484 std::string
486 {
487 namespace fs = std::filesystem;
488 fs::path absPath = fs::absolute(fs::path(properties.outputDirectory));
489 return absPath.string();
490 }
491
492 void
494 {
495 std::unique_lock lock(this->imageMutex);
496
497 std::filesystem::path path = this->getAbsoluteOutputPath();
498 std::string baseFilename = "snapshot_" + getDateString();
499
500 for (unsigned int i = 0; i < this->numberImages; ++i)
501 {
502 std::filesystem::path filename =
503 baseFilename +
504 getHumanReadableCameraID(i, this->numberImages, this->properties.depthImageIndex);
505 visionx::imrec::takeSnapshot(*this->images[i], path / filename);
506 }
507 }
508
509 void
511 {
512 if (this->recordingTask && this->recordingTask->isRunning())
513 {
514 return;
515 }
516
517 // Initialise needed values
518 const std::string baseFilename = "recording_" + getDateString();
519 const std::filesystem::path path = this->getAbsoluteOutputPath();
520 const double fps = [this]() -> double
521 {
522 if (this->properties.frameRate <= 0)
523 {
525 this->getImageTransferStats(this->properties.providerName);
526 const float source_fps = std::round(stats.imageProviderFPS.getFPS());
527 return static_cast<unsigned int>(source_fps);
528 }
529
530 return static_cast<double>(this->properties.frameRate);
531 }();
532
533 for (unsigned int i = 0; i < this->numberImages; ++i)
534 {
535 // Determine full filename and extension
536 const std::string ext =
537 this->properties.recordingMethods.at(static_cast<int>(i)).toStdString();
538 const std::filesystem::path filename =
539 baseFilename +
540 getHumanReadableCameraID(i, this->numberImages, this->properties.depthImageIndex) +
541 ext;
542 const std::filesystem::path fullFilePath = path / filename;
543
544 // Create recorder and add to list
546 ext != "" ? visionx::imrec::newRecording(fullFilePath, fps) : nullptr;
547 this->recorders.push_back(rec);
548 }
549
550 ARMARX_IMPORTANT << "Starting recording with " << fps
551 << " fps to path: " << getAbsoluteOutputPath();
552
553 this->recordingTask = new PeriodicTask<ImageMonitorWidgetController>(
554 this, &ImageMonitorWidgetController::recordFrame, 1, true, "ImageRecorderTask");
555 this->writeRecordingBuffer = true;
556 this->recordingTask->start();
557 }
558
559 void
561 {
562 emit this->recordingBufferEmpty(/* isEmpty = */ false);
563 // Disallow writing recording buffer and wait until it is empty
564 this->writeRecordingBuffer = false;
565 if (!this->recordingBuffer.empty())
566 {
567 ARMARX_IMPORTANT << "Stopping recording... Still " << this->recordingBuffer.size()
568 << " images in the queue to write";
569 return;
570 }
571
572 emit this->recordingBufferEmpty(/* isEmpty = */ true);
573
574 if (this->recordingTask)
575 {
576 this->recordingTask->stop();
577 }
578
579 ARMARX_INFO << "Closing recordings";
580
581 for (const visionx::imrec::Recording& rec : this->recorders)
582 {
583 if (rec)
584 {
585 rec->stopRecording();
586 }
587 }
588 this->recorders.clear();
589 }
590
591 void
592 ImageMonitorWidgetController::recordFrame()
593 {
594 std::vector<CByteImage*> images;
595 {
596 std::unique_lock lock(this->recordingBufferMutex);
597
598 // If the recording was stopped, keep running until the buffer was emptied completely
599 if (!this->writeRecordingBuffer)
600 {
601 if (this->recordingBuffer.empty())
602 {
603 ARMARX_IMPORTANT << "All images in queue were written";
604 this->stopRecording();
605 return;
606 }
607 else if (this->recordingBuffer.size() % 5 == 0)
608 {
609 ARMARX_INFO << "Stopping recording... Still " << this->recordingBuffer.size()
610 << " images in the queue to write";
611 }
612 }
613 else if (this->recordingBuffer.size() > 0 and this->recordingBuffer.size() % 5 == 0)
614 {
615 ARMARX_INFO << deactivateSpam(1) << "Recording buffer queue size currently at "
616 << this->recordingBuffer.size() << " images";
617 }
618
619 // Early return (nop) if the buffer is initially empty etc.
620 if (!this->connected or this->recordingBuffer.empty())
621 {
622 return;
623 }
624
625 images = this->recordingBuffer.front();
626 this->recordingBuffer.pop();
627 }
628
629 TIMING_START(imageWriting);
630
631 for (unsigned int i = 0; i < this->numberImages; ++i)
632 {
633 if (this->recorders[i])
634 {
635 this->recorders[i]->recordFrame(*images[i], std::chrono::microseconds{0});
636 }
637 delete images[i];
638 }
639
640 TIMING_END(imageWriting);
641 }
642
643 void
644 ImageMonitorWidgetController::updateStatistics()
645 {
646 std::unique_lock lock(imageMutex);
647 visionx::ImageTransferStats stats = getImageTransferStats(properties.providerName);
648
649 std::stringstream ss;
650
651 ss << std::fixed << std::setprecision(1)
652 << "source fps: " << stats.imageProviderFPS.getFPS();
653 ss << " - ";
654
655 IceUtil::Time displayDelay = widget->getImageViewer()->getDisplayDelay();
656 displayDelayFilter.update(timeReceived, displayDelay.toMilliSecondsDouble());
657
658 if (playing)
659 {
660 ss << "display fps: " << stats.pollingFPS.getFPS();
661 if (timeProvided.toMilliSeconds())
662 {
663 ss << " - image age: " << (timeReceived - timeProvided).toMilliSeconds()
664 << " ms - display delay: "
665 << IceUtil::Time::milliSecondsDouble(displayDelayFilter.getCurrentValue())
666 .toMilliSecondsDouble()
667 << " ms";
668 }
669 }
670 else
671 {
672 ss << "display paused";
673 }
674
675 std::string statisticsStr = ss.str();
676 emit statisticsUpdated(QString(statisticsStr.c_str()));
677 }
678
679 void
680 ImageMonitorWidgetController::hideControls(bool hide)
681 {
682 widget->hideControlWidgets(hide);
683 properties.controlsHidden = hide;
684 }
685
686 QPointer<QWidget>
688 {
689 if (customToolbar)
690 {
691 if (parent != customToolbar->parent())
692 {
693 customToolbar->setParent(parent);
694 }
695
696 return customToolbar.data();
697 }
698
699 customToolbar = new QToolBar(parent);
700 customToolbar->setIconSize(QSize(16, 16));
701
702 viewingModeAction =
703 customToolbar->addAction(QIcon(":icons/object-locked-2.ico"), "Hide controls");
704 viewingModeAction->setCheckable(true);
705 connect(viewingModeAction, SIGNAL(toggled(bool)), this, SLOT(hideControls(bool)));
706 viewingModeAction->setChecked(properties.controlsHidden);
707
708 return customToolbar.data();
709 }
710
711 void
713 {
714 float maxDistance = properties.maxDepthmm;
715 int pixelCount = depthImage->width * depthImage->height;
716 auto& depthToRgbLookUpTable = depthToRgbLookUpTables[maxDistance];
717 size_t depthValueCount = 256 * 256; // 16 bit depth images
718 if (depthToRgbLookUpTable.size() != depthValueCount)
719 {
720 ARMARX_VERBOSE << "Resizing lookup table for max distance " << maxDistance;
721 depthToRgbLookUpTable.resize(depthValueCount);
722 }
723 size_t pixelPos = 0;
724 for (int i = 0; i < pixelCount; ++i)
725 {
726 int z_value = visionx::tools::rgbToDepthValue(depthImage->pixels[pixelPos + 0],
727 depthImage->pixels[pixelPos + 1],
728 depthImage->pixels[pixelPos + 2],
729 false);
730 if (z_value > 0)
731 {
732 DrawColor24Bit rgb;
733 if (z_value <
734 static_cast<signed int>(
735 depthToRgbLookUpTable.size())) // lookup only for 16 bit depth images
736 {
737 std::optional<armarx::DrawColor24Bit>& rgbOptional =
738 depthToRgbLookUpTable.at(z_value);
739 if (rgbOptional)
740 {
741 rgb = *rgbOptional;
742 }
743 else
744 {
745 auto hsv = colorutils::HeatMapColor(1.0f - z_value / maxDistance);
746 rgb = colorutils::HsvToRgb(hsv);
747 rgbOptional = rgb;
748 }
749 }
750 else // fallback for 24 bit depth images
751 {
752 auto hsv = colorutils::HeatMapColor(1.0f - z_value / maxDistance);
753 rgb = colorutils::HsvToRgb(hsv);
754 }
755 depthImage->pixels[pixelPos] = rgb.r;
756 depthImage->pixels[pixelPos + 1] = rgb.g;
757 depthImage->pixels[pixelPos + 2] = rgb.b;
758 }
759 else
760 {
761 depthImage->pixels[pixelPos] = 0;
762 depthImage->pixels[pixelPos + 1] = 0;
763 depthImage->pixels[pixelPos + 2] = 0;
764 }
765 pixelPos += 3;
766 }
767 }
768
769
770} // namespace visionx
771
772namespace
773{
774 std::string
775 getHumanReadableCameraID(unsigned int index, unsigned int index_count, int depth_index)
776 {
777 if (index_count >= 2)
778 {
779 if (depth_index >= 0)
780 {
781 if (index == static_cast<unsigned int>(depth_index))
782 {
783 return "_depth";
784 }
785 if (index_count == 2 and index != static_cast<unsigned int>(depth_index))
786 {
787 return "_rgb";
788 }
789 }
790 else if (index_count == 2)
791 {
792 if (index == 0)
793 {
794 return "_left";
795 }
796 if (index == 1)
797 {
798 return "_right";
799 }
800 }
801
802 return "_cam" + std::to_string(index);
803 }
804
805 return "";
806 }
807
808 std::string
809 getDateString()
810 {
811 IceUtil::Time recordStartTime = IceUtil::Time::now();
812 std::string date_str = recordStartTime.toDateTime();
813 // I checked that this is equal to using boost::replace_all()
814 date_str = simox::alg::replace_all(date_str, "/", "-");
815 date_str = simox::alg::replace_all(date_str, " ", "_");
816 date_str = simox::alg::replace_all(date_str, ":", "-");
817 return date_str;
818 }
819} // namespace
uint8_t index
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
std::string getName() const
Retrieve name of object.
The periodic task executes one thread method repeatedly using the time period specified in the constr...
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
float getFPS()
Get frames per second.
ImageMonitorProperties brief one line description.
void imageProviderConnected(bool connected)
void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
void applyProperties(ImageMonitorProperties properties)
void statisticsUpdated(const QString &statisticsString)
QPointer< QWidget > getCustomTitlebarWidget(QWidget *parent) override
getTitleToolbar returns a pointer to the a toolbar widget of this controller.
void onExitImageProcessor() override
Exit the ImapeProcessor component.
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
void process() override
Process the vision component.
const ImageContainer & getBufferedImage(unsigned int position, unsigned int &realPosition)
void onInitImageProcessor() override
Setup the vision component.
QPointer< QWidget > getWidget() override
getWidget returns a pointer to the a widget of this controller.
void startRecording()
Start recording of the images to bmp-files.
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
bool waitForImages(int milliseconds=1000)
Wait for new images.
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
int getImages(CByteImage **ppImages)
Poll images from provider.
ImageTransferStats getImageTransferStats(std::string provideNname, bool resetStats=false)
Retrieve statistics for a connection to an ImageProvider.
void setCompressionType(CompressionType compressionType=ePNG, int compressionQuality=9)
Sets the compression type and compression quality.
void releaseImageProvider(std::string providerName)
int numberImages
Number of images.
ImageProviderInterfacePrx proxy
proxy to image provider
The ImageTransferStats class provides information on the connection between ImageProvider and ImagePr...
FPSCounter pollingFPS
Statistics for the images polled by the ImageProcessor.
FPSCounter imageProviderFPS
Statistics for the images announced by the ImageProvider.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define TIMING_START(name)
Helper macro to do timing tests.
Definition TimeUtil.h:289
#define TIMING_END(name)
Prints duration.
Definition TimeUtil.h:306
HsvColor HeatMapColor(float percentage)
HeatMapColor calculates the color of a value between 0 and 1 on a heat map.
Definition ColorUtils.h:161
DrawColor24Bit HsvToRgb(const HsvColor &in)
Definition ColorUtils.h:34
This file offers overloads of toIce() and fromIce() functions for STL container types.
void handleExceptions()
const LogSender::manipulator flush
Definition LogSender.h:251
int toInt(const std::string &input)
visionx::imrec::Recording newRecording(const std::filesystem::path &path, const std::string &name, const Format format, double fps)
void takeSnapshot(const CByteImage &image, const std::filesystem::path &filePath)
Takes a snapshot using the default recording method for snapshots.
std::shared_ptr< AbstractRecordingStrategy > Recording
Convenience alias for any recording strategy.
ImageType typeNameToImageType(const std::string &imageTypeName)
Converts an image type name as string into an ImageType integer.
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
float rgbToDepthValue(unsigned char r, unsigned char g, unsigned char b, bool noiseResistant=false)
Definition ImageUtil.h:148
ArmarX headers.
std::shared_ptr< CByteImage > CByteImagePtr
std::vector< CByteImagePtr > ImageContainer