296 lines
9.6 KiB
C++
296 lines
9.6 KiB
C++
/**
|
||
* @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() {}
|
||
|
||
} |