目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1 点云边界提取
2.1.2 可视化点云与边界
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
平面点云边界特征提取可以帮助识别点云数据中的几何特征,通过提取边界信息,识别出点云的轮廓或边界。Alpha Shapes 是一种边界提取算法,通过调节参数 α,来控制提取的边界形状。本文使用 PCL 的 pcl::ConcaveHull 类实现基于 Alpha Shapes 的点云边界提取,并可视化结果。
1.1原理
Alpha Shapes 算法是一种用于生成点集的边界的几何算法,具有灵活的 α 参数:
- 当 α 较大时,边界较为凸;
- 当 α 较小时,边界较为凹。
边界由多个连接在一起的三角形组成,α 参数决定了哪些点会参与到边界生成中。通过调整 α,可以实现不同层次的边界提取。基本步骤如下:
- 点云输入:从点云中选择点。
- 生成边界:根据 α 参数生成边界形状。
- 可视化边界:对提取出的边界进行可视化展示。
1.2实现步骤
- 加载点云数据;
- 使用 pcl::ConcaveHull 进行边界特征提取;
- 通过调整 α 参数,生成不同的边界形状;
- 可视化点云和边界结果。
1.3应用场景
- 物体识别:通过提取边界点,识别物体的轮廓;
- 表面重建:提取物体边缘,辅助表面重建算法;
- 形状分析:基于点云数据的形状分析,判断物体的几何特征。
二、代码实现
2.1关键函数
2.1.1 点云边界提取
该函数使用 pcl::ConcaveHull 进行点云边界提取,alpha 参数控制边界形状。
void extractBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr boundary, float alpha)
{
// 创建 ConcaveHull 对象
pcl::ConcaveHull<pcl::PointXYZ> concave_hull;
// 设置输入点云
concave_hull.setInputCloud(cloud);
// 设置 alpha 参数(控制边界形状)
concave_hull.setAlpha(alpha);
// 生成边界并存储到 boundary 点云中
concave_hull.reconstruct(*boundary);
}
2.1.2 可视化点云与边界
该函数负责将原始点云和提取的边界点进行可视化展示,原始点云显示为红色,边界点显示为绿色。
void visualizeBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr boundary)
{
// 创建可视化对象
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Boundary Viewer"));
int vp1, vp2;
// 创建视口 1,显示原始点云
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp1);
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp1); // 设置背景为白色
viewer->addText("Original Point Cloud", 10, 10, "vp1_text", vp1);
// 原始点云设置为红色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);
viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp1);
// 创建视口 2,显示边界
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp2);
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp2); // 设置背景为灰色
viewer->addText("Boundary", 10, 10, "vp2_text", vp2);
// 边界点设置为绿色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> boundary_color_handler(boundary, 0, 255, 0);
viewer->addPointCloud(boundary, boundary_color_handler, "boundary_cloud", vp2);
// 开始可视化显示
viewer->spin();
}
2.2完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
// 提取边界点
void extractBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr boundary, float alpha)
{
// 创建 ConcaveHull 对象
pcl::ConcaveHull<pcl::PointXYZ> concave_hull;
// 设置输入点云
concave_hull.setInputCloud(cloud);
// 设置 alpha 参数(控制边界形状)
concave_hull.setAlpha(alpha);
// 生成边界并存储到 boundary 点云中
concave_hull.reconstruct(*boundary);
}
// 可视化点云与边界
void visualizeBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr boundary)
{
// 创建可视化对象
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Boundary Viewer"));
int vp1, vp2;
// 创建视口 1,显示原始点云
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp1);
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp1); // 设置背景为白色
viewer->addText("Original Point Cloud", 10, 10, "vp1_text", vp1);
// 原始点云设置为红色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 255, 0, 0);
viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp1);
// 创建视口 2,显示边界
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp2);
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp2); // 设置背景为灰色
viewer->addText("Boundary", 10, 10, "vp2_text", vp2);
// 边界点设置为绿色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> boundary_color_handler(boundary, 0, 255, 0);
viewer->addPointCloud(boundary, boundary_color_handler, "boundary_cloud", vp2);
// 开始可视化显示
viewer->spin();
}
// 主函数
int main(int argc, char** argv)
{
// 读取点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
pcl::io::loadPCDFile("cloud.pcd", *cloud);
// 创建一个点云用于存储边界
pcl::PointCloud<pcl::PointXYZ>::Ptr boundary(new pcl::PointCloud<pcl::PointXYZ>);
// 提取边界,设定 alpha 为 0.05
float alpha = 0.05f;
extractBoundary(cloud, boundary, alpha);
// 可视化边界
visualizeBoundary(cloud, boundary);
return 0;
}