基于PCL的RANSAC(随机采样一致)算法简介与示例


前言

RANSAC(Random sample consensus,随机采样一致)是3D点云拟合的一种重要的手段,可以对直线、圆、平面,圆球、圆柱等形状的点云进行拟合,其优点在于可以最大程度上减少噪声点对拟合效果的影响。


一、RANSAC

RANSAC各种类型拟合的计算原理基本类似。
1,进行随机抽样,如直线,就随机找到两个点;如平面,就随机找到三个点来创建一个平面。
2,计算除去采样点的其余点与采样点组成的模型之间的距离,设定阈值,将符合阈值标准的点标记为内点,记录内点个数。
3,重复前面的步骤进行迭代计算,直到达到迭代终止条件,选择内点个数最多的模型计算最佳拟合参数。
其去除噪声影响效果好坏的关键在于内点阈值的选择和迭代次数。
PCL中有专门的一个类RandomSampleConsensus来实现其算法。
简单分析下其计算部分。

const double log_probability  = std::log (1.0 - probability_);

源码中probability_表示从数据集中选取采样点N均为局内点的概率。

// Better match ?
          if (n_inliers_count > n_best_inliers_count)
          {
            n_best_inliers_count = n_inliers_count; // This write and the previous read of n_best_inliers_count must be consecutive and must not be interrupted!
            n_best_inliers_count_tmp = n_best_inliers_count;

            // Save the current model/inlier/coefficients selection as being the best so far
            model_              = selection;
            model_coefficients_ = model_coefficients;

            // Compute the k parameter (k=std::log(z)/std::log(1-w^n))
            const double w = static_cast<double> (n_best_inliers_count) * one_over_indices;
            double p_no_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ()));
            p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers);       // Avoid division by -Inf
            p_no_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_no_outliers);   // Avoid division by 0.
            k = log_probability / std::log (p_no_outliers);
          }

以上为寻找最佳模型的代码。
w的值为从数据集中选取一个采样点为局内点的概率。
p_no_outliers:顾名思义,意思为非局外点的概率。
k表示估计的迭代采样次数。

二、应用示例

1.拟合直线

PCL中采样一致直线模型的类为SampleConsensusModelLine
通过这个类将输入的点云转化为采样一致模型。

pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr line(new pcl::SampleConsensusModelLine<pcl::PointXYZ>(cloud));
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(line);
ransac.setDistanceThreshold(0.01);
ransac.setMaxIterations(1000);
ransac.computeModel();

vector<int> inliers;
ransac.getInliers(inliers);

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_line(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *cloud_line);

Eigen::VectorXf coefficient;
ransac.getModelCoefficients(coefficient);

基于PCL的RANSAC(随机采样一致)算法简介与示例_第1张图片

2.拟合平面

同样,SampleConsensusModelPlane表示采样一致平面的模型。

pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr plane(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));

pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(plane);
ransac.setDistanceThreshold(0.1);
ransac.setMaxIterations(500);
ransac.setProbability(0.99);
ransac.computeModel();
vector<int> inliers; 
ransac.getInliers(inliers);       

Eigen::VectorXf coefficient;
ransac.getModelCoefficients(coefficient); 

基于PCL的RANSAC(随机采样一致)算法简介与示例_第2张图片

3.拟合球

SampleConsensusModelSphere表示采样一致平面的模型。

pcl::SampleConsensusModelSphere<pcl::PointXYZ>::Ptr	sphere(new pcl::SampleConsensusModelSphere<pcl::PointXYZ>(cloud));

pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(sphere);
ransac.setDistanceThreshold(0.1);
ransac.setMaxIterations(1000);
ransac.setProbability(0.99);
ransac.computeModel();

Eigen::VectorXf coeff;
ransac.getModelCoefficients(coeff);

pcl::IndicesPtr inliers(new vector <int>());
ransac.getInliers(*inliers);

基于PCL的RANSAC(随机采样一致)算法简介与示例_第3张图片

总结

优点:避免噪声点对拟合结果的干扰。
缺点:由于计算结果的不确定性,迭代次数可能过高,对于密集点云来讲,计算时间过长,需要进行预处理后再进行拟合过程,但同样会损失时间。
原理部分参考:
随机抽样一致算法(Random sample consensus,RANSAC)详解,保姆级教程
PCL函数库摘要——采样一致性

你可能感兴趣的:(PCL总结,3d,c++)