PCL随机采样一致性:RANSAC 平面拟合

Posted 借我十斤肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCL随机采样一致性:RANSAC 平面拟合相关的知识,希望对你有一定的参考价值。

1 平面方程

平面方程 是指空间中所有处于同一平面的点所对应的方程,其一般式形如 A x + B y + C z + D = 0 Ax+By+Cz+D=0 Ax+By+Cz+D=0点已知平面法向量 ( A , B , C ) (A,B,C) (A,B,C) 和平面上一点 p 0 ( x 0 , y 0 , z 0 ) p_0(x_0,y_0,z_0) p0(x0,y0,z0),则平面的点法式方程为 A ( x − x 0 ) + B ( y − y 0 ) + C ( z − z 0 ) = 0 A(x-x_0)+B(y-y_0)+C(z-z_0)=0 A(xx0)+B(yy0)+C(zz0)=0将点法式展开,其常数项 − ( A x 0 + B y 0 + C z 0 ) -(Ax_0+By_0+Cz_0) (Ax0+By0+Cz0)即为一般式方程中的 D D D,即 D = − ( A x 0 + B y 0 + C z 0 ) D=-(Ax_0+By_0+Cz_0) D=(Ax0+By0+Cz0)

2 算法原理

与最小二乘算法不同,随机采样一致性算法(RANSAC)不是用所有初始数据去获取一个初始解,然后剔除无效数据,而是使用满足可行条件的尽量少的初始数据,并使用一致性数据集去扩大它,这是一种寻找模型去拟合数据的思想,在计算机视觉领域有较广泛的应用。

RANSAC平面拟合的过程如下:

(1)在初始点云中随机选择三个点,计算其对应平面方程 a x + b y + c z + d = 0 ax + by + cz+d=0 ax+by+cz+d=0.

(2)计算所有点至该平面的代数距离 d i = ∣ a x i + b y i + c z i + d ∣ d_i=|ax_i+by_i+cz_i+d| di=axi+byi+czi+d .选取阈值 d t h r e s h o l d d_{threshold} dthreshold,若 d i ≤ d t h r e s h o l d di≤d_{threshold} didthreshold ,则该点被认为是模型内样本点(内点),否则为模型外样本点(外点),记录当前内点的个数。

(3)重复以上步骤,选取最佳拟合参数,即内点数量最多的平面对应的模型参数;每次迭代末尾都会根据期望的误差率、最佳内点个数、总样本个数、当前迭代次数计算一个迭代结束评判因子,根据次决定是否停止迭代。

(4)迭代结束后,最佳模型参数就是最终的参数估计值。

3 算法实现

PCL中Sample——consensus模块提供了RANSAC平面拟合模块。

SACMODEL_PLANE模型:定义为平面模型,共设置四个参数 [normal_x,normal_y,normal_z,d]。其中,(normal_x,normal_y,normal_z)为平面法向量,d为常数项。

实现代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;

int main()
{
	//---------------------------------------------
	//-------------------加载点云-------------------
	//---------------------------------------------
	cout << "->正在加载点云..." << endl;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile("plane.pcd", *cloud) < 0)
	{
		PCL_ERROR("警告!点云文件不存在!\\a\\n");
		system("pause");
		return -1;
	}

	//---------------------------------------------
	//-------------------模型估计-------------------
	//---------------------------------------------
	cout << "->正在估计平面..." << endl;
	pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr model_plane(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));	//选择拟合点云与几何模型
	pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_plane);	//创建随机采样一致性对象
	ransac.setDistanceThreshold(0.01);	//设置距离阈值,与平面距离小于0.01的点作为内点
	ransac.computeModel();				//执行模型估计
	vector<int> inliers;				//存储内点索引的向量
	ransac.getInliers(inliers);			//提取内点对应的索引
	
	/// 根据索引提取内点
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *cloud_plane);

	/// 输出模型参数ax+by+cz+d=0
	Eigen::VectorXf coefficient;
	ransac.getModelCoefficients(coefficient);
	cout << "平面方程为:\\n"
		<< coefficient[0] << "x + "
		<< coefficient[1] << "y + "
		<< coefficient[2] << "z + "
		<< coefficient[3] << " = 0"
		<< endl;


	//==========================================↓ 可视化拟合结果 ↓==========================================

	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("拟合结果"));

	viewer->addPointCloud<pcl::PointXYZ>(cloud, "cloud");													//添加原始点云
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 1, "cloud");	//颜色
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");	//点的大小

	viewer->addPointCloud<pcl::PointXYZ>(cloud_plane, "plane");												//添加平面点云
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "plane");	//颜色
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "plane");	//点的大小

	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	//==========================================↑ 可视化拟合结果 ↑==========================================

	return 0;
}

输出结果:

->正在加载点云...
->正在估计平面...
平面方程为:
-0.00847471x + -0.879568y + -0.475697z + -1.16966 = 0

拟合结果:

在这里插入图片描述

以上是关于PCL随机采样一致性:RANSAC 平面拟合的主要内容,如果未能解决你的问题,请参考以下文章

PCL 平面拟合——RANSAC

PCL:RANSAC圆柱体拟合(详细注释,对新手友好!)

点云处理技术之PCL随机采样一致算法(Random sample consensus,RANSAC)

PCL:RANSAC 空间直线拟合

PCL:平面模型分割

PCL:多直线拟合(RANSAC)