LAMPCAE/src/PluginWBFZExchangePlugin/DialogPCLRadiusOutlierRemov...

296 lines
9.6 KiB
C++
Raw Normal View History

/**
* @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 <QMenu>
#include <QDebug>
#include <pcl/filters/convolution_3d.h>
#include <QFileDialog>
#include <QFileInfo>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/radius_outlier_removal.h>
#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<MeshData::MeshSet *>)), this, SLOT(selectedComponentsSlot(QList<MeshData::MeshSet *>)));
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<MeshData::MeshSet *> 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<vtkGeometryFilter> cellToPointFilter = vtkSmartPointer<vtkGeometryFilter>::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<pcl::PointXYZRGBA>::Ptr cloud_with_rgba(new pcl::PointCloud<pcl::PointXYZRGBA>);
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGBA>);
pcl::io::vtkPolyDataToPointCloud(outpolyData,*cloud_with_rgba);
// 创建滤波器对象
pcl::RadiusOutlierRemoval<pcl::PointXYZRGBA> 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() {}
}