目标:以PCL中欧式聚类为例,通过触发主界面的“segmentation”->“EuclideanClustering”
然后调用出参数设置界面,最终将结果可视化到显示窗口中。
具体步骤如下:
1.新建.ui:右击“Form Files”->“添加”->“类”->“Qt5GuiClass”。
class name命名为qeuclideancluster,然后就会生成相应的.ui,.h,.cpp文件。
2.构建ui界面及对象名称修改
我这里设置了这样一个简单的参数设定界面
3.设置信号与槽函数声明
在.h中添加:
typedef struct
{
double clusterTolerance;
int minSize;
int maxSize;
}euclideancluster_data;
signals:
void SendEuclideanClusterData(euclideancluster_data);//用来传递数据的信号
private slots:
void EuclideanClusterPressed_ok();//button_ok
void EuclideanClusterPressed_cancel();
4.在参数设置界面:连接信号与槽,及槽函数定义(在窗口设置界面)
4.1 连接信号与槽:
qeuclideancluster::qeuclideancluster(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect(ui.pushButton_euclideancluster_ok, SIGNAL(clicked()), this, SLOT(EuclideanClusterPressed_ok()));
connect(ui.pushButton_euclideancluster_cancel, SIGNAL(clicked()), this, SLOT(EuclideanClusterPressed_cancel()));
}
4.2 槽函数定义
void qeuclideancluster::EuclideanClusterPressed_ok()
{
euclideancluster_data tmp_data;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//创建欧式聚类对象
tmp_data.clusterTolerance = ui.lineEdit_ClusterTolerance->text().toDouble();
tmp_data.minSize = ui.lineEdit_ClusterMinsize->text().toInt();
tmp_data.maxSize = ui.lineEdit_ClusterMaxsize->text().toInt();
emit SendEuclideanClusterData(tmp_data);
}
void qeuclideancluster::EuclideanClusterPressed_cancel()
{
this->hide();
}
5:在主界面:信号与槽函数声明与定义
5.1 在.h中声明信号与槽函数
void ReceiveEuclideanclusterData(euclideancluster_data param);
void euclideancluster();
qeuclideancluster* euclidean;
5.2 在.cpp中连接信号与槽
connect(ui.actionEuclideanClustring, SIGNAL(triggered()), this, SLOT(euclideancluster()))
5.3 在.cpp中定义信号与槽
void PCLlab_1::ReceiveEuclideanclusterData(euclideancluster_data param)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr add_cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance(param.clusterTolerance);
ec.setMinClusterSize(param.minSize);
ec.setMaxClusterSize(param.maxSize);
ec.setSearchMethod(tree);
ec.setInputCloud(cloud);
ec.extract(cluster_indices);
//迭代访问点云索引cluster_indices,直至分割出所有聚类
typedef std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> cloudptrlist;//定义一个向量,用于存放各个聚类的指针
cloudptrlist ptrlist;
int j = 0;//定义变量j用于存储点云聚类名称
for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); it++)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);//存放点云聚类
for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
{
cloud_cluster->points.push_back(cloud->points[*pit]);//将当前点云聚类中的点云索引存放到cloud_cluster中
}
cloud_cluster->width = cloud_cluster->points.size();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
//保存点云文件
std::stringstream ss;
ss << "cloud_cluster_D" << j << ".pcd";//保存每一个聚类
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ>(ss.str(), *cloud_cluster, false);
ptrlist.push_back(cloud_cluster);//关键的一句,所有的点云聚类都放到数组向量中去
j++;
}
//随机上色,注意区分点云的ID
for (int i = 0; i < ptrlist.size(); i++)
{
double r = 256 * rand() / (RAND_MAX + 1.0f);
double g = 256 * rand() / (RAND_MAX + 1.0f);
double b = 256 * rand() / (RAND_MAX + 1.0f);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> ::Ptr handler_tempt(new pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(r, g, b));
handler_tempt->setInputCloud(ptrlist[i]);//输入点云
std::ostringstream oss;
oss << i;//不同的点云,赋予不同的ID
viewer->addPointCloud(ptrlist[i], *handler_tempt, "cluster" + oss.str());
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cluster" + oss.str());
}
viewer->resetCamera();
ui.qvtkWidget->update();
}
void PCLlab_1::euclideancluster()
{
euclidean = new qeuclideancluster;
connect(euclidean , SIGNAL(SendEuclideanClusterData(euclideancluster_data)), this, SLOT(ReceiveEuclideanclusterData(euclideancluster_data)));
euclidean->show();
}
6:功能展示