LAMPCAE/src/PluginWBFZExchangePlugin/DialogPCLRadiusOutlierRemov...

296 lines
9.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @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() {}
}