• PCL库点云小知识


    1.计算极值点

    #include 
    #include 
    #include 
    
    pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
    pcl::io::loadPCDFile ("your_pcd_file.pcd", *cloud);
    
    pcl::PointXYZ minPt, maxPt;
    pcl::getMinMax3D (*cloud, minPt, maxPt);
    
    #例如获取最大、最小的x值
    float max_x=maxPt.x;
    float min_x=minPt.x;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.从点云数据中删除和添加点

    #include 
    #include 
    #include 
    #include 
     
    pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
    pcl::io::loadPCDFile("your_pcd_file.pcd", *cloud);
    
    #1.删除指定位置的点
    pcl::PointCloud::iterator index=cloud->begin();
    cloud->erase(index);//删除第一个
    index=cloud->begin()+5;//删除第5个,???不是第6个吗?从0开始??
    
    #2.在指定位置添加点
    pcl::PointXYZ point={1,1,1};
    cloud->insert(cloud->begin()+5,point);//在索引号为5的位置1上插入一点,原来的点后移一位
    
    #3.在最后添加点
    cloud->push_back(point);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.1不同类型点云的相互转换

    #方法1.使用pcl自带的函数转换
     PointCloud cloud_xyz;
     PointCloud cloud_xyzrgb;
    copyPointCloud(cloud_xyz, cloud_xyzrgb);//将xyz形式点云转换成xyzrgb形式
    
    #方法2.直接赋值
    cloud_xyzrgb.points.resize(cloud_xyz.size());
     for (size_t i = 0; i < cloud_xyz.points.size(); i++) {
        cloud_xyzrgb.points[i].x = cloud_xyz.points[i].x;
        cloud_xyzrgb.points[i].y = cloud_xyz.points[i].y;
        cloud_xyzrgb.points[i].z = cloud_xyz.points[i].z;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.2点对象不同定义方式的相互转换
    (类似pcl::PointCloud::Ptr和pcl::PointCloud的两个类相互转换)

    #include 
    #include 
    #include 
     
    pcl::PointCloud::Ptr cloudPtr(new pcl::PointCloud);
    pcl::PointCloud cloud;
    cloud = *cloudPtr;//由Ptr转变为另一种类型
    cloudPtr = cloud.makeShared();//转变为Ptr类型
    ///注意**:一般常用pcl::PointCloud::Ptr,因为kdtree和octree类中的setInputCloud()函数只支持pcl::PointCloud::Ptr类型
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.知道了要保存的点云索引,如何从原点云中只保存需要的索引数据到新点云

    #include 
    #include 
    #include 
    #include 
     
    pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
    pcl::io::loadPCDFile("your_pcd_file.pcd", *cloud);
    pcl::PointCloud::Ptr cloudOut(new pcl::PointCloud);
    
    std::vector indexs={1,2,5}; //索引
    pcl::copuPointCloud(*cloud,indexs,*cloudOut);//保存到新点云
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5.如何删除无效点(某一个值为nan的点)

    pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
    pcl::PointCloud::Ptr output(new pcl::PointCloud);
    
    vector indices;
    pcl::removeNaNFromPointCloud(*cloud,*output,indices);
    pcl::io::savePCDFile("out.pcd",*output);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6.1使用flann kdtree 查询k近邻
    (如果被查询点在该点云中,那么第一个近邻为它本身)

    
    #include 
    pcl::KdTreeFLANN kdtree; //创建KDtree
    kdtree.setInputCloud (cloud);//输入点云
    int k=10;//查询的近邻点个数为10
    pcl::PointXYZ searchPoint={1,1,1};
    std::vector pointIdxNKNSearch(k); //存储近邻点集的索引
    std::vectorpointNKNSquareDistance(k); //近邻点集距离的平方值
    //size值即为查询到的k近邻点个数
    int size=kdtree.nearestKSearch(searchPoint,k,pointIdxNKNSearch,pointNKNSquareDistance);
    //如果size>0,则可以通过存储的索引对近邻点云进行提取
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    6.2使用flann kdtree 查询r范围近邻

    #include 
    pcl::KdTreeFLANN kdtree; //创建KDtree
    kdtree.setInputCloud (cloud); //输入点云
    float radius=0.5;//查询的近邻点的距离
    pcl::PointXYZ searchPoint={1,1,1};
    std::vector pointIdxRadiusSearch; //存储近邻点集的索引
    std::vectorpointNRSquareDistance; //近邻点集距离的平方值
    //size值即为查询searchPoint点在radius范围内近邻点的个数
    int size=kdtree.radiusSearch(searchPoint,radius,pointIdxRadiusSearch,pointNRSquareDistance);
    //如果size>0,则可以通过存储的索引对近邻点云进行提取
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.计算点云的平均密度

    //创建一个快速k近邻查询,查询的时候若该点在点云中,则第一个近邻点是其本身
    pcl::KdTreeFLANN kdtree;  
    kdtree.setInputCloud(cloud);//输入点云
    int k =2;
    float everagedistance =0;
    //为什么要使用cloud->size()/2个点,而不是全部点???
    for (int i =0; i < cloud->size()/2;i++)
    {
        vector indices ;
        vector squaredistance;
        kdtree.nearestKSearch(cloud->points[i],k,indices,squaredistance);
        everagedistance += sqrt(squaredistance[1]);
    }
    everagedistance = everagedistance/(cloud->size()/2);
    cout<<"everage distance is : "<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    8.质心计算

    Eigen::Vector4f centroid;  //质心
    pcl::compute3DCentroid(*cloud,centroid); //估计质心的坐标
    float centroid_x=centroid(0);
    float centroid_y=centroid(1);
    float centroid_z=centroid(2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    9.时间计算

    #include 
    pcl::console::TicToc time; time.tic(); //开始计时
    //你的程序片段 
    cout<
    • 1
    • 2
    • 3
    • 4

    10.使用vector存储点云
    在分割后常有多个簇,使用点云索引存储被分割后的多个簇在迭代读取时容易出现问题,若循环迭代的输入点云发生了变化,得到的子点云索引是新输入点云中的索引,并非最初的输入点云的索引,因此最可靠的方法是将子点云存入向量。

    //点云向量的定义方式
    std::vector, Eigen::aligned_allocator> clouds_vector;
    clouds_vector.push_back(cloud);  //将待保存点云存入向量。
    
    • 1
    • 2
    • 3

    注:ply文件不仅可以存储点信息,而且可以存储网格数据. 用emacs打开一个ply文件,观察表头,如果表头element face的值为0,则表示该文件为点云文件,如果element face的值为某一正整数N,则表示该文件为网格文件,且包含N个网格.

  • 相关阅读:
    TypeScript算法每日一题:两数之和(167)
    vue入门到精通-Axios入门
    【Java】二月份有多少天?
    【端到端存储解决方案】Weka,让企业【文件存储】速度飞起来!
    node-gyp rebuild error【npm install时报错】python
    VS+Qt+opencascade三维绘图stp/step/igs/stl格式图形读取显示
    LeetCode-83. Remove Duplicates from Sorted List [C++][Java]
    Oracle EBS 动态调用 XML Publisher 模板 输出不同的报表
    Laravel 实现redis分布式锁
    golang操作etcd
  • 原文地址:https://blog.csdn.net/qq_43685921/article/details/126969838