22 #include <qtconcurrentrun.h>
24 #include <QApplication>
26 #include <QProgressDialog>
29 #if defined(CV_WINDOWS)
36 #ifdef USE_PYTHON_MODULE
37 ecvDeepSemanticSegmentationTool::ecvDeepSemanticSegmentationTool(
40 Ui::DeepSemanticSegmentationDlg(),
41 m_show_progress(true) {
43 connect(detectToolButton, &QAbstractButton::clicked,
this,
44 &ecvDeepSemanticSegmentationTool::detect);
45 connect(appyToolButton, &QAbstractButton::clicked,
this,
46 &ecvDeepSemanticSegmentationTool::apply);
47 connect(cancelToolButton, &QAbstractButton::clicked,
this,
48 &ecvDeepSemanticSegmentationTool::cancel);
49 connect(selectAllRadioButton, &QAbstractButton::clicked,
this,
50 &ecvDeepSemanticSegmentationTool::selectAllClasses);
51 connect(unselectAllRadioButton, &QAbstractButton::clicked,
this,
52 &ecvDeepSemanticSegmentationTool::selectAllClasses);
55 ecvDeepSemanticSegmentationTool::~ecvDeepSemanticSegmentationTool() {}
57 bool ecvDeepSemanticSegmentationTool::linkWith(QWidget* win) {
65 bool ecvDeepSemanticSegmentationTool::addEntity(
ccHObject* entity) {
70 if (pointNumber < 65536) {
71 CVLog::Warning(QString(
"[ecvDeepSemanticSegmentationTool::addEntity] "
72 "Skip entity [%1] as the point number of it is "
73 "%2 lower than min limit 65536!")
74 .arg(entity->
getName(), pointNumber));
83 unsigned ecvDeepSemanticSegmentationTool::getNumberOfValidEntities()
const {
84 return m_entity.getChildrenNumber();
87 bool ecvDeepSemanticSegmentationTool::start() {
91 if (!m_clusters_map.empty()) {
92 m_clusters_map.clear();
94 if (!m_clusters.empty()) {
98 if (m_selectedEntity.getChildrenNumber() != 0) {
99 m_selectedEntity.detachAllChildren();
102 unsigned childNum = getNumberOfValidEntities();
103 if (childNum == 0)
return false;
105 selectedTreeWiget->headerItem()->setCheckState(0, Qt::Checked);
106 for (
unsigned i = 0; i < getNumberOfValidEntities(); ++i) {
107 QTreeWidgetItem* item =
new QTreeWidgetItem();
108 item->setCheckState(0, Qt::Checked);
109 item->setText(1, m_entity.getChild(i)->getName());
110 selectedTreeWiget->insertTopLevelItem(i, item);
113 #ifdef USE_PYTHON_MODULE
120 void ecvDeepSemanticSegmentationTool::apply() {
121 if (m_clusters_map.empty())
123 performSegmentation();
130 void ecvDeepSemanticSegmentationTool::detect() {
131 if (performSegmentation() > 0) {
132 exportClustersToSF();
133 refreshSelectedClouds();
137 void ecvDeepSemanticSegmentationTool::refreshSelectedClouds() {
139 for (
unsigned i = 0; i < m_selectedEntity.getChildrenNumber(); ++i) {
140 m_selectedEntity.getChild(i)->setRedrawFlagRecursive(
true);
145 void ecvDeepSemanticSegmentationTool::cancel() {
150 void ecvDeepSemanticSegmentationTool::stop(
bool state) {
154 void ecvDeepSemanticSegmentationTool::clear() {
155 m_entity.detachAllChildren();
156 for (
int i = 0; i < selectedTreeWiget->topLevelItemCount(); ++i) {
157 delete selectedTreeWiget->takeTopLevelItem(i);
160 m_clusters_map.clear();
162 m_selectedEntity.detachAllChildren();
165 void ecvDeepSemanticSegmentationTool::getSegmentations(
167 if (exportModeComboBox->currentIndex() == 0) {
168 exportClustersToEntities(
result);
169 }
else if (exportModeComboBox->currentIndex() == 1) {
170 exportClustersToSF();
174 void ecvDeepSemanticSegmentationTool::updateSelectedEntity() {
175 m_selectedEntity.detachAllChildren();
176 for (
int i = 0; i < selectedTreeWiget->topLevelItemCount(); ++i) {
177 QTreeWidgetItem* item = selectedTreeWiget->topLevelItem(i);
178 if (item->checkState(0) == Qt::Checked) {
179 for (
unsigned j = 0; j < getNumberOfValidEntities(); ++j) {
180 if (item->text(1) == m_entity.getChild(j)->getName()) {
181 m_selectedEntity.addChild(m_entity.getChild(j),
190 void ecvDeepSemanticSegmentationTool::exportClustersToSF() {
192 m_selectedEntity.filterChildren(selectedClouds,
false,
194 if (m_clusters.size() != selectedClouds.size()) {
196 "[ecvDeepSemanticSegmentationTool] dimensions do not match!");
200 std::vector<std::vector<ScalarType>> scalarsVector;
201 ccEntityAction::ConvertToScalarType<size_t>(m_clusters, scalarsVector);
204 "[ecvDeepSemanticSegmentationTool::exportClustersToSF] import "
208 void ecvDeepSemanticSegmentationTool::exportClustersToEntities(
210 bool needFresh =
false;
211 for (
unsigned int i = 0; i < m_selectedEntity.getChildrenNumber(); ++i) {
236 for (ClassMap::ClusterMap::const_iterator it = clusterMap.begin();
237 it != clusterMap.end(); ++it) {
240 res->
setName(it->first.c_str());
250 result.push_back(ecvGroup);
255 refreshSelectedClouds();
258 for (
unsigned i = 0; i < m_selectedEntity.getChildrenNumber(); ++i) {
259 m_selectedEntity.getChild(i)->setEnabled(
false);
263 void ecvDeepSemanticSegmentationTool::getSelectedFilterClasses(
264 std::vector<size_t>& filteredClasses) {
265 if (!filteredClasses.empty()) {
266 filteredClasses.clear();
269 if (unlabeledCheckBox->isChecked()) filteredClasses.push_back(0);
270 if (manMadeTerrainCheckBox->isChecked()) filteredClasses.push_back(1);
271 if (naturalTerrainCheckBox->isChecked()) filteredClasses.push_back(2);
272 if (highVegetationCheckBox->isChecked()) filteredClasses.push_back(3);
273 if (lowVegetationCheckBox->isChecked()) filteredClasses.push_back(4);
274 if (buildingsCheckBox->isChecked()) filteredClasses.push_back(5);
275 if (hardScapeCheckBox->isChecked()) filteredClasses.push_back(6);
276 if (scanningArtifactsCheckBox->isChecked()) filteredClasses.push_back(7);
277 if (carsCheckBox->isChecked()) filteredClasses.push_back(8);
278 if (utilityPoleCheckBox->isChecked()) filteredClasses.push_back(9);
279 if (insulatorCheckBox->isChecked()) filteredClasses.push_back(10);
280 if (electricalWireCheckBox->isChecked()) filteredClasses.push_back(11);
281 if (crossBarCheckBox->isChecked()) filteredClasses.push_back(12);
282 if (stickCheckBox->isChecked()) filteredClasses.push_back(13);
283 if (fuseCheckBox->isChecked()) filteredClasses.push_back(14);
284 if (wireClipCheckBox->isChecked()) filteredClasses.push_back(15);
285 if (linkerInsulatorCheckBox->isChecked()) filteredClasses.push_back(16);
286 if (personsCheckBox->isChecked()) filteredClasses.push_back(17);
287 if (trafficSignCheckBox->isChecked()) filteredClasses.push_back(18);
288 if (trafficLightCheckBox->isChecked()) filteredClasses.push_back(19);
291 void ecvDeepSemanticSegmentationTool::selectAllClasses() {
292 bool state = selectAllRadioButton->isChecked();
293 QList<QCheckBox*> list = classGroupBox->findChildren<QCheckBox*>();
295 foreach (QCheckBox* ncheckBox, list) {
297 ncheckBox->setChecked(state);
302 int ecvDeepSemanticSegmentationTool::performSegmentation() {
303 m_clusters_map.clear();
305 updateSelectedEntity();
308 int check_result = checkSelected();
309 if (check_result != 1) {
314 int start_status = startDetection();
315 if (start_status != 1) {
320 size_t entityNumber = m_selectedEntity.getChildrenNumber();
321 if (m_clusters_map.size() != entityNumber) {
329 int ecvDeepSemanticSegmentationTool::checkSelected() {
331 if (m_selectedEntity.getChildrenNumber() == 0) {
332 CVLog::Warning(
"no selected point cloud, please select one again!");
336 std::vector<size_t> selectedFilters;
337 getSelectedFilterClasses(selectedFilters);
338 if (selectedFilters.empty()) {
340 "no selected class, please select at least one to continue!");
349 int ecvDeepSemanticSegmentationTool::startDetection() {
356 QString tipInfo =
"Operation in progress, please wait for a while";
357 if (useVotesCheckBox->isChecked()) {
358 tipInfo +=
"\n(disable votes to speed up!)";
361 QProgressDialog progressCb(tipInfo, QString(), 0, 0);
363 if (m_show_progress) {
364 progressCb.setWindowTitle(tr(
"Deep Semantic Segmentation"));
366 QApplication::processEvents();
373 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
374 QFuture<void> future = QtConcurrent::run([
this]() { this->
doCompute(); });
376 QFuture<void> future = QtConcurrent::run(
379 while (!future.isFinished()) {
380 #if defined(CV_WINDOWS)
385 if (m_show_progress) progressCb.setValue(++progress);
391 if (m_show_progress) {
393 QApplication::processEvents();
396 CVLog::Print(QString(
"Deep Semantic Segmentation: finish cost %1 s")
407 #ifdef USE_PYTHON_MODULE
409 cloudViewer::utility::DeepSemanticSegmentation dss;
410 dss.setEnableSampling(samplingCheckBox->isChecked());
411 dss.setEnableVotes(useVotesCheckBox->isChecked());
412 dss.setInputCloud(&m_selectedEntity);
413 dss.compute(m_clusters, m_clusters_map);
415 if (m_clusters_map.empty()) {
421 std::vector<size_t> filteredClasses;
422 getSelectedFilterClasses(filteredClasses);
423 for (
auto itMap = m_clusters_map.begin();
424 itMap != m_clusters_map.end();) {
425 auto& clusterMap = *itMap;
426 for (
auto it = clusterMap.begin(); it != clusterMap.end();) {
430 QString(
"ignore class index {%1}").arg(index));
435 auto ret = std::find(filteredClasses.begin(),
436 filteredClasses.end(), index);
437 if (ret == filteredClasses.end() ||
438 it->second.size() < clusterMinSizeSpinBox->value()) {
439 it = clusterMap.erase(it);
446 if (clusterMap.empty()) {
447 itMap = m_clusters_map.erase(itMap);
454 }
catch (
const std::exception&) {
459 CVLog::Warning(
"python interface library has not been compiled!");
static int s_computeStatus
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
virtual void setVisible(bool state)
Sets entity visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
Hierarchical CLOUDVIEWER Object.
unsigned getChildrenNumber() const
Returns the number of children.
ccHObject * getParent() const
Returns parent object.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
virtual QString getName() const
Returns object name.
virtual void setName(const QString &name)
Sets object name.
bool isKindOf(CV_CLASS_ENUM type) const
Generic overlay dialog interface.
virtual void stop(bool accepted)
Stops process/dialog.
virtual bool start()
Starts process.
virtual bool linkWith(QWidget *win)
Links the overlay dialog with a MDI window.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
static ccPointCloud * From(const cloudViewer::GenericIndexedCloud *cloud, const ccGenericPointCloud *sourceCloud=nullptr)
Creates a new point cloud object from a GenericIndexedCloud.
bool hasDisplayedScalarField() const override
Returns whether an active scalar field is available or not.
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
void deleteScalarField(int index) override
Deletes a specific scalar field.
unsigned size() const override
std::map< std::string, std::vector< size_t > > ClusterMap
static int FindindexByValue(const std::string &value)
bool importToSF(const ccHObject::Container &selectedEntities, const std::vector< std::vector< ScalarType >> &scalarsVector, const std::string &name)
void Sleep(int milliseconds)