目录
PCL点云算法汇总及实战案例汇总的目录地址链接:
一、概述
根据索引提取点云子集 是在点云处理中常见的操作之一。PCL 提供了pcl::ExtractIndices 类,允许从点云中提取指定索引的点,形成一个新的子集点云。这种方法特别适用于从计算结果中提取感兴趣的点集,或者去除不需要的点。
1.1原理
通过提供点云中某些点的索引,可以提取这些索引对应的点形成一个子集。PCL 的 ExtractIndices 类会根据输入的索引提取指定点,同时可以选择是保留还是去除这些点。
1.2实现步骤
- 读取点云数据。
- 定义要提取的索引(如通过计算或手动指定)。
- 使用 pcl::ExtractIndices 提取对应的点云子集。
- 可视化提取结果。
1.3应用场景
- 提取感兴趣区域:通过索引提取特定的感兴趣区域进行后续处理。
- 噪声去除:去除或提取某些噪声点。
- 子集操作:在点云处理过程中提取某些区域,进行细粒度操作。
二、代码实现
2.1关键函数
2.1.1 根据索引提取点云
使用 pcl::ExtractIndices 类来从点云中提取指定索引的点。
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
// 根据索引提取点云子集
pcl::PointCloud<pcl::PointXYZ>::Ptr extractSubsetByIndices(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 输入点云
const std::vector<int>& indices // 要提取的索引
)
{
// 创建索引对象
pcl::PointIndices::Ptr indices_ptr(new pcl::PointIndices);
indices_ptr->indices = indices;
// 创建提取对象
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud); // 设置输入点云
extract.setIndices(indices_ptr); // 设置要提取的索引
extract.setNegative(false); // false 表示提取指定索引的点
// 提取后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr extracted_cloud(new pcl::PointCloud<pcl::PointXYZ>);
extract.filter(*extracted_cloud); // 执行提取操作
return extracted_cloud; // 返回提取的子集点云
}
2.1.2 可视化函数
#include <pcl/visualization/pcl_visualizer.h>
// 可视化点云
void visualizePointClouds(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 原始点云
pcl::PointCloud<pcl::PointXYZ>::Ptr subset_cloud // 子集点云
)
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Point Cloud Viewer"));
// 创建视口1,显示原始点云
int vp_1;
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1); // 左侧窗口
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1); // 白色背景
viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> original_color(cloud, 0, 255, 0); // 绿色
viewer->addPointCloud(cloud, original_color, "original_cloud", vp_1);
// 创建视口2,显示子集点云
int vp_2;
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2); // 右侧窗口
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2); // 浅灰色背景
viewer->addText("Subset PointCloud", 10, 10, "vp2_text", vp_2);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> subset_color(subset_cloud, 255, 0, 0); // 红色
viewer->addPointCloud(subset_cloud, subset_color, "subset_cloud", vp_2);
// 设置点的大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "subset_cloud", vp_2);
// 启动可视化循环
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
}
}
2.2完整代码
// C++头文件
#include <iostream>
// PCL头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/visualization/pcl_visualizer.h>
// 根据索引提取点云子集
pcl::PointCloud<pcl::PointXYZ>::Ptr extractSubsetByIndices(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 输入点云
const std::vector<int>& indices // 要提取的索引
)
{
// 创建索引对象
pcl::PointIndices::Ptr indices_ptr(new pcl::PointIndices);
indices_ptr->indices = indices;
// 创建提取对象
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud); // 设置输入点云
extract.setIndices(indices_ptr); // 设置要提取的索引
extract.setNegative(false); // false 表示提取指定索引的点
// 提取后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr extracted_cloud(new pcl::PointCloud<pcl::PointXYZ>);
extract.filter(*extracted_cloud); // 执行提取操作
return extracted_cloud; // 返回提取的子集点云
}
// 可视化点云
void visualizePointClouds(
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 原始点云
pcl::PointCloud<pcl::PointXYZ>::Ptr subset_cloud // 子集点云
)
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Point Cloud Viewer"));
// 创建视口1,显示原始点云
int vp_1;
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1); // 左侧窗口
viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1); // 白色背景
viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> original_color(cloud, 0, 255, 0); // 绿色
viewer->addPointCloud(cloud, original_color, "original_cloud", vp_1);
// 创建视口2,显示子集点云
int vp_2;
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2); // 右侧窗口
viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2); // 浅灰色背景
viewer->addText("Subset PointCloud", 10, 10, "vp2_text", vp_2);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> subset_color(subset_cloud, 255, 0, 0); // 红色
viewer->addPointCloud(subset_cloud, subset_color, "subset_cloud", vp_2);
// 设置点的大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "subset_cloud", vp_2);
// 启动可视化循环
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("bunny.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read the file\n");
return -1;
}
// 定义前 1000 个点的索引
std::vector<int> indices;
for (int i = 0; i < std::min(1000, static_cast<int>(cloud->points.size())); ++i)
{
indices.push_back(i);
}
// 根据索引提取点云子集
pcl::PointCloud<pcl::PointXYZ>::Ptr subset_cloud = extractSubsetByIndices(cloud, indices);
// 可视化原始点云和子集点云
visualizePointClouds(cloud, subset_cloud);
return 0;
}
三、实现效果
提取前1000个点