Qt PCL学习(三):点云滤波

注意事项

  • 版本一览:Qt 5.15.2 + PCL 1.12.1 + VTK 9.1.0
  • 前置内容:Qt PCL学习(一):环境搭建、Qt PCL学习(二):点云读取与保存

0. 效果演示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1. pcl_open_save.pro

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgets// 添加下行代码(根据自己安装目录进行修改)
include(D:/PCL1.12.1/pcl1.12.1.pri)

2. mainwindow.h

#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")
#endiftypedef 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_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic: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

3. mainwindow.cpp

#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);// 设置窗口标题和 logothis->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.reset(new pcl::visualization::PCLVisualizer("viewer", false));vtkNew<vtkGenericOpenGLRenderWindow> window;window->AddRenderer(cloud_viewer->getRendererCollection()->GetFirstRenderer());ui->openGLWidget->setRenderWindow(window.Get());cloud_viewer->removeAllPointClouds();cloud_viewer->removeAllShapes();for (int i = 0; i<vector_cloud.size(); i++) {if (index[i] == 1) {pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ>render(vector_cloud[i], "intensity");cloud_viewer->addPointCloud<pcl::PointXYZ>(vector_cloud[i], render, 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)return;if (item->isCheckable()) {//判断状态Qt::CheckState state = item->checkState();  // 获取当前的选择状态if (Qt::Checked == state) {cloud_index[index.row()] = 1;}if (Qt::Unchecked == state) {cloud_index[index.row()] = 0;}view_updata(cloud_vec, cloud_index);}
}

4. voxel_filtering.h

