在 PCL 中,获取点云聚类的包络尺寸(即聚类的边界框尺寸)可以通过以下步骤实现:
1. 对点云进行聚类:使用聚类算法(如欧几里得聚类)将点云分割成多个聚类。
2. 计算每个聚类的边界框:对每个聚类,计算其轴对齐边界框(AABB)或旋转边界框(OBB),并获取其尺寸。
以下是完整的代码示例,展示如何获取聚类的包络尺寸:
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <pcl/visualization/pcl_visualizer.h>
int main(int argc, char** argv)
{
// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("input_cloud.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read file input_cloud.pcd \n");
return -1;
}
// 创建 KD 树用于聚类
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(0.02); // 设置聚类距离阈值
ec.setMinClusterSize(100); // 设置最小聚类点数
ec.setMaxClusterSize(25000); // 设置最大聚类点数
ec.setSearchMethod(tree);
ec.setInputCloud(cloud);
ec.extract(cluster_indices); // 执行聚类
// 可视化对象
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Cluster Viewer"));
viewer->setBackgroundColor(0, 0, 0);
// 遍历每个聚类
int cluster_id = 0;
for (const auto& indices : cluster_indices)
{
// 提取当前聚类的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cluster_cloud(new pcl::PointCloud<pcl::PointXYZ>);
for (const auto& index : indices.indices)
{
cluster_cloud->points.push_back(cloud->points[index]);
}
cluster_cloud->width = cluster_cloud->points.size();
cluster_cloud->height = 1;
cluster_cloud->is_dense = true;
// 计算聚类的惯性矩和边界框
pcl::MomentOfInertiaEstimation<pcl::PointXYZ> feature_extractor;
feature_extractor.setInputCloud(cluster_cloud);
feature_extractor.compute();
pcl::PointXYZ min_point, max_point;
feature_extractor.getAABB(min_point, max_point); // 获取轴对齐边界框
// 计算包络尺寸
float width = max_point.x - min_point.x;
float height = max_point.y - min_point.y;
float depth = max_point.z - min_point.z;
std::cout << "Cluster " << cluster_id << " size (W x H x D): "
<< width << " x " << height << " x " << depth << std::endl;
// 可视化聚类和边界框
std::string cluster_name = "cluster_" + std::to_string(cluster_id);
viewer->addPointCloud<pcl::PointXYZ>(cluster_cloud, cluster_name);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,
1.0 - (float)cluster_id / cluster_indices.size(),
0.0,
(float)cluster_id / cluster_indices.size(),
cluster_name);
std::string cube_name = "cube_" + std::to_string(cluster_id);
viewer->addCube(min_point.x, max_point.x, min_point.y, max_point.y, min_point.z, max_point.z,
1.0, 1.0, 0.0, cube_name);
viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION,
pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME,
cube_name);
cluster_id++;
}
// 主循环
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
}
return 0;
}
代码说明
1. 加载点云数据
- 使用 pcl::io::loadPCDFile加载点云文件。
2. 欧几里得聚类:
- 使用 pcl::EuclideanClusterExtraction 对点云进行聚类。
- 设置聚类参数:距离阈值、最小和最大聚类点数。
3. 计算聚类的边界框:
- 对每个聚类,使用 pcl::MomentOfInertiaEstimation计算其轴对齐边界框(AABB)。
- 通过 getAABB()获取边界框的最小点和最大点。
4. 计算包络尺寸:
- 根据边界框的最小点和最大点,计算聚类的宽度、高度和深度。
5. 可视化:
- 使用 pcl::visualization::PCLVisualizer可视化聚类和边界框。
如果需要计算旋转边界框(OBB),可以使用 pcl::MomentOfInertiaEstimation 的 getOBB() 方法,并获取 OBB 的尺寸和方向。