文章目录[隐藏]
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
暂无评论