zoukankan      html  css  js  c++  java
  • pcl::PolygonMesh简析

    PCL利用VTK的IO接口,可以直接读取stl,ply,obj等格式的三维点云数据。pcl的接口方法为

    int
    pcl::io::loadPolygonFile (const std::string &file_name, pcl::PolygonMesh& mesh);

    这里要说明的对象即是PolygonMesh这个类。对于三角网格,其数据构成主要有三维点的坐标、构成三角面的点的索引以及法向量等。下面是类PolygonMesh的定义。

    struct PolygonMesh
      {
        PolygonMesh () : header (), cloud (), polygons ()
        {}
    
        ::pcl::PCLHeader  header;
    
        ::pcl::PCLPointCloud2 cloud;
    
        std::vector< ::pcl::Vertices>  polygons;
    
    
      public:
        typedef boost::shared_ptr< ::pcl::PolygonMesh> Ptr;
        typedef boost::shared_ptr< ::pcl::PolygonMesh const> ConstPtr;
      }; // struct PolygonMesh

    很明显,polygons是顶点的索引,每三个顶点构成一个三角面。根据惯例,可以猜测cloud应该是点云数据了,见PCLPointCloud2 定义。

    struct PCLPointCloud2
      {
        PCLPointCloud2 () : header (), height (0), width (0), fields (),
                         is_bigendian (false), point_step (0), row_step (0),
                         data (), is_dense (false)
        {
    #if defined(BOOST_BIG_ENDIAN)
          is_bigendian = true;
    #elif defined(BOOST_LITTLE_ENDIAN)
          is_bigendian = false;
    #else
    #error "unable to determine system endianness"
    #endif
        }
    
        ::pcl::PCLHeader header;
    
        pcl::uint32_t height;
        pcl::uint32_t width;
    
        std::vector< ::pcl::PCLPointField>  fields;
    
        pcl::uint8_t is_bigendian;
        pcl::uint32_t point_step;
        pcl::uint32_t row_step;
    
        std::vector<pcl::uint8_t> data;
    
        pcl::uint8_t is_dense;
    
      public:
        typedef boost::shared_ptr< ::pcl::PCLPointCloud2> Ptr;
        typedef boost::shared_ptr< ::pcl::PCLPointCloud2  const> ConstPtr;
      }; // struct PCLPointCloud2

    可以发现该类型完全不同于常用的PointCloud< PointT >,这里的std::vector< pcl::uint8_t > data跟点云坐标有没有关系并不能缺定。只能去查看PCL的IO源码部分。

    int
    pcl::io::vtk2mesh (const vtkSmartPointer<vtkPolyData>& poly_data, pcl::PolygonMesh& mesh)
    {
      mesh.polygons.resize (0);
      mesh.cloud.data.clear ();
      mesh.cloud.width = mesh.cloud.height = 0;
      mesh.cloud.is_dense = true;
    
      vtkSmartPointer<vtkPoints> mesh_points = poly_data->GetPoints ();
      vtkIdType nr_points = mesh_points->GetNumberOfPoints ();
      vtkIdType nr_polygons = poly_data->GetNumberOfPolys ();
    
      if (nr_points == 0)
        return (0);
    
    
      // First get the xyz information
      pcl::PointCloud<pcl::PointXYZ>::Ptr xyz_cloud (new pcl::PointCloud<pcl::PointXYZ> ());
      xyz_cloud->points.resize (nr_points);
      xyz_cloud->width = static_cast<uint32_t> (xyz_cloud->points.size ());
      xyz_cloud->height = 1;
      xyz_cloud->is_dense = true;
      double point_xyz[3];
      for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints (); i++)
      {
        mesh_points->GetPoint (i, &point_xyz[0]);
        xyz_cloud->points[i].x = static_cast<float> (point_xyz[0]);
        xyz_cloud->points[i].y = static_cast<float> (point_xyz[1]);
        xyz_cloud->points[i].z = static_cast<float> (point_xyz[2]);
      }
      // And put it in the mesh cloud
      pcl::toPCLPointCloud2 (*xyz_cloud, mesh.cloud);
    
      ...
    

    在vtk2mesh 方法中,xyz_cloud即是点云的xyz坐标信息,其通过toPCLPointCloud2 方法将数据赋值给PCLPointCloud2类型变量cloud,实现了pcl::PointCloud< pcl::PointXYZ >转化为PCLPointCloud2。同时可以发现,PCLPointCloud2不单保存xyz,还可以保存点云颜色以及法线向量

    此时,不难发现,同样存在PCLPointCloud2转化为pcl::PointCloud< pcl::PointXYZ >的方法fromPCLPointCloud2 :

     /** rief Convert a PCLPointCloud2 binary data blob into a pcl::PointCloud<T> object.
      * param[in] msg the PCLPointCloud2 binary blob
      * param[out] cloud the resultant pcl::PointCloud<T>
      */
      template<typename PointT> void
      fromPCLPointCloud2 (const pcl::PCLPointCloud2& msg, pcl::PointCloud<PointT>& cloud)

    值得注意的是,PCLPointCloud2 在转换成PointCloud< PointT>要确认类型匹配。

    示例代码:

    ...
    string infile = "J20170411_L.ply";
    
    pcl::PolygonMesh mesh;
    pcl::io::loadPolygonFile(infile, mesh);
    
    std::cout << "Polygon: " << mesh.polygons.size() << std::endl;
    std::cout <<"cloud: "<< mesh.cloud.width << std::endl;
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr 
    cloud(new pcl::PointCloud<pcl::PointXYZ>);
    fromPCLPointCloud2(mesh.cloud, *cloud);
    
    std::cout << cloud->width << " " << cloud->height << std::endl;
    std::cout << cloud->points.size() << endl;
    
    int index = rand() % 10000;
    std::cout << cloud->points[index].x << " " << 
    cloud->points[index].y << " " << cloud->points[index].z << std::endl;
    ...

    out

    ply模型数据:
    链接: https://pan.baidu.com/s/1i5khc93 密码: s4qu

  • 相关阅读:
    第01组 Beta冲刺(5/5)
    第01组 Beta冲刺(4/5)
    第01组 Beta冲刺(3/5)
    第01组 Beta冲刺(2/5)
    第01组 Beta冲刺(1/5)
    2019 SDN上机第6次作业
    SDN课程阅读作业(2)
    2019 SDN上机第5次作业
    第01组 Alpha事后诸葛亮
    第01组 Alpha冲刺(6/6)
  • 原文地址:https://www.cnblogs.com/brother-louie/p/13976569.html
Copyright © 2011-2022 走看看