PCL_平面模型上构建凹(凸)多边形

步骤:

  1. 滤波预处理,减小分割干扰;
  2. 创建分割对象,获取平面模型参数;
  3. 创建投影滤波对象,滤波点云投影到平面模型上,获取投影后点云;
  4. 创建多边形投影对象,获取多边形边界上的点。

代码:

#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/surface/concave_hull.h>

int
main (int argc, char** argv)
{
  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;

  reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
  // Build a filter to remove spurious NaNs
  pcl::PassThrough<pcl::PointXYZ> pass;
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0, 1.1);
  pass.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering has: "
            << cloud_filtered->points.size () << " data points." << std::endl;

  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  // Create the segmentation object
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_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;

  // Project the model inliers
  pcl::ProjectInliers<pcl::PointXYZ> proj;
  proj.setModelType (pcl::SACMODEL_PLANE);
  proj.setInputCloud (cloud_filtered);
  proj.setModelCoefficients (coefficients);
  proj.filter (*cloud_projected);
  std::cerr << "PointCloud after projection has: "
            << cloud_projected->points.size () << " data points." << std::endl;

  // Create a Concave Hull representation of the projected inliers
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ConcaveHull<pcl::PointXYZ> chull;
  chull.setInputCloud (cloud_projected);
  chull.setAlpha (0.1);
  chull.reconstruct (*cloud_hull);

  std::cerr << "Concave hull has: " << cloud_hull->points.size ()
            << " data points." << std::endl;

  pcl::PCDWriter writer;
  writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);

  return (0);
}
### 如何从平面点云数据中提取内多边形轮廓 #### 数据预处理 在进行内多边形轮廓提取之前,通常需要对原始点云数据进行预处理。这一步骤包括加载点云文件并对其进行去噪操作,从而减少不必要的干扰因素。通过使用PCL中的`pcl::VoxelGrid`类可以实现体素网格滤波器来降低点云密度,同时也可以应用统计异常值移除方法(Statistical Outlier Removal,SOR),以进一步提高数据质量[^1]。 #### 平面分割 完成初步的数据清理之后,下一步是从复杂的场景中分离出目标所在的平面区域。此过程可以通过随机抽样一致性算法RANSAC (Random Sample Consensus) 来达成,在PCL中有专门用于执行这一功能的模块 `pcl::SACSegmentation< PointT >` 。该函数能够识别最佳拟合给定点集的一个数学模型——在这里即为一个平面方程,并返回属于这个平面的所有点坐标集合。 #### 投影变换 一旦获得了代表感兴趣表面的子集后,则需将其转换到二维空间以便后续分析更加简便高效。为此可采用正交投影技术把三维点映射至选定基准面上;这样做的好处在于简化了几何运算难度同时也保留了原有拓扑关系不变性特征。 #### 构建 对于已经降维后的二维点群来说,现在面临的主要挑战是如何界定其外部界限尤其是当存在内部陷部分时更是如此。一种常用策略便是运用α-shape理论框架下的特定参数设定来进行逼近估计得到最终结果形式。另外还有诸如Graham Scan或者Melkman Algorithm等经典包生成方案经过适当修改也可适用于此类情形之下[^3]。 #### 后续优化与存储 最后阶段涉及到了一些细节上的调整比如消除冗余顶点序列、确保方向一致等等然后再按照指定格式导出成果文档供其他程序调用解析之用。 ```python import pclpy as pcl from vtk.util.numpy_support import numpy_to_vtkPoints def preprocess_cloud(cloud): vox = pcl.filters.VoxelGrid() sor = pcl.filters.StatisticalOutlierRemoval() # Apply voxel grid filter to downsample the cloud. filtered_cloud = vox.setInputCloud(cloud).setLeafSize(0.01, 0.01, 0.01).filter() # Remove statistical outliers from the point cloud. cleaned_cloud = sor.setInputCloud(filtered_cloud).setMeanK(50).setStddevMulThresh(1.0).filter() return cleaned_cloud def segment_plane(cleaned_cloud): seg = pcl.segmentation.SACSegmentation() coefficients = pcl.ModelCoefficients() inliers = pcl.PointIndices() seg.setOptimizeCoefficients(True) seg.setModelType(pcl.SACMODEL_PLANE) seg.setMethodType(pcl.SAC_RANSAC) seg.setMaxIterations(1000) seg.setDistanceThreshold(0.01) plane_inliers = seg.setInputCloud(cleaned_cloud).segment(inliers,coefficients)[0] extracted_plane = cleaned_cloud.extract(plane_inliers.indices,True) return extracted_plane def project_points(extracted_plane): pass # Implement projection logic here. if __name__ == "__main__": input_file_path="path/to/input.pcd" output_file_path="path/to/output.txt" original_cloud=pcl.io.loadPCDFile(input_file_path,"PointXYZ") processed_cloud=preprocess_cloud(original_cloud) segmented_plane=segment_plane(processed_cloud) projected_2d_points=project_points(segmented_plane) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值