PCL Ransac 点云平面拟合 将三维不平整表面投影到一个平面 C++代码

时间:2024-04-08 21:31:22

参考链接(投影):https://blog.csdn.net/soaryy/article/details/82884691

参考链接(Ransac拟合):https://blog.csdn.net/weixin_41758695/article/details/85322304

利用开源的点云库PCL,使用VS2015完成的C++代码,测试文件(.obj)已经在本站(csdn)上传资源,供大家交流,如有问题欢迎多提宝贵意见

对于不平整表面,利用ransac平面拟合,然后将三维不平整表面(或者曲面)近似为一个平面,并将表面上的点投影到该平面,并且显示出来,如图所示,白色为原始点云,绿色为拟合的平面

PCL Ransac 点云平面拟合 将三维不平整表面投影到一个平面 C++代码

代码如下

#define _CRT_SECURE_NO_WARNINGS
#include <glut.h>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <iostream>
#include <string>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/obj_io.h>
#include <pcl/PolygonMesh.h>
#include <pcl/point_cloud.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <cstdlib>
#include <vector>

using namespace pcl;
using namespace std;


int main()
{   //--------------------- Input path ----------------------------------------------
	pcl::PolygonMesh mesh;
	pcl::io::loadPolygonFile(".\\Original.obj", mesh);

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::fromPCLPointCloud2(mesh.cloud, *cloud);

	//--------------------------- Plane ---------------------------------

	pcl::SACSegmentation<pcl::PointXYZ> sac;
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);

	sac.setInputCloud(cloud);
	sac.setMethodType(pcl::SAC_RANSAC);
	sac.setModelType(pcl::SACMODEL_PLANE);
	sac.setDistanceThreshold(15);                  //Distance need to be adjusted according to the obj
	sac.setMaxIterations(100);
	sac.setProbability(0.95); 
	sac.segment(*inliers, *coefficients);

	boost::shared_ptr<pcl::visualization::PCLVisualizer> view(new pcl::visualization::PCLVisualizer);
	view->addPointCloud(cloud);

	//Plane Model: ax+by+cz+d=0; saved in *coefficients

	float a, b, c, d;
	a = coefficients->values[0];
	b = coefficients->values[1];
	c = coefficients->values[2];
	d = coefficients->values[3];

	int i, j, k;
	int size = cloud->size();
	//------------------------ Projection ------------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_proj(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointXYZ point;
	for (i = 0; i<size; i++)
	{
		float x, y, z;
		x = cloud->at(i).x;
		y = cloud->at(i).y;
		z = cloud->at(i).z;

		point.x = ((b*b + c*c)*x - a*(b*y + c*z + d)) / (a*a + b*b + c*c);
		point.y = ((a*a + c*c)*y - b*(a*x + c*z + d)) / (a*a + b*b + c*c);
		point.z = ((b*b + a*a)*z - c*(a*x + b*y + d)) / (a*a + b*b + c*c);
		cloud_proj->push_back(point);
	}

	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handler(cloud_proj, 50, 230, 12);
	view->addPointCloud(cloud_proj, color_handler, "CH");
	view->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "CH");

	while (!view->wasStopped())
	{
		view->spinOnce(100);
	}

	system("pause");
	return 0;
}