赞
踩
注意事项
- 版本一览:Qt 5.15.2 + PCL 1.12.1 + VTK 9.1.0
- 前置内容:Qt PCL学习(一):环境搭建、Qt PCL学习(二):点云读取与保存、PCL学习六:Filtering-滤波
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
// 添加下行代码(根据自己安装目录进行修改)
include(D:/PCL1.12.1/pcl1.12.1.pri)
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <voxel_filtering.h> #include <vector> #include <QMainWindow> #include <QDebug> #include <QColorDialog> #include <QMessageBox> #include <QFileDialog> #include <QTime> #include <QDir> #include <QFile> #include <QtMath> #include <QWindow> #include <QAction> #include <QHBoxLayout> #include <QVBoxLayout> #include <QIcon> #include <QMenuBar> #include <QMenu> #include <QToolBar> #include <QStatusBar> #include <QFont> #include <QString> #include <QTextBrowser> #include <QDirIterator> #include <QStandardItemModel> #include <QModelIndex> #include "QVTKOpenGLNativeWidget.h" #include <vtkSphereSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkGenericOpenGLRenderWindow.h> #include <vtkNamedColors.h> #include <vtkProperty.h> #include <vtkSmartPointer.h> #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2); VTK_MODULE_INIT(vtkRenderingFreeType); #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/io/ply_io.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/filters/voxel_grid.h> #ifndef TREE_ITEM_ICON_DataItem #define TREE_ITEM_ICON_DataItem QStringLiteral("treeItem_folder") #endif typedef pcl::PointXYZ PointT; typedef pcl::PointCloud<PointT> PointCloudT; typedef pcl::visualization::PCLVisualizer PCLViewer; typedef std::shared_ptr<PointCloudT> PointCloudPtr; QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); PointCloudT::Ptr pcl_voxel_filter(PointCloudT::Ptr cloud_in, float leaf_size); void view_updata(std::vector<PointCloudT::Ptr> vector_cloud, std::vector<int> index); private slots: void open_clicked(); // 打开文件 void save_clicked(); // 保存文件 void on_treeView_clicked(const QModelIndex &index); // 点云滤波 void pressBtn_voxel(); void voxel_clicked(QString data); private: Ui::MainWindow *ui; QMap<QString, QIcon> m_publicIconMap; // 存放公共图标 QStandardItemModel* model; QStandardItem* itemFolder; QModelIndex index_cloud; std::vector<PointCloudT::Ptr> cloud_vec; std::vector<int> cloud_index; // 点云名称 std::vector<std::string> cloud_name{"0", "1", "2"}; int point_size = 1; PointCloudPtr cloudptr; PCLViewer::Ptr cloud_viewer; voxel_filtering *dialog_voxel; }; #endif // MAINWINDOW_H
#pragma execution_character_set("utf-8") #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 设置窗口标题和 logo this->setWindowTitle("CloudOne"); this->setWindowIcon(QIcon(":/resourse/icon.ico")); m_publicIconMap[TREE_ITEM_ICON_DataItem] = QIcon(QStringLiteral(":/resourse/folder.png")); model = new QStandardItemModel(ui->treeView); model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("--cloud--DB-Tree--")); ui->treeView->setHeaderHidden(true); ui->treeView->setModel(model); ui->treeView->setSelectionMode(QAbstractItemView::ExtendedSelection); // 设置多选 cloudptr.reset(new PointCloudT); cloud_viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false)); vtkNew<vtkGenericOpenGLRenderWindow> window; window->AddRenderer(cloud_viewer->getRendererCollection()->GetFirstRenderer()); ui->openGLWidget->setRenderWindow(window.Get()); cloud_viewer->setupInteractor(ui->openGLWidget->interactor(), ui->openGLWidget->renderWindow()); ui->openGLWidget->update(); // 创建菜单栏 QMenuBar *menu_bar = new QMenuBar(this); this->setMenuBar(menu_bar); menu_bar->setStyleSheet("font-size : 16px"); // 1、File 下拉列表 QMenu *file_menu = new QMenu("File", menu_bar); QAction *open_action = new QAction("Open File"); QAction *save_action = new QAction("Save File"); QAction *exit_action = new QAction("Exit"); // 添加动作到文件菜单 file_menu->addAction(open_action); file_menu->addAction(save_action); file_menu->addSeparator(); // 添加菜单分隔符将 exit 单独隔离开 file_menu->addAction(exit_action); // 把 File 添加到菜单栏 menu_bar->addMenu(file_menu); // 2、Filter 下拉列表 QMenu *filter_menu = new QMenu("Filter", menu_bar); QAction *voxel_action = new QAction("Voxel Filtering"); filter_menu->addAction(voxel_action); menu_bar->addMenu(filter_menu); // 信号与槽函数链接 connect(open_action, SIGNAL(triggered()), this, SLOT(open_clicked())); // 打开文件 connect(save_action, SIGNAL(triggered()), this, SLOT(save_clicked())); // 保存文件 connect(exit_action, SIGNAL(triggered()), this, SLOT(close())); // 退出 connect(voxel_action, SIGNAL(triggered()), this, SLOT(pressBtn_voxel())); } MainWindow::~MainWindow() { delete ui; } PointCloudT::Ptr MainWindow::pcl_voxel_filter(PointCloudT::Ptr cloud_in, float leaf_size) { pcl::VoxelGrid<PointT> voxel_grid; voxel_grid.setLeafSize(leaf_size, leaf_size, leaf_size); voxel_grid.setInputCloud(cloud_in); PointCloudT::Ptr cloud_out (new PointCloudT()) ; voxel_grid.filter(*cloud_out); return cloud_out; } void MainWindow::pressBtn_voxel() { dialog_voxel = new voxel_filtering(); connect(dialog_voxel, SIGNAL(sendData(QString)), this, SLOT(voxel_clicked(QString))); if (dialog_voxel->exec() == QDialog::Accepted){} delete dialog_voxel; } // 体素采样 void MainWindow::voxel_clicked(QString data) { if (cloudptr->empty()) { QMessageBox::warning(this, "Warning", "None point cloud!"); return; } else { if (data.isEmpty()) { QMessageBox::warning(this, "Warning", "Wrong format!"); return; } float size = data.toFloat(); auto cloud_out = pcl_voxel_filter(cloudptr, size); cloudptr = cloud_out; int size1 = static_cast<int>(cloudptr->size()); QString PointSize = QString("%1").arg(size1); ui->textBrowser_2->clear(); ui->textBrowser_2->insertPlainText("PCD number: " + PointSize); ui->textBrowser_2->setFont(QFont("Arial", 9, QFont::Normal)); cloud_viewer->removeAllPointClouds(); cloud_viewer->removeAllShapes(); cloud_viewer->addPointCloud<pcl::PointXYZ>(cloudptr->makeShared(), std::to_string(cloud_vec.size()-1)); cloud_viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, std::to_string(cloud_vec.size()-1)); cloud_viewer->resetCamera(); // 设置颜色处理器,将点云数据添加到 cloud_viewer 中 const std::string axis = "z"; pcl::visualization::PointCloudColorHandlerGenericField<PointT> color_handler(cloudptr, axis); cloud_viewer->addPointCloud(cloudptr, color_handler, "cloud"); cloud_viewer->addPointCloud(cloudptr, "cloud"); } } void MainWindow::open_clicked() { // this:代表当前对话框的父对象;tr("open file"):作为对话框的标题显示在标题栏中,使用 tr 函数表示这是一个需要翻译的文本 // "":代表对话框的初始目录,这里为空表示没有指定初始目录 // tr("pcb files(*.pcd *.ply *.txt) ;;All files (*.*)"):过滤器,决定在对话框中只能选择指定类型的文件 QString fileName = QFileDialog::getOpenFileName(this, tr("open file"), "", tr("point cloud files(*.pcd *.ply) ;; All files (*.*)")); if (fileName.isEmpty()) { return; } if (fileName.endsWith("ply")) { qDebug() << fileName; if (pcl::io::loadPLYFile(fileName.toStdString(), *cloudptr) == -1) { qDebug() << "Couldn't read .ply file \n"; return ; } } else if (fileName.endsWith("pcd")) { qDebug() << fileName; if (pcl::io::loadPCDFile(fileName.toStdString(), *cloudptr) == -1) { qDebug() << "Couldn't read .pcd file \n"; return; } } else { QMessageBox::warning(this, "Warning", "Wrong format!"); } cloud_vec.push_back(cloudptr->makeShared()); cloud_index.push_back(1); itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")], QStringLiteral("cloud%1").arg(cloud_vec.size()-1)); itemFolder->setCheckable(true); itemFolder->setCheckState(Qt::Checked); // 获取选中状态 model->appendRow(itemFolder); int size = static_cast<int>(cloudptr->size()); QString PointSize = QString("%1").arg(size); ui->textBrowser_2->clear(); ui->textBrowser_2->insertPlainText("PCD number: " + PointSize); ui->textBrowser_2->setFont(QFont("Arial", 9, QFont::Normal)); cloud_viewer->addPointCloud<pcl::PointXYZ>(cloudptr->makeShared(), std::to_string(cloud_vec.size()-1)); // 设置点云大小 cloud_viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, std::to_string(cloud_vec.size()-1)); cloud_viewer->resetCamera(); ui->openGLWidget->renderWindow()->Render(); ui->openGLWidget->update(); // 设置颜色处理器,将点云数据添加到 cloud_viewer 中 const std::string axis = "z"; pcl::visualization::PointCloudColorHandlerGenericField<PointT> color_handler(cloudptr, axis); cloud_viewer->addPointCloud(cloudptr, color_handler, "cloud"); cloud_viewer->addPointCloud(cloudptr, "cloud"); } void MainWindow::save_clicked() { int return_status; QString filename = QFileDialog::getSaveFileName(this, tr("Open point cloud"), "", tr("Point cloud data (*.pcd *.ply)")); if (cloudptr->empty()) { return; } else { if (filename.isEmpty()) { return; } if (filename.endsWith(".pcd", Qt::CaseInsensitive)) { return_status = pcl::io::savePCDFileBinary(filename.toStdString(), *cloudptr); } else if (filename.endsWith(".ply", Qt::CaseInsensitive)) { return_status = pcl::io::savePLYFileBinary(filename.toStdString(), *cloudptr); } else { filename.append(".ply"); return_status = pcl::io::savePLYFileBinary(filename.toStdString(), *cloudptr); } if (return_status != 0) { PCL_ERROR("Error writing point cloud %s\n", filename.toStdString().c_str()); return; } } } void MainWindow::view_updata(std::vector<PointCloudT::Ptr> vector_cloud, std::vector<int> index) { cloud_viewer->removeAllPointClouds(); cloud_viewer->removeAllShapes(); for (size_t i = 0; i < vector_cloud.size(); ++i) { if (index[i] == 1) { pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> color_handler(vector_cloud[i], "z"); cloud_viewer->addPointCloud(vector_cloud[i], color_handler, std::to_string(i)); cloud_viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size, std::to_string(i)); } } cloud_viewer->resetCamera(); ui->openGLWidget->update(); } // 确定 index void MainWindow::on_treeView_clicked(const QModelIndex &index) { QStandardItem* item = model->itemFromIndex(index); // 点云数量更改 QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeView->model()); QModelIndex index_temp = ui->treeView->currentIndex(); int size = static_cast<int>(cloud_vec[index_temp.row()]->size()); QString PointSize = QString("%1").arg(size); ui->textBrowser_2->clear(); ui->textBrowser_2->insertPlainText("Point cloud number: " + PointSize); ui->textBrowser_2->setFont(QFont("Arial", 9, QFont::Normal)); // 可视化更改 if (item == nullptr || !item->isCheckable()) { return; } Qt::CheckState state = item->checkState(); int cloudIndex = index.row(); if (state == Qt::Checked) { cloud_index[cloudIndex] = 1; } else { cloud_index[cloudIndex] = 0; } view_updata(cloud_vec, cloud_index); }
#ifndef VOXEL_FILTERING_H #define VOXEL_FILTERING_H #include <QDialog> #include <QString> namespace Ui { class voxel_filtering; } class voxel_filtering : public QDialog { Q_OBJECT signals: void sendData(QString data); public: explicit voxel_filtering(QWidget *parent = nullptr); ~voxel_filtering(); private slots: void on_buttonBox_accepted(); private: Ui::voxel_filtering *ui; }; #endif // VOXEL_FILTERING_H
#include "voxel_filtering.h" #include "ui_voxel_filtering.h" voxel_filtering::voxel_filtering(QWidget *parent) : QDialog(parent), ui(new Ui::voxel_filtering) { ui->setupUi(this); } voxel_filtering::~voxel_filtering() { delete ui; } void voxel_filtering::on_buttonBox_accepted() { emit sendData(ui->lineEdit->text()); this->close(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。