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;
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);
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;
}
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类型
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);//保存到新点云
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);
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,则可以通过存储的索引对近邻点云进行提取
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,则可以通过存储的索引对近邻点云进行提取
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 : "<
8.质心计算
Eigen::Vector4f centroid; //质心
pcl::compute3DCentroid(*cloud,centroid); //估计质心的坐标
float centroid_x=centroid(0);
float centroid_y=centroid(1);
float centroid_z=centroid(2);
9.时间计算
#include
pcl::console::TicToc time; time.tic(); //开始计时
//你的程序片段
cout<
10.使用vector存储点云
在分割后常有多个簇,使用点云索引存储被分割后的多个簇在迭代读取时容易出现问题,若循环迭代的输入点云发生了变化,得到的子点云索引是新输入点云中的索引,并非最初的输入点云的索引,因此最可靠的方法是将子点云存入向量。
//点云向量的定义方式
std::vector, Eigen::aligned_allocator> clouds_vector;
clouds_vector.push_back(cloud); //将待保存点云存入向量。
注:ply文件不仅可以存储点信息,而且可以存储网格数据. 用emacs打开一个ply文件,观察表头,如果表头element face的值为0,则表示该文件为点云文件,如果element face的值为某一正整数N,则表示该文件为网格文件,且包含N个网格.