25#include <boost/lexical_cast.hpp>
27#include <pcl/common/colors.h>
45 return boost::lexical_cast<std::string>(t);
52 return QString::fromStdString(boost::lexical_cast<std::string>(t));
61 return "VisionX.UserAssistedSegmenterGui";
70 widget.tableSegmentsOverviewLayout->addWidget(segmentsOverviewTable);
71 widget.tableSegmentsOverviewPlaceholder->deleteLater();
75 widget.tableUserGrouping->setColumnCount(3);
76 widget.tableUserGrouping->setRowCount(0);
81 <<
"Space seperated segment IDs";
82 widget.tableUserGrouping->setHorizontalHeaderLabels(header);
83 widget.tableUserGrouping->setColumnWidth(0, 30);
84 widget.tableUserGrouping->setColumnWidth(1, 40);
111 return qobject_cast<UserAssistedSegmenterConfigDialog*>(configDialog);
117 userAssistedSegmenterProxyName = configDialog->getUserAssistedSegmenterProxyName();
118 userAssistedSegmenterTopicName = configDialog->getUserAssistedSegmenterTopicName();
125 drawer.offeringTopic(*
this);
133 drawer.getTopic(*
this);
139 ARMARX_ERROR <<
"Could not get proxy '" << userAssistedSegmenterProxyName <<
"'.";
144 connect(widget.spinBoxFilterSmallSegmentsNum,
145 SIGNAL(editingFinished()),
149 connect(widget.checkBoxFilterSegment0, SIGNAL(toggled(
bool)),
this, SLOT(
updateFilters()));
151 widget.checkBoxFilterSmallSegments, SIGNAL(toggled(
bool)),
this, SLOT(
updateFilters()));
153 connect(widget.checkBoxShowIDs, SIGNAL(toggled(
bool)),
this, SLOT(
onShowIDsToggled(
bool)));
154 connect(widget.radioButtonShowInput,
155 SIGNAL(toggled(
bool)),
158 connect(widget.radioButtonShowResult,
159 SIGNAL(toggled(
bool)),
163 connect(widget.spinBoxNumObjects,
164 SIGNAL(valueChanged(
int)),
167 connect(widget.tableUserGrouping,
168 SIGNAL(cellChanged(
int,
int)),
172 connect(widget.buttonClearVisu, SIGNAL(released()),
this, SLOT(
clearVisualization()));
175 connect(widget.tableUserGrouping,
176 SIGNAL(cellChanged(
int,
int)),
181 for (
auto& spinBox : {widget.spinTextSize, widget.spinSphereSize})
183 connect(spinBox, SIGNAL(valueChanged(
int)),
this, SLOT(
updateSegmentIDs()));
189 const visionx::ColoredLabeledPointCloud& receivedPointCloud,
192 if (!widget.checkBoxListening->isChecked())
202 ARMARX_INFO <<
"Emittinging signal receivedSegmentation().";
211 widget.labelPcStatus->setText(QString(
"Processing..."));
213 this->pointCloud = sourcePointCloud;
215 computeSegmentIndex(pointCloud);
217 applyFilters(pointCloud, segmentIndex);
219 updatePointCloud(pointCloud, segmentIndex);
223 widget.labelPcStatus->setText(QString(
"Current point cloud:"));
229 widget.checkBoxFilterSmallSegments->setChecked(
230 widget.spinBoxFilterSmallSegmentsNum->value() > 0);
236 applyFilters(pointCloud, segmentIndex);
237 updatePointCloud(pointCloud, segmentIndex);
245 drawInputPointCloud(
false);
254 drawResultPointCloud(
false);
263 drawSegmentIDs(
false);
267 drawer.clearLayer(layerSegmentIDs);
278 UserAssistedSegmenterGuiWidgetController::applyFilters(
280 std::map<uint32_t, pcl::PointIndices>& segmentIndex)
284 if (widget.checkBoxFilterSegment0)
286 auto ifLabelZero = [](
const PointT& p) {
return p.label == 0; };
287 pointCloud.erase(std::remove_if(pointCloud.begin(), pointCloud.end(), ifLabelZero),
290 computeSegmentIndex(pointCloud);
293 if (widget.checkBoxFilterSmallSegments->isChecked())
295 const int minPoints = std::max(0, widget.spinBoxFilterSmallSegmentsNum->value());
300 auto ifLessPoints = [&segmentIndex, minPoints](
const PointT& p) {
301 return segmentIndex.at(p.label).indices.size() <
302 static_cast<std::size_t
>(minPoints);
304 pointCloud.erase(std::remove_if(pointCloud.begin(), pointCloud.end(), ifLessPoints),
307 computeSegmentIndex(pointCloud);
313 UserAssistedSegmenterGuiWidgetController::updatePointCloud(
315 const std::map<uint32_t, pcl::PointIndices>& segmentIndex)
318 computeCenters(pointCloud, segmentIndex);
320 widget.labelPcPointsNum->setText(
qstr(pointCloud.size()));
321 widget.labelPcSegmentsNum->setText(
qstr(segmentIndex.size()));
323 updateTableOverview();
324 drawInputPointCloud();
325 drawSegmentIDs(
true);
329 UserAssistedSegmenterGuiWidgetController::computeSegmentIndex(
const PointCloudT& pointCloud)
331 segmentIndex.clear();
332 const bool excludeZero =
false;
337 UserAssistedSegmenterGuiWidgetController::computeCenters(
339 const std::map<uint32_t, pcl::PointIndices>& segmentIndex)
343 for (
const auto& [segmentID, indices] : segmentIndex)
348 const PointT& p = pointCloud[
static_cast<std::size_t
>(i)];
349 center += Vector3f(p.x, p.y, p.z);
351 center /= segmentIndex.at(segmentID).indices.size();
352 centers[segmentID] =
center;
357 UserAssistedSegmenterGuiWidgetController::updateTableOverview()
359 segmentsOverviewTable->setData(segmentIndex);
363 UserAssistedSegmenterGuiWidgetController::drawSegmentIDs(
bool onlyIfChecked)
365 if (onlyIfChecked && !widget.checkBoxShowIDs->isChecked())
370 drawer.clearLayer(layerSegmentIDs,
true);
372 for (
const auto& [segmentID, _] : segmentIndex)
374 const int textSize = widget.spinTextSize->value();
375 const int sphereSize = widget.spinSphereSize->value();
377 const DrawColor segColor = dcolor(segmentID);
378 const DrawColor textColor = (segColor.r + segColor.g + segColor.b) > 1.f
379 ? DrawColor{0, 0, 0, 1}
380 : DrawColor{1, 1, 1, 1};
382 drawer.drawText({layerSegmentIDs,
"id" +
str(segmentID)},
387 drawer.drawSphere({layerSegmentIDs,
"sph" +
str(segmentID)},
395 UserAssistedSegmenterGuiWidgetController::drawInputPointCloud(
bool onlyIfChecked)
397 if (onlyIfChecked && !widget.radioButtonShowInput->isChecked())
405 drawer.drawPointCloud({layerPointCloud,
"PointCloud"},
407 [
this](
const PointT& p) {
return dcolor(p.label); });
413 UserAssistedSegmenterGuiWidgetController::drawResultPointCloud(
bool onlyIfChecked)
415 if (onlyIfChecked && !widget.radioButtonShowResult->isChecked())
422 DebugDrawerColoredPointCloud debugPointCloud;
424 for (std::size_t group = 0; group < userGrouping.size(); ++group)
426 for (uint32_t segment : userGrouping[group])
428 for (
int i : segmentIndex.at(segment).indices)
430 PointT& p = pointCloud[
static_cast<std::size_t
>(i)];
431 debugPointCloud.points.push_back(
432 DebugDrawerColoredPointCloudElement{p.x, p.y, p.z, dcolor(group)});
437 drawer.drawPointCloud({layerPointCloud,
"PointCloud"}, debugPointCloud);
443 UserAssistedSegmenterGuiWidgetController::dcolor(std::size_t
id)
const
451 return static_cast<int>(f * 255);
455 UserAssistedSegmenterGuiWidgetController::qcolor(std::size_t
id)
const
457 const DrawColor
c = dcolor(
id);
464 int previousNumRows = widget.tableUserGrouping->rowCount();
465 widget.tableUserGrouping->setRowCount(numRows);
467 std::set<uint32_t> segmentIDs;
468 for (
const auto& [segmentID, _] : segmentIndex)
470 segmentIDs.insert(segmentID);
474 for (
int id = previousNumRows;
id < numRows; ++id)
476 QTableWidgetItem* itemColor =
new QTableWidgetItem(QString());
477 itemColor->setBackgroundColor(qcolor(
static_cast<std::size_t
>(
id)));
478 widget.tableUserGrouping->setItem(
id, 0, itemColor);
480 QTableWidgetItem* itemID =
new QTableWidgetItem(
qstr(
id));
481 itemID->setTextAlignment(Qt::AlignCenter);
482 widget.tableUserGrouping->setItem(
id, 1, itemID);
487 SIGNAL(groupingChanged(uint32_t, std::vector<uint32_t>)),
490 widget.tableUserGrouping->setCellWidget(
id, 2, itemList);
493 userGrouping.resize(
static_cast<std::size_t
>(numRows));
499 std::vector<uint32_t> segmentIDs)
501 if (groupID < userGrouping.size())
503 userGrouping[groupID] = segmentIDs;
505 ARMARX_INFO <<
"Updated user grouping " << groupID <<
": \n" << userGrouping[groupID];
506 drawResultPointCloud(
true);
515 widget.tableUserGrouping->item(row, col)->setText(QString());
519 widget.tableUserGrouping->item(row, col)->setText(
qstr(row));
532 visionx::ColoredLabeledPointCloud resultCloud;
534 for (std::size_t groupID = 0; groupID < userGrouping.size(); ++groupID)
536 for (uint32_t segment : userGrouping[groupID])
538 for (
int i : segmentIndex.at(segment).indices)
540 PointT& p = pointCloud.at(
static_cast<std::size_t
>(i));
541 resultCloud.push_back(
542 visionx::ColoredLabeledPoint3D{visionx::Point3D{p.x, p.y, p.z},
543 visionx::RGBA{p.r, p.g, p.b, p.a},
544 static_cast<int>(groupID)});
548 segmenterProxy->publishSegmentation(resultCloud);
554 drawer.clearLayer(layerSegmentIDs);
555 drawer.clearLayer(layerPointCloud);
556 drawer.clearColoredPointCloud({layerPointCloud,
"PointCloud"});
static DrawColor at(std::size_t id, float alpha=1.f)
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
#define ARMARX_CHECK_NONNEGATIVE(number)
Check whether number is nonnegative (>= 0).
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
state::Type center(state::Type previous)
This file offers overloads of toIce() and fromIce() functions for STL container types.
pcl::PointCloud< PointT > PointCloudT
pcl::PointIndices::Ptr indices(const PCG &g)
Retrieve the indices of the points of the point cloud stored in a point cloud graph that actually bel...