本节是继《点云库PCL学习——QT5.7.0+VS2013+PCL1.8.0环境》章节的应用,将一步步搭建环境实现直通滤波的功能。
最终实现的简单界面如下:
1.在QT的ui界面拉入相应的控件
为了全面实现直通滤波,我拉入了以下控件:
1)现在以"RadioButton"控件为例,如果我要改变对象名称。可以在相应控件,右击,写入相应的标签即可。
2)"pushbutton"控件与其它控件有所区别,因为他要建立起信号与槽之间的通信。因此需要做以下工作:
(1)右击主界面,改变信号/槽
如上图,我有一个“clicked()”信号,触发一个"onPassThrough"的槽函数,所有的实现就在这个函数中实现。
(2)编辑信号/槽。
点击“编辑信号/槽”,右击“OK”往下拉动,会出现“配置连接”窗口。在这里选择clicked(),onPassThrough()。
配置完成后,点击OK,会出现如下:
至此,界面设置完毕。
3)保存设置并生成"ui_xxx.h"文件,最终将生成的ui_xxx.h代替以下位置的ui_***.h文件。
那么该文件怎么生成呢?“窗体”->“查看代码”->“保存”,文件名"ui_xxx.h",
保存替换目录中存在的"ui_xxx.h"。
将VS工程中的.ui_***.h文件删除,然后右击“Generated Files”->"添加”->“现有项”,选择保存后的“ui_xxx.h”,重新编译生成即可。
2.在VS中写入相应代码
2.1 ***.h文件
#ifndef PCLVISUALIZER_H
#define PCLVISUALIZER_H
#include "vtkRenderWindow.h"
#include <QtWidgets/QMainWindow>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/visualization/pcl_visualizer.h>
#include<pcl/visualization/cloud_viewer.h>
#include "ui_pclvisualizer.h"
class PCLVisualizer : public QMainWindow
{
Q_OBJECT
public:
PCLVisualizer(QWidget *parent = 0, Qt::WindowFlags flags = 0);
~PCLVisualizer();
private: //主要用于创建变量、初始化部件、以及创建槽函数
Ui::PCLVisualizerClass ui;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud; //点云数据存储
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer; //
//初始化vtk部件
void initialVtkWidget();
private slots: //运行槽
//创建打开槽 槽函数onopen
void onOpen();
void onPassThrough();
};
#endif // PCLVISUALIZER_H
2.2 ***.cpp文件
#include <QFileDialog>
#include <iostream>
#include "pclvisualizer.h"
PCLVisualizer::PCLVisualizer(QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
//初始化
initialVtkWidget();
//连接信号和槽
connect(ui.actionOpen, SIGNAL(triggered()), this, SLOT(onOpen()));
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(onPassThrough()));
}
PCLVisualizer::~PCLVisualizer()
{
}
void PCLVisualizer::initialVtkWidget() //在pclvusalizer.h定义的成员函数initialVtkWidget
{
cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
viewer->addPointCloud(cloud, "cloud1");
ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());
ui.qvtkWidget->update();
}
//读取文本型和二进制型点云数据
void PCLVisualizer::onOpen() //在pclvisualizer.cpp定义的成员函数onopen
{ //读取*.pcd放进cloud中
//只能打开PCD文件
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open PointCloud"), ".",
tr("Open PCD files(*.pcd)"));
if (!fileName.isEmpty())
{
std::string file_name = fileName.toStdString();
//sensor_msgs::PointCloud2 cloud_1;
pcl::PCLPointCloud2 cloud_1;
Eigen::Vector4f origin;
Eigen::Quaternionf orientation;
int pcd_version;
int data_type;
unsigned int data_idx;
int offset = 0;
pcl::PCDReader rd;
rd.readHeader(file_name, cloud_1, origin, orientation, pcd_version, data_type, data_idx);
if (data_type == 0) //点云数据类型0。
{
pcl::io::loadPCDFile(fileName.toStdString(), *cloud);
}
else if (data_type == 2) //点云数据类型2。
{
pcl::PCDReader reader;
reader.read<pcl::PointXYZ>(fileName.toStdString(), *cloud);
}
viewer->updatePointCloud(cloud, "cloud1");
viewer->resetCamera();
ui.qvtkWidget->update();
}
}
void PCLVisualizer::onPassThrough()
{
bool FilterLimitsNegative;
std::string FilterFiledName;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filterd_1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
if (ui.radioButton_FilterFieldName_X->isChecked())
pass.setFilterFieldName("X");
if (ui.radioButton_FilterFieldName_Y->isChecked())
pass.setFilterFieldName("Y");
if (ui.radioButton_FilterFieldName_Z->isChecked())
pass.setFilterFieldName("Z");
pass.setFilterLimits(ui.lineEdit_FilterLimits_from->text().toFloat(), ui.lineEdit_FilterLimits_to->text().toFloat());
if (ui.radioButton_FilterLimitsNegative->isChecked())
pass.setFilterLimitsNegative(true);
else
pass.setFilterLimitsNegative(false);
}