参考链接(投影):https://blog.csdn.net/soaryy/article/details/82884691
参考链接(Ransac拟合):https://blog.csdn.net/weixin_41758695/article/details/85322304
利用开源的点云库PCL,使用VS2015完成的C++代码,测试文件(.obj)已经在本站(csdn)上传资源,供大家交流,如有问题欢迎多提宝贵意见
对于不平整表面,利用ransac平面拟合,然后将三维不平整表面(或者曲面)近似为一个平面,并将表面上的点投影到该平面,并且显示出来,如图所示,白色为原始点云,绿色为拟合的平面
代码如下
#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;
}