三维目标检测:(三)用PCL中的RANSAC算法去除点云的平面点

RANSAC算法原理

随机采样一致性原理如下

https://blog.csdn.net/qq_28087491/article/details/107376740

简单来说,如果三个点确定一个平面,那我们随机取三个点,然后拟合成一个平面,我们计算有多少点在平面上,然后不断迭代更新这三个点,最终到达迭代次数后,结束迭代。

用PCL库中的代码实现

1.需要引入的头文件

#include <pcl/filters/extract_indices.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>

2.具体的代码实现

	pcl::PointCloud<PointType>::Ptr ground_cloud(new pcl::PointCloud<PointType>);
    if (cloudPtrv->size() > 0) {
        //创建分割时所需要的模型系数对象,coefficients及存储内点的点索引集合对象inliers
        pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
        pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
        // 创建分割对象
        pcl::SACSegmentation<PointType> seg;
        // 可选择配置,设置模型系数需要优化
        seg.setOptimizeCoefficients(true);
        // 必要的配置,设置分割的模型类型,所用的随机参数估计方法,距离阀值,输入点云
        seg.setModelType(pcl::SACMODEL_PLANE);//设置模型类型
//                SACMODEL_PLANE, 三维平面
//                SACMODEL_LINE,    三维直线
//                SACMODEL_CIRCLE2D, 二维圆
//                SACMODEL_CIRCLE3D,  三维圆
//                SACMODEL_SPHERE,      球
//                SACMODEL_CYLINDER,    柱
//                SACMODEL_CONE,        锥
//                SACMODEL_TORUS,       环面
//                SACMODEL_PARALLEL_LINE,   平行线
//                SACMODEL_PERPENDICULAR_PLANE, 垂直平面
//                SACMODEL_PARALLEL_LINES,  平行线
//                SACMODEL_NORMAL_PLANE,    法向平面
//                SACMODEL_NORMAL_SPHERE,   法向球
//                SACMODEL_REGISTRATION,
//                SACMODEL_REGISTRATION_2D,
//                SACMODEL_PARALLEL_PLANE,  平行平面
//                SACMODEL_NORMAL_PARALLEL_PLANE,   法向平行平面
//                SACMODEL_STICK
        seg.setMethodType(pcl::SAC_RANSAC);//设置随机采样一致性方法类型
        // you can modify the parameter below
        seg.setMaxIterations(10000);//设置最大迭代次数
        seg.setDistanceThreshold(0.01);//设定距离阀值,距离阀值决定了点被认为是局内点是必须满足的条件
        seg.setInputCloud(cloudPtrv);
        //引发分割实现,存储分割结果到点几何inliers及存储平面模型的系数coefficients
        seg.segment(*inliers, *coefficients);
        if (inliers->indices.size() == 0) {
            cout << "error! Could not found any inliers!" << endl;
        }
	// 从点云中抽取分割的处在平面上的点集
        pcl::ExtractIndices<PointType> extractor;//点提取对象
        extractor.setInputCloud(cloudPtrv);
        extractor.setIndices(inliers);
        //true表示的是输入点集以外的点
        extractor.setNegative(true);
        extractor.filter(*obj_cloud);
        // 从点云中抽取分割的处在平面上的点集
        pcl::ExtractIndices<PointType> extractor1;//点提取对象
        extractor1.setInputCloud(cloudPtrv);
        extractor1.setIndices(inliers);
         //false表示的是输入点集的点
        extractor1.setNegative(false);
        extractor1.filter(*ground_cloud);
        cout << "filter done." << endl;

3.用ros节点输出,可以用rviz查看

        sensor_msgs::PointCloud2 plant_output;
        sensor_msgs::PointCloud2 obj_output;
        pcl::toROSMsg(*ground_cloud, plant_output);
        pub_plant.publish(plant_output);
        pcl::toROSMsg(*obj_cloud, obj_output);
        pub_obj.publish(obj_output);

参数解析

1.是否采用优化器优化,优化的话效果会比较好。

seg.setOptimizeCoefficients(true);

2.选择要拟合的模型(平面,圆柱…)

seg.setModelType(pcl::SACMODEL_PLANE);

SACMODEL_PLANE, 三维平面
// SACMODEL_LINE, 三维直线
// SACMODEL_CIRCLE2D, 二维圆
// SACMODEL_CIRCLE3D, 三维圆
// SACMODEL_SPHERE, 球
// SACMODEL_CYLINDER, 柱
// SACMODEL_CONE, 锥
// SACMODEL_TORUS, 环面
// SACMODEL_PARALLEL_LINE, 平行线
// SACMODEL_PERPENDICULAR_PLANE, 垂直平面
// SACMODEL_PARALLEL_LINES, 平行线
// SACMODEL_NORMAL_PLANE, 法向平面
// SACMODEL_NORMAL_SPHERE, 法向球
// SACMODEL_REGISTRATION,
// SACMODEL_REGISTRATION_2D,
// SACMODEL_PARALLEL_PLANE, 平行平面
// SACMODEL_NORMAL_PARALLEL_PLANE, 法向平行平面
// SACMODEL_STICK

3.采用拟合方法

seg.setMethodType(pcl::SAC_RANSAC);

也可以采用其他的方法,比如 SAC_LMEdS 最小中值法:

LMedS的做法很简单,就是从样本中随机抽出N个样本子集,使用最大似然(通常是最小二乘) 对每个子集计算模型参数和该模型的偏差,记录该模型参数及子集中所有样本中偏差居中的那个样本的偏差(即Med偏差),最后选取N个样本子集中Med偏差最小的所对应的模型参数作为我们要估计的模型参数。

4.最大迭代次数

seg.setMaxIterations(20000);//设置最大迭代次数

5.设定距离阀值,距离阀值决定了点被认为是局内点是必须满足的条件

seg.setDistanceThreshold(0.03);

意思是平面上下0.03m距离的点都归类于平面点

6.输入点云

seg.setInputCloud(cloudPtrv);

7.输出

seg.segment(*inliers, *coefficients);

引发分割实现,存储分割结果到点几何inliers及存储平面模型的系数coefficients

版权声明:本文为CSDN博主「ZZZZZZZZZZZZZYQ」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43348387/article/details/121443704

ZZZZZZZZZZZZZYQ

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

【原理篇】一文读懂Mask RCNN

Mask RCNN 何凯明大神的经典论文之一,是一个实例分割算法,正如文中所说,Mask RCNN是一个简单、灵活、通用的框架,该框架主要作用是实例分割,目标检测&#xff0