/** * @file DialogPCLStatisticalRemoveFilter.cpp * @brief None * @author 陈增辉 (3045316072@qq.com) * @version 2.5.0 * @date 2024/4/5 * @copyright Copyright (c) Since 2024 中科卫星应用研究院 All rights reserved. */ // You may need to build the project (run Qt uic code generator) to get // "ui_DialogPCLStatisticalRemoveFilter.h" resolved #include "DialogPCLRadiusOutlierRemoval.h" #include "ui_DialogPCLRadiusOutlierRemoval.h" #include "PythonModule/PyAgent.h" #include "MeshData/meshSingleton.h" #include "MeshData/meshSet.h" #include #include #include #include #include #include #include #include "MeshData/meshKernal.h" #include "PointCloudOperator/PointCloudCommon.h" #include "Settings/BusAPI.h" #include "BaseTool.h" #include "IO/IOConfig.h" #include "ModuleBase/ThreadControl.h" #include "ConfigOptions/ConfigOptions.h" #include "ConfigOptions/MeshConfig.h" #include "Common/DebugLogger.h" namespace MainWidget { DialogPCLRadiusOutlierRemoval::DialogPCLRadiusOutlierRemoval(GUI::MainWindow *parent) : QFDialog(parent), _ui(new Ui::DialogPCLRadiusOutlierRemoval), _mw(parent), _selectdlg(new DialogSelectComponents(parent)) { _ui->setupUi(this); _ui->geoSelectPoint->setToolTip(tr("Clicked Button Selected Components")); setWindowTitle(tr("Radius Outlier Removal")); _ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(_ui->geoSelectPoint, &QPushButton::clicked, [=]() { _selectdlg->clearSelectItems(); _selectdlg->exec(); }); connect(_selectdlg, SIGNAL(selectedComponentsSig(QList)), this, SLOT(selectedComponentsSlot(QList))); connect(_ui->listWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(customContextMenuRequestedSlot(const QPoint &))); } DialogPCLRadiusOutlierRemoval::~DialogPCLRadiusOutlierRemoval() { delete _ui; _ui = NULL; delete _selectdlg; _selectdlg = NULL; } void DialogPCLRadiusOutlierRemoval::accept() { if (_components.size() == 0) return; QString componentIds, rotate, moveLocation, scale; for (auto component : _components) componentIds.append(QString(",%1").arg(component->getID())); componentIds.remove(0, 1); double RadiusSearch=_ui->RadiusSearch->value(); double MinNeighborsInRadius=_ui->MinNeighborsInRadius->value(); QString outfilename="filter"; for (auto component : _components) outfilename.append(QString("_%1").arg(component->getName())); // 确定是否保存结果文件 QMessageBox::StandardButton result=QMessageBox::critical(this, "info","save as result ?"); QString filepath= JoinPath(Setting::BusAPI::instance()->getWorkingDir() ,outfilename+"_tmep.pcd"); QString AbFileName; if(result==QMessageBox::StandardButton::Ok||result==QMessageBox::StandardButton::Yes){ QStringList suffixlist = IO::IOConfigure::getPclExporters(); if(suffixlist.isEmpty()) { QMessageBox::warning(this, tr("Warning"), tr("The MeshPlugin is not installed !")); return; } if(MeshData::MeshData::getInstance()->getKernalCount() == 0) { QMessageBox::warning(this, tr("Warning"), tr("No one has any grid!")); return; } QStringList meshsuffix = ConfigOption::ConfigOption::getInstance() ->getMeshConfig() ->getExportSuffix(ConfigOption::MeshDataType::PointCloud) .split(";"); QStringList list; for(QString s : meshsuffix) { for(int i = 0; i < suffixlist.size(); i++) { QString suffix = suffixlist.at(i); if(suffix.contains(s)) list.append(suffix); } } std::sort(list.begin(), list.end()); QString suffixes = list.join(";;"); QString workDir = Setting::BusAPI::instance()->getWorkingDir(); QFileDialog dlg(this, tr("Export Pcl"), workDir, suffixes); dlg.setAcceptMode(QFileDialog::AcceptSave); if(dlg.exec() != QFileDialog::FileName) return; QString aSuffix = dlg.selectedNameFilter(); QString aFileName = dlg.selectedFiles().join(","); if(!(aFileName.isEmpty())){ filepath=aFileName; }else{} AbFileName=filepath; QTextCodec *codec = QTextCodec::codecForName("GB18030"); QByteArray ba = codec->fromUnicode(filepath); std::string outFileName=ba.data(); }else{ // 不保存成点云数据 } // 启动线程 auto pclfilter = new WBFZ::PCLRadiusOutlierRemoval( AbFileName,WBFZ::PointCloudOperation::POINTCLOUD_FILTER,_mainWindow,componentIds, RadiusSearch,MinNeighborsInRadius); ModuleBase::ThreadControl* tc = new ModuleBase::ThreadControl(pclfilter); emit tc->threadStart(); // emit MSHwriter->start(); QFDialog::accept(); } void DialogPCLRadiusOutlierRemoval::selectedComponentsSlot(QList components) { for (MeshData::MeshSet *set : components) { if (_components.contains(set)) continue; _components.append(set); _ui->listWidget->addItem(set->getName()); } } void DialogPCLRadiusOutlierRemoval::customContextMenuRequestedSlot(const QPoint &point) { QListWidgetItem *curItem = _ui->listWidget->itemAt(point); if (!curItem) return; QMenu *menu = new QMenu(this); QAction *deleteItem = new QAction(tr("delete this item")); menu->addAction(deleteItem); connect(menu, &QMenu::triggered, [=]() { removeCurrentItem(curItem); }); menu->exec(QCursor::pos()); } void DialogPCLRadiusOutlierRemoval::removeCurrentItem(QListWidgetItem *curItem) { auto meshData = MeshData::MeshData::getInstance(); auto meshSet = meshData->getMeshSetByName(curItem->text()); if (!meshSet) return; _components.removeOne(meshSet); _ui->listWidget->removeItemWidget(curItem); delete curItem; } } // namespace MainWidget namespace WBFZ{ WBFZ::PCLRadiusOutlierRemoval::PCLRadiusOutlierRemoval(const QString &fileName, WBFZ::PointCloudOperation operation, GUI::MainWindow* mw, QString componentIds, double RadiusSearch,double MinNeighborsInRadius) : PointCloudThreadBase(fileName, operation, mw) , _fileName(fileName) , _operation(operation) , _componentIds(componentIds) , _RadiusSearch(RadiusSearch) , _MinNeighborsInRadius(MinNeighborsInRadius) { } vtkDataSet* WBFZ::PCLRadiusOutlierRemoval::PCLRadiusOutlierRemovalAlg(QString componentIds, double RadiusSearch, double MinNeighborsInRadius) { emit _mainwindow->printMessage(Common::Message::Normal,"PCLRadiusOutlierRemovalAlg"); // 获取vtdataset QStringList qCompontIds = QString(componentIds).split(','); MeshData::MeshSet* meshSet = NULL; MeshData::MeshKernal* meshKernal = NULL; MeshData::MeshData* meshData = MeshData::MeshData::getInstance(); QString kernalName, transformedName, setType, ids; // 筛选其中的点云数据 // 创建 vtkCellDataToPointData 过滤器 vtkSmartPointer cellToPointFilter = vtkSmartPointer::New(); QString outfilename; for(QString compontId : qCompontIds) { meshSet = meshData->getMeshSetByID(compontId.toInt()); DebugInfo("point count %d : %d ",compontId.toInt(),meshSet==nullptr); if(!meshSet) continue; outfilename=meshSet->getName(); vtkPolyData* temppolyData=PointCloudOperator::PointCloudCommon::meshSetToVtkDataset(meshSet); cellToPointFilter->SetInputData(temppolyData); DebugInfo("point count %d : %d ",compontId.toInt(),temppolyData==nullptr); } // 执行过滤操作 cellToPointFilter->Update(); DebugInfo("cellToPointFilter "); // 获取过滤后的 vtkPolyData vtkPolyData* outpolyData = cellToPointFilter->GetOutput(); DebugInfo("outpolyData "); pcl::PointCloud::Ptr cloud_with_rgba(new pcl::PointCloud); pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud); pcl::io::vtkPolyDataToPointCloud(outpolyData,*cloud_with_rgba); // 创建滤波器对象 pcl::RadiusOutlierRemoval sor; sor.setInputCloud(cloud_with_rgba); //设置待滤波的点云 sor.setRadiusSearch(RadiusSearch); //设置在进行统计时考虑查询点邻居点数,K个最近邻点 sor.setMinNeighborsInRadius(MinNeighborsInRadius); //设置判断是否为离群点的阈值 sor.filter(*cloud_filtered); //将滤波结果保存在cloud_filtered中 // 转换处理结果 vtkPolyData* polydata=nullptr; polydata=vtkPolyData::New(); // 创建新的指针,智能指针会释放 pcl::io::pointCloudTovtkPolyData(*cloud_filtered,polydata); vtkDataSet* dataset= vtkDataSet::SafeDownCast(polydata); // 默认完成 vtkpolydata --> vtkdataset size_t pointCount = dataset->GetNumberOfPoints(); if(pointCount==0){ return nullptr; } emit _mainwindow->printMessage(Common::Message::Normal,"PCLRadiusOutlierRemovalAlg successfully!! Point Count : "+QString::number(pointCount)); outpolyData->Delete(); // 释放指针 QString filepath=_fileName; // 加载文件 QFileInfo info(filepath); QString name = info.fileName(); QString path = info.filePath(); QString suffix = info.suffix().toLower(); QTextCodec *codec = QTextCodec::codecForName("GB18030"); QByteArray ba = codec->fromUnicode(filepath); std::string outFileName=ba.data(); if (suffix == "pcd") { pcl::io::savePCDFileBinary(outFileName,*cloud_filtered); } else if (suffix == "ply") { pcl::io::savePLYFileBinary(outFileName,*cloud_filtered); } else{} return dataset; } vtkDataSet* PCLRadiusOutlierRemoval::filter() { return PCLRadiusOutlierRemovalAlg( _componentIds, _RadiusSearch,_MinNeighborsInRadius); } PCLRadiusOutlierRemoval::~PCLRadiusOutlierRemoval() {} }