【PCL】教程concave_hull_2d.cpp 对点云进行过滤、分割、投影以及凹包构建

ddce9d6f52fcbeaa2d031782c1c74dfe.png

[done, 599.439 ms : 307200 points]
Available dimensions: x y z rgb

原始点云

PointCloud after filtering has: 139656 data points.
PointCloud after segmentation has: 123727 inliers.
PointCloud after projection has: 139656 data points.
Concave hull has: 457 data points.

87fdf5e48d2d7bf241aabed4ea8e2049.png

[done, 438.018 ms : 457 points]
Available dimensions: x y z

投影后点云凸包

该段代码是一个使用PCL(Point Cloud Library,点云库)进行点云处理的完整程序。程序的主要过程如下:

  1. 首先,初始化三个pcl::PointCloud<pcl::PointXYZ>智能指针cloud用于存储原始点云数据,cloud_filtered用于存储过滤后的点云数据,cloud_projected用于存储投影后的点云数据。

  2. 使用pcl::PCDReader对象读取名为"table_scene_mug_stereo_textured.pcd"的PCD文件到cloud中。

  3. 使用pcl::PassThrough<pcl::PointXYZ>过滤器来移除点云中的NaN值,同时根据z字段的范围(0到1.1)来裁剪点云,以移除场景背景,结果存入cloud_filtered

  4. 初始化pcl::ModelCoefficientspcl::PointIndices,以存储模型系数和分割得到的内点索引

  5. 创建pcl::SACSegmentation<pcl::PointXYZ>对象进行分割操作,设置模型类型为平面(pcl::SACMODEL_PLANE)方法类型为RANSAC(pcl::SAC_RANSAC),并设定距离阈值为0.01。将cloud_filtered作为输入进行分割,并将内点索引存入inliers

  6. 使用pcl::ProjectInliers<pcl::PointXYZ>对象将分割出的平面内点投影到一个模型平面上,得到的投影点云存储在cloud_projected

  7. 创建一个凹包(Concave Hull)的表示形式,使用pcl::ConcaveHull<pcl::PointXYZ>对象对投影的点云cloud_projected进行处理,设置凹包的alpha值为0.1,并将重构后的凹包点云存储在cloud_hull

  8. 最后,使用pcl::PCDWriter对象将凹包点云写入名为"table_scene_mug_stereo_textured_hull.pcd"的文件中。

  9. 程序返回0,正常结束。

总而言之,这段代码是利用PCL对3D点云数据进行预处理的工作流程,这包括对点云进行过滤、分割、投影以及凹包构建等处理步骤,最终生成了目标物体凹包表示的点云数据,这种数据可用于后续的物体识别或其他点云处理任务。

// 包含PCL库中关于模型系数的头文件
#include <pcl/ModelCoefficients.h>
// 包含PCL库中PCD文件输入输出的头文件
#include <pcl/io/pcd_io.h>
// 包含PCL库中点类型定义的头文件
#include <pcl/point_types.h>
// 包含PCL库中随机抽样一致性算法所需方法类型的头文件
#include <pcl/sample_consensus/method_types.h>
// 包含PCL库中随机抽样一致性算法所需模型类型的头文件
#include <pcl/sample_consensus/model_types.h>
// 包含PCL库中直通滤波器的头文件
#include <pcl/filters/passthrough.h>
// 包含PCL库中点云投影的头文件
#include <pcl/filters/project_inliers.h>
// 包含PCL库中平面分割的头文件
#include <pcl/segmentation/sac_segmentation.h>
// 包含PCL库中凹面包络的头文件
#include <pcl/surface/concave_hull.h>


// 主函数入口
int
main ()
{
  // 创建几个PointCloud<pcl::PointXYZ>智能指针,用于后续存储数据
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), 
                                      cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), 
                                      cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PCDReader reader;
  
  // 从PCD文件中读取点云数据
  reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
  // 创建直通过滤器,移除NaN数据点和背景的数据点
  pcl::PassThrough<pcl::PointXYZ> pass;
  // 设置输入点云
  pass.setInputCloud (cloud);
  // 设置过滤时所用的字段名称
  pass.setFilterFieldName ("z");
  // 设置过滤的z轴数值范围为0到1.1
  pass.setFilterLimits (0, 1.1);
  // 进行过滤,并保存结果到cloud_filtered
  pass.filter (*cloud_filtered);
  // 输出过滤之后点云的数量
  std::cerr << "PointCloud after filtering has: "
            << cloud_filtered->size () << " data points." << std::endl;


  // 定义一个模型系数对象和点索引对象的智能指针
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  // 创建平面分割对象
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // 可选设置,设置优化系数
  seg.setOptimizeCoefficients (true);
  // 必选设置,选择分割模型的类型,这里选择平面模型
  seg.setModelType (pcl::SACMODEL_PLANE);
  // 必选设置,选择采用的RANSAC方法类型
  seg.setMethodType (pcl::SAC_RANSAC);
  // 设置RANSAC的距离阈值
  seg.setDistanceThreshold (0.01);


  // 设置输入点云为过滤后的点云
  seg.setInputCloud (cloud_filtered);
  // 执行分割操作,并将分割结果的内点和模型系数输出
  seg.segment (*inliers, *coefficients);
  // 输出分割后的内点数量
  std::cerr << "PointCloud after segmentation has: "
            << inliers->indices.size () << " inliers." << std::endl;


  // 创建点云投影对象
  pcl::ProjectInliers<pcl::PointXYZ> proj;
  // 设置投影模型的类型
  proj.setModelType (pcl::SACMODEL_PLANE);
  // 设置输入的点云为过滤后的点云
  proj.setInputCloud (cloud_filtered);
  // 设置模型系数
  proj.setModelCoefficients (coefficients);
  // 执行投影滤波,并将结果输出到cloud_projected
  proj.filter (*cloud_projected);
  // 输出投影后的点云数量
  std::cerr << "PointCloud after projection has: "
            << cloud_projected->size () << " data points." << std::endl;


  // 创建凹面包络(Concave Hull)对象
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ConcaveHull<pcl::PointXYZ> chull;
  // 设置输入的点云为投影后的点云
  chull.setInputCloud (cloud_projected);
  // 设置凹面包络的alpha值,控制输出凹包络的形状
  chull.setAlpha (0.1);
  // 构建凹面包络,输出结果到cloud_hull
  chull.reconstruct (*cloud_hull);


  // 输出凹面包络的点数量
  std::cerr << "Concave hull has: " << cloud_hull->size ()
            << " data points." << std::endl;


  // 创建PCD文件写入对象
  pcl::PCDWriter writer;
  // 将凹面包络的点云数据写入到文件中
  writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);


  // 程序正常执行结束
  return (0);
}

