本節是繼《點雲庫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);
}