目录
PCL点云算法汇总及实战案例汇总的目录地址链接:
一、概述
在PCL中,CropHull滤波器是一种用于根据指定的多边形边界,裁剪点云中位于该多边形内的点的工具。该方法可以通过给定任意的多边形,将点云数据根据这些边界进行筛选,提取出符合要求的内部点。
1.1原理
CropHull 过滤的主要步骤是通过多边形(通常为凸包)的几何边界,在三维空间中将点云进行裁剪。其基本原理如下:
- 多边形定义:定义用于裁剪的多边形边界,可以是任意多边形。
- 点云裁剪:将原始点云中位于多边形内部的点提取出来。具体过程是通过判断每个点是否位于多边形边界内,如果是,则保留该点,否则将其剔除。
1.2实现步骤
- 加载原始点云。
- 定义一个多边形(通常为凸包),作为裁剪边界。
- 使用 CropHull 滤波器,提取多边形内部的点云。
- 可视化裁剪前后的点云。
1.3应用场景
- 点云分割:在复杂场景中,使用自定义多边形边界,提取特定区域的点云。
- 点云裁剪:只保留感兴趣的区域,去除不必要的背景或干扰点。
- 场景预处理:在应用机器学习或深度学习算法前,通过裁剪减少不必要的数据量,提升处理效率。
二、代码实现
2.1关键函数
2.1.1 定义多边形边界
我们使用自定义的多边形边界进行裁剪,通常使用 pcl::ConvexHull 来定义边界。
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/convex_hull.h>
// 定义凸包边界并进行裁剪
void applyCropHullFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& cropped_cloud)
{
// 1. 计算点云的凸包,作为多边形边界
pcl::PointCloud<pcl::PointXYZ>::Ptr hull_points(new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConvexHull<pcl::PointXYZ> chull;
chull.setInputCloud(cloud);
chull.reconstruct(*hull_points); // 计算凸包的点云
std::vector<pcl::Vertices> hull_polygons;
chull.reconstruct(*hull_points, hull_polygons); // 获取凸包的多边形顶点索引
// 2. 使用CropHull进行裁剪操作
pcl::CropHull<pcl::PointXYZ> cropHull;
cropHull.setInputCloud(cloud); // 设置输入点云
cropHull.setHullCloud(hull_points); // 设置凸包点云作为裁剪边界
cropHull.setHullIndices(hull_polygons);// 设置凸包的顶点索引
cropHull.setDim(3); // 使用三维空间裁剪
cropHull.filter(*cropped_cloud); // 执行裁剪并存储裁剪后的点云
}
2.1.2 可视化函数
使用 PCLVisualizer 来同时显示原始点云和裁剪后的点云,两个视口分别展示。
#include <pcl/visualization/pcl_visualizer.h>
// 可视化裁剪前和裁剪后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& cropped_cloud)
{
// 创建PCLVisualizer对象
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("CropHull Viewer"));
// 设置第一个视口,显示原始点云
int v1(0), v2(1);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 左侧视口
viewer->setBackgroundColor(1.0, 1.0, 1.0, v1); // 白色背景
viewer->addText("Original Point Cloud", 10, 10, "v1 text", v1); // 添加标题
viewer->addPointCloud(cloud, "original_cloud", v1); // 显示原始点云
// 设置第二个视口,显示裁剪后的点云
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2); // 右侧视口
viewer->setBackgroundColor(0.98, 0.98, 0.98, v2); // 浅灰色背景
viewer->addText("Cropped Point Cloud", 10, 10, "v2 text", v2); // 添加标题
viewer->addPointCloud(cropped_cloud, "cropped_cloud", v2); // 显示裁剪后的点云
viewer->addCoordinateSystem(1.0); // 添加坐标系
// 循环显示直到窗口关闭
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
}
}
2.2完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/visualization/pcl_visualizer.h>
// 定义凸包边界并进行裁剪
void applyCropHullFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& cropped_cloud)
{
// 1. 计算点云的凸包,作为多边形边界
pcl::PointCloud<pcl::PointXYZ>::Ptr hull_points(new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConvexHull<pcl::PointXYZ> chull;
chull.setInputCloud(cloud);
chull.reconstruct(*hull_points); // 计算凸包的点云
std::vector<pcl::Vertices> hull_polygons;
chull.reconstruct(*hull_points, hull_polygons); // 获取凸包的多边形顶点索引
// 2. 使用CropHull进行裁剪操作
pcl::CropHull<pcl::PointXYZ> cropHull;
cropHull.setInputCloud(cloud); // 设置输入点云
cropHull.setHullCloud(hull_points); // 设置凸包点云作为裁剪边界
cropHull.setHullIndices(hull_polygons);// 设置凸包的顶点索引
cropHull.setDim(3); // 使用三维空间裁剪
cropHull.filter(*cropped_cloud); // 执行裁剪并存储裁剪后的点云
}
// 可视化裁剪前和裁剪后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& cropped_cloud)
{
// 创建PCLVisualizer对象
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("CropHull Viewer"));
// 设置第一个视口,显示原始点云
int v1(0), v2(1);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 左侧视口
viewer->setBackgroundColor(1.0, 1.0, 1.0, v1); // 白色背景
viewer->addText("Original Point Cloud", 10, 10, "v1 text", v1); // 添加标题
viewer->addPointCloud(cloud, "original_cloud", v1); // 显示原始点云
// 设置第二个视口,显示裁剪后的点云
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2); // 右侧视口
viewer->setBackgroundColor(0.98, 0.98, 0.98, v2); // 浅灰色背景
viewer->addText("Cropped Point Cloud", 10, 10, "v2 text", v2); // 添加标题
viewer->addPointCloud(cropped_cloud, "cropped_cloud", v2); // 显示裁剪后的点云
viewer->addCoordinateSystem(1.0); // 添加坐标系
// 循环显示直到窗口关闭
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
}
}
int main(int argc, char** argv)
{
// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("data/bunny.pcd", *cloud) < 0)
{
PCL_ERROR("点云文件不存在");
return -1;
}
std::cout << "原始点云个数:" << cloud->points.size() << std::endl;
// 创建用于存储裁剪后的点云对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cropped_cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 调用裁剪过滤器函数
applyCropHullFilter(cloud, cropped_cloud);
// 输出裁剪后点云的个数
std::cout << "裁剪后点云个数:" << cropped_cloud->points.size() << std::endl;
// 可视化裁剪前和裁剪后的点云
visualizePointClouds(cloud, cropped_cloud);
return 0;
}