欧式聚类
PCL专栏目录及须知
1.原理
条件聚类是欧式聚类的拓展,除了欧式聚类的距离阈值以外,还添加了条件阈值。通过本类,可自定义距离约束以外的条件约束,然后重写比较方法,进行条件比较。
(1)进行欧式聚类(基于距离)。
(2)对聚类出的结果再进行条件聚类(基于用户设定的条件属性)。
以RGB颜色条件欧式聚类为例:
1)首先对如上点云,进行欧式聚类(基于距离)分割点云,得到欧式聚类之后的结果点。即下图的树1,树2,树3。
2)再对欧式聚类之后的结果点,进行依照RGB条件判断的聚类。得到最终结果(不同颜色即为不同的聚类簇)。不是既符合欧式聚类且符合条件聚类的点云点将被抛弃。
2.使用场景
条件欧式聚类使用场景较多,因为实际计算中往往不只是欧式聚类,对于欧式聚类之后的结果还要进行适用当前场景的再度分割。因此需要用到条件欧式聚类。
3.关键函数
(1)通过比较方法进行条件比较
1)重写比较方法
float threshold = 0.0;
bool conditionFunction(const pcl::PointXYZRGB& point_a, const pcl::PointXYZRGB& point_b, float a)
{
if (point_a.r - point_b.r < threshold && point_a.g - point_b.g < threshold && point_a.b - point_b.b < threshold)
return true;
else
return false;
}
2)调用比较
segmentation.setConditionFunction(&conditionFunction);
(2)其余同欧式聚类中的关键函数
4.完整代码
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
float threshold = 0.0;
bool conditionFunction(const pcl::PointXYZRGB& point_a, const pcl::PointXYZRGB& point_b, float a)
{
if (point_a.r - point_b.r < threshold && point_a.g - point_b.g < threshold && point_a.b - point_b.b < threshold)
return true;
else
return false;
}
int main()
{
/****************条件欧式聚类(以Rgb为例)********************/
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 源点云
pcl::io::loadPCDFile("D:/code/csdn/data/many_tree.pcd", *cloud);
// 条件聚类
threshold = 10.0; // 条件聚类阈值
pcl::ConditionalEuclideanClustering<pcl::PointXYZRGB> segmentation(true); // 设置为true,即提取太大或者太小的聚类点
segmentation.setInputCloud(cloud);
segmentation.setConditionFunction(&conditionFunction); // 设置条件判断函数(可类比lambda定理)
segmentation.setClusterTolerance(1.3); // 设置欧式聚类阈值
segmentation.setMinClusterSize(50); // 设置最大聚类数目
segmentation.setMaxClusterSize(10000); // 设置最小聚类数目
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>); // 设置搜索树
tree->setInputCloud(cloud);
segmentation.setSearchMethod(tree);
std::vector<pcl::PointIndices> clusterIndices; // 聚类结果
segmentation.segment(clusterIndices);
// 提取聚类后点云
std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> clustreClouds;
for (size_t i = 0; i < clusterIndices.size(); i++)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTemp(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud, clusterIndices[i], *cloudTemp);
clustreClouds.push_back(cloudTemp);
}
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("EuclideanClusterExtraction"));
for (size_t i = 0; i < clustreClouds.size(); i++)
{
pcl::RGB rgb = pcl::getRandomColor(0, 255);
viewer->addPointCloud<pcl::PointXYZ>(clustreClouds.at(i), pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(clustreClouds.at(i), rgb.r, rgb.g, rgb.b), "clustreClouds" + i);
}
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
5.结果展示
原始数据
可视化结果