代码的主要功能:

  1. 从PCD文件中读取点云数据。

  2. 使用直通过滤器(PassThrough)移除NaNs值和不在指定范围内的点。

  3. 使用SACSegmentation进行基于RANSAC的平面分割,输出平面模型的内点(inliers)和模型系数(coefficients)。

  4. 使用ProjectInliers将内点投影到平面模型上。

  5. 使用ConcaveHull构造投影点云的凹包络,输出凹面形状

  6. 最终将凹面包络的点云数据写入到新的PCD文件中。

pcl::PassThrough<pcl::PointXYZ>

c6791137925bf863e9b65cd36da1aa07.png

pcl::ModelCoefficients::Ptr

fa09bf5b56d559269e42c2b520f9838d.png

pcl::SACSegmentation<pcl::PointXYZ>

86b0424d5fa51e266708f47b16330ad3.png

样本一致性算法,如 RANSAC、LMedS、MSAC 和 MLESAC

样本一致性算法是用于从数据中估计数学模型参数的一组算法,特别适用于数据中含有大量离群点(噪声)的情况。它们通过迭代地选择一组随机样本来估计模型,并计算整个数据集中有多少点符合该模型(内点),然后选择出最佳匹配的模型。下面是一些常见的样本一致性算法,以及它们的应用场景对比:

RANSAC(Random Sample Consensus)

RANSAC 是一种基本且广泛使用的样本一致性算法。

  • 特点:假设数据集中大部分数据是内点,内点是可以拟合成某个模型的。

  • 优势:对于大量的噪声和离群点非常鲁棒。

  • 劣势:可能需要较多的迭代次数,所需迭代次数难以提前确定,可能无法找到最优解。

  • 应用场景:适用于点云分割、图像配准、目标检测等,在点云数据处理和计算机视觉领域非常常见。

LMedS(Least Median of Squares)

LMedS 是另一种样本一致性算法,它通过最小化中值误差来增强数据噪声的鲁棒性。

  • 特点:不需要设置误差阈值。

  • 优势:非常鲁棒,特别是在有高比例的离群点时。

  • 劣势:无法直接确保结果模型优化到最高程度,且计算代价相对较高。

  • 应用场景:当离群点比例很高,且数据分布不清楚时候适用,常见于健壮回归分析。

MSAC(M-Estimator SAmple Consensus)

MSAC 是 RANSAC 的变种,它通过修改成本函数改善了估计质量。

  • 特点:使用另一种成本函数,倾向于内点较多的模型。

  • 优势:结果模型的质量通常比 RANSAC 更好。

  • 劣势:对于成本函数的选择比较敏感。

  • 应用场景:在重视模型质量,但同时需要鲁棒性的场合,如图像分析和三维重建。

MLESAC(Maximum Likelihood Estimation SAmple Consensus)

MLESAC 是 RANSAC 的另一个变种,它通过最大似然估计来提高参数估计的准确性。

  • 特点:将问题转化为最大似然估计问题,更偏向于可能性高的模型。

  • 优势:相比 RANSAC,能够得到更准确的参数估计。

  • 劣势:计算代价较高,设置适当的似然函数可能很复杂。

  • 应用场景:当需要非常准确的参数估计时,如在高精度的机器人导航和地图制作中。

总结

所有这些算法都各有特点和优势,也都各自适合于不同类型的问题。选择哪种算法往往取决于应用需求、噪声和离群点的比例、计算资源等因素。通常,RANSAC 是最常见的起点,但若数据中的噪声比例极高或者需要更精确的模型,可能需要考虑使用 LMedS、MSAC 或 MLESAC 等算法。最终的选择应根据具体问题和实验结果来确定。

pcl::ProjectInliers<pcl::PointXYZ>

cad42c2683fa501eba5598bf1ebbfb69.png

pcl::ConcaveHull<pcl::PointXYZ>

a63a10cff4b2decedda52027bfe81563.png

pcl::PCDWriter

0a32ec41acafad70b67836178e46c4fd.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值