前言
点云分割在点云处理过程中十分重要。关于点云分割的算法有很多,接下来先介绍几种。
1.欧式分割
欧式分割其实就是欧式聚类,使用聚类的思想来实现点云分割的效果
代码如下:
2.RANSAC几何特征分割
使用RANSAC可以对点云进行拟合,可以拟合平面、直线、球、圆、圆柱、圆锥等。因此可以得到点云的内点,即拟合特征的标准方程上的点和外点(非特征点)。从而实现点云分割的效果。比较常见的自然是拟合平面,从点云中提取出平面点云。
代码如下:
/// <summary>
/// 使用PCL中集成的用于点云分割的RANSAC方法进行平面拟合
/// </summary>
/// <param name="cloud_in">输入待拟合的点云</param>
/// <param name="inliers">RANSAC拟合得到的内点</param>
/// <param name="coefficients">得到的平面方程参数</param>
/// <param name="iterations">平面拟合最大迭代次数</param>
/// <param name="threshold">RANSAC拟合算法距离阈值</param>
void SEG_RANSAC(const pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_in, pcl::PointIndices::Ptr& inliers, Eigen::VectorXf& coefficients,
const int& iterations, const double& threshold)
{
if (inliers == nullptr) inliers.reset(new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients_m(new pcl::ModelCoefficients);
pcl::SACSegmentation<pcl::PointXYZ> seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setMaxIterations(iterations); // 设置最大迭代次数
seg.setDistanceThreshold(threshold); // 设定阈值
seg.setNumberOfThreads(10); // 设置线程数量
seg.setInputCloud(cloud_in);
seg.segment(*inliers, *coefficients_m);
coefficients.resize(4);
coefficients[0] = coefficients_m->values[0]; coefficients[1] = coefficients_m->values[1];
coefficients[2] = coefficients_m->values[2]; coefficients[3] = coefficients_m->values[3];
std::cout << "SEG coefficients: " << coefficients[0] << ", " << coefficients[1] << ", " << coefficients[2] << ", " << coefficients[3] << std::endl;
}
3.凹包凸包检测分割
4.区域生长
5.射线法基于轮廓分割
函数使用了射线法(Ray Casting)来判断点是否在多边形内部。它通过遍历多边形的每条边,检查边与水平线(通过待检测点)的交点个数来确定点的位置。具体步骤如下:
初始化变量i为0,j为poly_sides - 1,res为0。
对于每一条多边形的边,进行如下判断:
判断边的两个端点中,一个在待检测点的上方,另一个在待检测点的下方,并且至少有一个端点的Y坐标小于待检测点的Y坐标,另一个端点的Y坐标大于等于待检测点的Y坐标。这个条件确保射线与边相交。
如果上述条件满足,并且边的两个端点中至少有一个的X坐标小于等于待检测点的X坐标,那么射线与边相交,并且交点的X坐标小于待检测点的X坐标。
对于每条满足上述条件的边,将res与1进行异或操作(即将res的最低位取反),用于计算交点的个数。
更新j为i,准备下一条边的判断。
返回res作为结果,如果res为1,则表示点在多边形内部;如果res为0,则表示点在多边形外部或边界上。