#ifndef VOXEL_FILTERING_H
#define VOXEL_FILTERING_H#include <QDialog>
#include <QString>namespace Ui {
class voxel_filtering;
}class voxel_filtering : public QDialog {Q_OBJECTsignals: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

5. voxel_filtering.cpp

#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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2777706.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Linux应用程序参数传递的深入探索

大家好&#xff0c;今天给大家介绍Linux应用程序参数传递的深入探索&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在Linux环境中&#xff0c;应用程序的参数传递是一个核心且灵…

【Linux】模块参数

&#x1f525;博客主页&#xff1a;PannLZ &#x1f38b;系列专栏&#xff1a;《Linux系统之路》 &#x1f94a;不要让自己再留有遗憾&#xff0c;加油吧&#xff01; 模块参数 像用户程序一样&#xff0c;内核模块也可以接受命令行参数。首先应该声明用于保存命令行参数值的变…

XSS-Lab

1.关于20关的payload合集。 <script>alert(1)</script> "><script>alert(1)</script> onclickalert(1) " onclick"alert(1) "><a href"javascript:alert(1)"> "><a HrEf"javascript:alert…

sklearn中一些简单机器学习算法的使用

目录 前言 KNN算法 决策树算法 朴素贝叶斯算法 岭回归算法 线性优化算法 前言 本篇文章会介绍一些sklearn库中简单的机器学习算法如何使用&#xff0c;一些注释已经写在代码中&#xff0c;帮助一些小伙伴入门sklearn库的使用。 注意&#xff1a;本篇文章只涉及到如何使用…

Java实现快乐贩卖馆管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 搞笑视频模块2.3 视频收藏模块2.4 视频评分模块2.5 视频交易模块2.6 视频好友模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 搞笑视频表3.2.2 视频收藏表3.2.3 视频评分表3.2.4 视频交易表 四、系…

【iOS】——使用ZXingObjC库实现条形码识别并请求信息

文章目录 前言一、实现步骤二、扫描界面和扫描框的样式1.扫描界面2.扫描框 三、实现步骤 前言 ZXing库是一个专门用来解析多种二维码和条形码&#xff08;包括包括 QR Code、Aztec Code、UPC、EAN、Code 39、Code 128等&#xff09;的开源性质的处理库&#xff0c;而ZingObjC库…

蓝桥杯刷题day08——完全日期

1、题目描述 如果一个日期中年月日的各位数字之和是完全平方数&#xff0c;则称为一个完全日期。 例如&#xff1a;2021年6月5日的各位数字之和为20216516&#xff0c;而16是一个完全平方数&#xff0c;它是4的平方。所以2021年6月5日是一个完全日期。 请问&#xff0c;从200…

怎么加密电脑磁盘?磁盘加密软件哪个好?

磁盘是电脑储存数据的基础工具&#xff0c;可以存放大量数据。为了避免数据泄露&#xff0c;可以使用专业的磁盘加密软件加密保护电脑磁盘。那么&#xff0c;磁盘加密软件哪个好呢&#xff1f;下面我们就来了解一下。 磁盘加锁专家 磁盘加锁专家是一款专业的磁盘加锁软件&…

社区店选址要素揭秘:人流量与商业潜力的关键

开店五年&#xff0c;我深刻体会到选址对于社区店的重要性。 不管是哪个行业的实体店&#xff0c;选址更是决定成败的关键因素之一。今天&#xff0c;我就以一名资深鲜奶吧创业者的身份&#xff0c;来揭秘社区店选址的几大要素&#xff0c;帮助大家在创业的道路上少走弯路。 …

C#使用哈希表对XML文件进行查询

目录 一、使用的方法 1.Hashtable哈希表 2.Hashtable哈希表的Add方法 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;示例 3.XML文件的使用 二、实例 1.源码 2.生成效果 可以通过使用哈希表可以对XML文件进行查询。 一、使用的方法 1.Hashtable哈希表…

spring上下文源码分析

请直接看原文: 原文链接: 一文搞懂Spring上下文生命周期 | spring系列第55篇-腾讯云开发者社区-腾讯云 (tencent.com) -------------------------------------------------------------------------------------------------------------------------------- 本文主要内容&a…

linux应用 进程间通信之信号量(System V)

1、定义 System V 信号量是一种用于进程间同步和互斥的机制&#xff0c;它是 System V IPC&#xff08;Inter-Process Communication&#xff0c;进程间通信&#xff09;机制的一部分。信号量通常用于控制对共享资源的访问&#xff0c;以避免竞争条件&#xff08;race conditi…

2024年【N1叉车司机】新版试题及N1叉车司机模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N1叉车司机新版试题参考答案及N1叉车司机考试试题解析是安全生产模拟考试一点通题库老师及N1叉车司机操作证已考过的学员汇总&#xff0c;相对有效帮助N1叉车司机模拟考试题库学员顺利通过考试。 1、【多选题】《中华…

计算机服务器中了mkp勒索病毒如何解密,mkp勒索病毒解密流程

随着网络技术的不断发展与应用&#xff0c;越来越多的企业走向数字化办公模式&#xff0c;计算机极大地方便了企业的正常生产运营&#xff0c;但网络威胁的手段也不断增加。近期&#xff0c;云天数据恢复接到很多企业的求助&#xff0c;企业的计算机服务器遭到了mkp勒索病毒攻击…

重学JavaScript高级(十二):async/await-事件循环-面试高频

async/await-事件循环 前面我们学习了生成器和迭代器&#xff0c;那么在本篇文章中&#xff0c;我们主要讲解生成器与Promise的结合使用&#xff0c;从而引出async/await语法&#xff0c;同时会涉及面试中频次最高的一个知识点&#xff1a;事件循环 生成器与异步处理 首先需要…

【分布式技术专题】「Zookeeper中间件」Paxos协议的原理和实际运行中的应用流程分析

Paxo算法介绍 Paxos算法是莱斯利兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法。 Paxos产生背景 Paxos算法是基于消息传递且具有高度容错特性的一致性算法&#xff0c;是目前公认的解决分布式一致性问题最有效的算法之一&#xff0c;其解决的问题就是在分…

SQL拆分字段内容(含分隔符)

问题描述&#xff1a; 在做数据迁移的过程中&#xff0c;我们希望对表中的某个字段根据分隔符进行拆分&#xff0c;得到多条数据&#xff0c;原代码有点意思&#xff0c;因此记录一下。 我们假设某条数据如下&#xff1a; IDSTRS1公司名称不能小于四个字&#xff0c;行业类别…

SSM框架,Spring-ioc的学习(上)

知识点引入 关于框架 框架( Framework )是一个集成了基本结构、规范、设计模式、编程语言和程序库等基础组件的软件系统&#xff0c;它可以用来构建更高级别的应用程序。框架的设计和实现旨在解决特定领域中的常见问题&#xff0c;帮助开发人员更高效、更稳定地实现软件开发目…

python-pandas查漏补缺

1. create labels for Series 2. 3. 4. 用平均数等去填empty的格子 5. 6. 7.

SPSS双变量相关分析

双变量相关分析通过计算皮尔逊简单相关系数、斯皮尔曼等级相关系数、肯德尔等级相关系数及其显著性水平展开。其中皮尔逊简单相关系数是一种线性关联度量&#xff0c;适用于变量为定量连续变量且服从正态分布、相关关系为线性时的情形。如果变量不是正态分布的&#xff0c;或具…