目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
本文将介绍如何使用PCL库进行点云的圆柱邻域搜索,并将搜索到的结果进行可视化展示。圆柱邻域搜索是一种特定的邻域搜索方法,通过在点云中查找某一特定点周围的邻域,分析和处理圆柱形物体的点云数据。
1.1原理
圆柱邻域搜索的基本思想是通过KD树(k-D Tree)进行半径搜索,但搜索时仅考虑投影到特定平面(如XY平面)上的点,形成圆柱形的搜索邻域。KD树是一种高效的空间数据结构,用于组织和查询多维数据点。在PCL中,KD树能够快速找到某点周围指定半径内的邻近点。
1.2实现步骤
- 读取点云数据。
- 对点云进行平面投影,生成圆柱形邻域搜索的基准点云。
- 使用KD树执行半径搜索,找到圆柱体邻域内的点。
- 将搜索到的邻域点和原始点云进行可视化展示。
1.3应用场景
- 圆柱体检测:在点云数据中,检测圆柱形物体或分析圆柱体周围的点云。
- 管道检测:分析管道内部或外部的点云数据,查找与管道形状相符合的邻域点。
- 3D重建:在三维点云中,对圆柱形状物体进行建模或重建。
二、代码实现
2.1关键函数
- pcl::KdTreeFLANN:用于构建KD树和执行搜索操作。
- radiusSearch:执行圆柱邻域搜索,找到指定半径内的所有邻域点。
- pcl::visualization::PCLVisualizer:用于可视化点云数据。
2.2完整代码
#include <iostream>
#include <vector>
#include <pcl/io/pcd_io.h> // 用于加载PCD文件的头文件
#include <pcl/point_types.h> // PCL点类型定义的头文件
#include <pcl/kdtree/kdtree_flann.h> // KD树近邻搜索的头文件
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h> // PCL可视化相关定义的头文件
using namespace std;
int main()
{
// --------------------------------读取点云------------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 加载PCD文件中的点云数据
if (pcl::io::loadPCDFile<pcl::PointXYZ>("person2.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read file!"); // 如果文件加载失败,输出错误信息
return -1; // 返回错误代码并退出程序
}
// -----------------------------圆柱形邻域搜索---------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cylindCloud(new pcl::PointCloud<pcl::PointXYZ>);
cylindCloud->resize(cloud->size()); // 调整圆柱点云的大小与原始点云一致
// 将点云投影到XY平面上(Z坐标设置为0),生成平面投影点云
for (size_t i = 0; i < cloud->size(); ++i)
{
cylindCloud->points[i].x = cloud->points[i].x;
cylindCloud->points[i].y = cloud->points[i].y;
cylindCloud->points[i].z = 0.0; // 将Z坐标设为0,投影到XY平面
}
// 创建KD树对象,用于快速查找邻域
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud(cylindCloud); // 设置KD树的输入点云为平面投影点云
// 选择一个点作为查询点,定义圆柱体的搜索中心
pcl::PointXYZ searchPoint = cylindCloud->points[200]; // 设置查询点为第2920个点
float radius = 0.3; // 定义查找半径范围为0.3单位
// 用于存储找到的邻域点的索引和对应的距离
vector<int> pointIdxRadiusSearch; // 保存每个邻域点的索引
vector<float> pointRadiusSquaredDistance; // 保存每个邻域点与查找点之间的距离平方值
// 创建点云对象result用于存储搜索到的邻域点
pcl::PointCloud<pcl::PointXYZ>::Ptr result(new pcl::PointCloud<pcl::PointXYZ>);
if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
{
// 如果搜索成功,将原始点云中对应索引的点复制到result点云中
pcl::copyPointCloud(*cloud, pointIdxRadiusSearch, *result);
}
// -------------------------------结果可视化------------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setWindowName("圆柱形邻域搜索"); // 设置窗口名称
// 设置原始点云的颜色为绿色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0); // 绿色
viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud"); // 添加原始点云到可视化窗口
// 设置圆柱邻域内点云的颜色为红色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cylind_color(cloud, 255, 0, 0); // 红色
viewer->addPointCloud<pcl::PointXYZ>(result, cylind_color, "cylind cloud"); // 添加邻域点云到可视化窗口
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cylind cloud"); // 设置邻域点云点的大小
// 进入主循环,保持窗口打开
while (!viewer->wasStopped())
{
viewer->spinOnce(100); // 刷新窗口
boost::this_thread::sleep(boost::posix_time::microseconds(100000)); // 等待100ms
}
return 0; // 程序结束
}