当前位置: 首页 > article >正文

pcl源码分析之计算凸包

文章目录

  • 前言
  • 一、应用案例
  • 二、源码分析
    • 1.ConvexHull类
    • 2.reconstruct函数
    • 3.performReconstruction 函数
    • 4.calculateInputDimension 函数
  • 总结


前言

本文分析一下pcl里凸包的源码。什么是凸包以及怎么求解,可以了解一下概念。


一、应用案例

#include <pcl/surface/convex_hull.h>

	pcl::ConvexHull<pcl::PointXYZ> convex_hull;
	convex_hull.setInputCloud(cloud_in);//输入点云
	//convex_hull.setDimension(3);//设置维数,当然不设置,内部算法也会自己计算
	//pcl::PointCloud<pcl::PointXYZ>::Ptr hull_out(new pcl::PointCloud<pcl::PointXYZ>);
	convex_hull.reconstruct(*cloud_out);//输出凸包(点)
	convex_hull.getHullPointIndices(Indices);//输出凸包(点)在输入点云中的id

二、源码分析

1.ConvexHull类

  template<typename PointInT>
  class ConvexHull : public MeshConstruction<PointInT>
  {
  ...
  	  //构造函数中dimension_(数据的维数) 默认是0
  	  //x_axis_ , y_axis_ , z_axis_ 坐标轴三个参数也在这里确定
  	   /** \brief Empty constructor. */
      ConvexHull () : compute_area_ (false), total_area_ (0), total_volume_ (0), dimension_ (0), 
                      projection_angle_thresh_ (cos (0.174532925) ), qhull_flags ("qhull "),
                      x_axis_ (1.0, 0.0, 0.0), y_axis_ (0.0, 1.0, 0.0), z_axis_ (0.0, 0.0, 1.0)
      {
      };
  ...
	  //输出凸包接口
	      /** \brief Compute a convex hull for all points given.
        * \param[out] points the resultant points lying on the convex hull.
        */
      void
      reconstruct (PointCloud &points);
  ...
  	//设置维数接口(这里如果不设置具体的维数,则会维数默认值是构造函数里的值0,并且算法里会自行计算真实的维数)
      void 
      setDimension (int dimension)
      {
        if ((dimension == 2) || (dimension == 3))
          dimension_ = dimension;
        else
          PCL_ERROR ("[pcl::%s::setDimension] Invalid input dimension specified!\n", getClassName ().c_str ());
      }
  ...
    //获取凸包点在输入点云中的id
        void
      getHullPointIndices (pcl::PointIndices &hull_point_indices) const;
  ...
  }

2.reconstruct函数

template <typename PointInT> void
pcl::ConvexHull<PointInT>::reconstruct (PointCloud &points)
{
  points.header = input_->header;
  //初始化,这里initCompute 实际上是PCLBase这个基类的初始化函数,前文有讲过,这里不再赘述
  if (!initCompute () || input_->points.empty () || indices_->empty ())
  {
    points.points.clear ();
    return;
  }

  // Perform the actual surface reconstruction
  //这里就是真正的凸包计算接口
  std::vector<pcl::Vertices> polygons;
  performReconstruction (points, polygons, false);

  points.width = static_cast<uint32_t> (points.points.size ());
  points.height = 1;
  points.is_dense = true;

  deinitCompute ();
}

3.performReconstruction 函数

对于Qhull,有兴趣可以了解学习一下:
3.1 什么是Qhull
3.2 怎么下载编译Qhull
3.2 Qhull官网地址

template <typename PointInT> void
pcl::ConvexHull<PointInT>::performReconstruction (PointCloud &hull, std::vector<pcl::Vertices> &polygons,
                                                  bool fill_polygon_data)
{
  //如上面所说,如果没有在维度设置接口中设置维度,则默认维度是0,也即会执行calculateInputDimension 
  if (dimension_ == 0)
    calculateInputDimension ();
  //后面这两函数就是具体的调用哦个Ahull库来实现凸包的计算
  //具体怎么实现的,后续有空再研究吧,毕竟又涉及到另一个开源库,need more time~~
  if (dimension_ == 2)
    performReconstruction2D (hull, polygons, fill_polygon_data);
  else if (dimension_ == 3)
    performReconstruction3D (hull, polygons, fill_polygon_data);
  else
    PCL_ERROR ("[pcl::%s::performReconstruction] Error: invalid input dimension requested: %d\n",getClassName ().c_str (),dimension_);
}

4.calculateInputDimension 函数

template <typename PointInT> void
pcl::ConvexHull<PointInT>::calculateInputDimension ()
{
  PCL_DEBUG ("[pcl::%s::calculateInputDimension] WARNING: Input dimension not specified.  Automatically determining input dimension.\n", getClassName ().c_str ());
  //计算输入点云质心
  Eigen::Vector4d xyz_centroid;
  compute3DCentroid (*input_, *indices_, xyz_centroid);
  EIGEN_ALIGN16 Eigen::Matrix3d covariance_matrix;
  //计算每个点的协方差矩阵
  //这里原理就是:
  //1.将原始点云坐标减去中心点坐标
  //2.再对这些数据构造协方差矩阵,协方差矩阵具体构造原理看前文harris3d源码分析,就不再详细分析
  //3.有一点要说明,这个部分构造协方差矩阵的开源代码,比harris3d里协方差矩阵开源代码要清晰很多
  computeCovarianceMatrixNormalized (*input_, *indices_, xyz_centroid, covariance_matrix);
  
  //求协方差矩阵的特征值
  //主法向量是协方差矩阵的最小特征值对应的特征向量
  EIGEN_ALIGN16 Eigen::Vector3d eigen_values;
  pcl::eigen33 (covariance_matrix, eigen_values);
  //对于二维的数据,主法向量就是0或者近似于0
  if (std::abs (eigen_values[0]) < std::numeric_limits<double>::epsilon () || std::abs (eigen_values[0] / eigen_values[2]) < 1.0e-3)
    dimension_ = 2;
  else
    dimension_ = 3;
}

总结

分析了下pcl里求解凸包的整体流程,有一些收获~~


http://www.kler.cn/a/466464.html

相关文章:

  • HTML——56.表单发送
  • 用opencv实现像素统计
  • CANFD芯片在商业航天的应用
  • 【Unity报错】error Cs0103: The name ‘keyCode‘ does not exist in the current context
  • Python 中常见的数据结构之二推导式
  • [创业之路-232]:《华为闭环战略管理》-5-组织架构、业务架构、产品架构、技术架构、项目架构各自设计的原则是什么?
  • 设计模式之访问者模式:一楼千面 各有玄机
  • 养老院小程序怎么搭建?让老年人老有所养,老有所依!
  • 数据挖掘——关联规则挖掘
  • 如何进一步提高Oracle lgwr的写性能?
  • R机器学习:神经网络算法的理解与实操,实例解析
  • eplan如何导出可跳转的PDF
  • 【Rust练习】26.Package and Crate
  • 深入理解 Java Set 集合:原理、应用与高频面试题解析
  • 图片转三维模型网站(免费),AI建模,一键把图片转三维模型,二维图片转3维模型,AI建模
  • 用python编写一个放烟花的小程序
  • 机器学习笔记——正则化
  • Entity Framework Core介绍
  • React第二十一章(useCallback)
  • Kafka 快速实战及基本原理详解解析-01
  • Ubuntu Server安装谷歌浏览器
  • 多模态论文笔记——Coca
  • MATLAB中dbstack函数用法
  • 【pyqt】(四)Designer布局
  • 根据 el-dialog 的高度动态计算 el-table 的高度
  • 常规继承类对象大小