在测量较小的数据时会产生一些误差,这些误差所造成的不规则数据如果直接拿来曲面重建的话,会使得重建的曲面不光滑或者有漏洞,可以采用对数据重采样来解决这样问题,通过对周围的数据点进行高阶多项式插值来重建表面缺少的部分,

(1)用最小二乘法对点云进行平滑处理

新建文件resampling.cpp

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h> //kd-tree搜索对象的类定义的头文件
#include <pcl/surface/mls.h> //最小二乘法平滑处理类定义头文件 int
main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
pcl::io::loadPCDFile ("bun0.pcd", *cloud); // 创建 KD-Tree
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); // Output has the PointNormal type in order to store the normals calculated by MLS
pcl::PointCloud<pcl::PointNormal> mls_points; // 定义最小二乘实现的对象mls
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls; mls.setComputeNormals (true); //设置在最小二乘计算中需要进行法线估计 // Set parameters
mls.setInputCloud (cloud);
mls.setPolynomialFit (true);
mls.setSearchMethod (tree);
mls.setSearchRadius (0.03); // Reconstruct
mls.process (mls_points); // Save output
pcl::io::savePCDFile ("bun0-mls.pcd", mls_points);
}

结果对比

    

(2)在平面模型上提取凸(凹)多边形

本例子先从点云中提取平面模型,再通过该估计的平面模型系数从滤波后的点云投影一组点集形成点云,最后为投影后的点云计算其对应的二维凸多边形

#include <pcl/ModelCoefficients.h>           //采样一致性模型相关类头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h> //滤波相关类头文件
#include <pcl/segmentation/sac_segmentation.h> //基于采样一致性分割类定义的头文件
#include <pcl/surface/concave_hull.h> //创建凹多边形类定义头文件 int
main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>),
cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>),
cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader; reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
// 建立过滤器消除杂散的NaN
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud); //设置输入点云
pass.setFilterFieldName ("z"); //设置分割字段为z坐标
pass.setFilterLimits (, 1.1); //设置分割阀值为(0, 1.1)
pass.filter (*cloud_filtered);
std::cerr << "PointCloud after filtering has: "
<< cloud_filtered->points.size () << " data points." << std::endl; pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers (new pcl::PointIndices); //inliers存储分割后的点云
// 创建分割对象
pcl::SACSegmentation<pcl::PointXYZ> seg;
// 设置优化系数,该参数为可选参数
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setDistanceThreshold (0.01); seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
std::cerr << "PointCloud after segmentation has: "
<< inliers->indices.size () << " inliers." << std::endl; // Project the model inliers
pcl::ProjectInliers<pcl::PointXYZ> proj;//点云投影滤波模型
proj.setModelType (pcl::SACMODEL_PLANE); //设置投影模型
proj.setIndices (inliers);
proj.setInputCloud (cloud_filtered);
proj.setModelCoefficients (coefficients); //将估计得到的平面coefficients参数设置为投影平面模型系数
proj.filter (*cloud_projected); //得到投影后的点云
std::cerr << "PointCloud after projection has: "
<< cloud_projected->points.size () << " data points." << std::endl; // 存储提取多边形上的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConcaveHull<pcl::PointXYZ> chull; //创建多边形提取对象
chull.setInputCloud (cloud_projected); //设置输入点云为提取后点云
chull.setAlpha (0.1);
chull.reconstruct (*cloud_hull); //创建提取创建凹多边形 std::cerr << "Concave hull has: " << cloud_hull->points.size ()
<< " data points." << std::endl; pcl::PCDWriter writer;
writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false); return ();
}

实验结果

 

(3)无序点云的快速三角化

使用贪婪投影三角化算法对有向点云进行三角化,

具体方法是:

(1)先将有向点云投影到某一局部二维坐标平面内

(2)在坐标平面内进行平面内的三角化

(3)根据平面内三位点的拓扑连接关系获得一个三角网格曲面模型.

贪婪投影三角化算法原理:

是处理一系列可以使网格“生长扩大”的点(边缘点)延伸这些点直到所有符合几何正确性和拓扑正确性的点都被连上,该算法可以用来处理来自一个或者多个扫描仪扫描到得到并且有多个连接处的散乱点云但是算法也是有很大的局限性,它更适用于采样点云来自表面连续光滑的曲面且点云的密度变化比较均匀的情况

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h> //贪婪投影三角化算法 int
main (int argc, char** argv)
{
// 将一个XYZ点类型的PCD文件打开并存储到对象中
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCLPointCloud2 cloud_blob;
pcl::io::loadPCDFile ("bun0.pcd", cloud_blob);
pcl::fromPCLPointCloud2 (cloud_blob, *cloud);
//* the data should be available in cloud // Normal estimation*
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n; //法线估计对象
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>); //存储估计的法线
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); //定义kd树指针
tree->setInputCloud (cloud);   ///用cloud构建tree对象
n.setInputCloud (cloud);
n.setSearchMethod (tree);
n.setKSearch ();
n.compute (*normals);       ////估计法线存储到其中
//* normals should not contain the point normals + surface curvatures // Concatenate the XYZ and normal fields*
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); //连接字段
//* cloud_with_normals = cloud + normals //定义搜索树对象
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud (cloud_with_normals); //点云构建搜索树 // Initialize objects
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3; //定义三角化对象
pcl::PolygonMesh triangles; //存储最终三角化的网络模型 // Set the maximum distance between connected points (maximum edge length)
gp3.setSearchRadius (0.025); //设置连接点之间的最大距离,(即是三角形最大边长) // 设置各参数值
gp3.setMu (2.5); //设置被样本点搜索其近邻点的最远距离为2.5,为了使用点云密度的变化
gp3.setMaximumNearestNeighbors (); //设置样本点可搜索的邻域个数
gp3.setMaximumSurfaceAngle(M_PI/); // 设置某点法线方向偏离样本点法线的最大角度45
gp3.setMinimumAngle(M_PI/); // 设置三角化后得到的三角形内角的最小的角度为10
gp3.setMaximumAngle(*M_PI/); // 设置三角化后得到的三角形内角的最大角度为120
gp3.setNormalConsistency(false); //设置该参数保证法线朝向一致 // Get result
gp3.setInputCloud (cloud_with_normals); //设置输入点云为有向点云
gp3.setSearchMethod (tree2); //设置搜索方式
gp3.reconstruct (triangles); //重建提取三角化 // 附加顶点信息
std::vector<int> parts = gp3.getPartIDs();
std::vector<int> states = gp3.getPointStates(); // Finish
return ();
}

首先看一下原来的PCD可视化文件

对其进行三角化可视化的结果是

效果还是很明显的阿

微信公众号号可扫描二维码一起共同学习交流

PCL点云曲面重建(1)的更多相关文章

  1. PCL点云库:ICP算法

    ICP(Iterative Closest Point迭代最近点)算法是一种点集对点集配准方法.在VTK.PCL.MRPT.MeshLab等C++库或软件中都有实现,可以参见维基百科中的ICP Alg ...

  2. PCL中点云数据格式之间的转化

    (1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别 pcl::PointXYZ::PointXYZ ...

  3. PCL点云库中的坐标系(CoordinateSystem)

    博客转载自:https://blog.csdn.net/qq_33624918/article/details/80488590 引言 世上本没有坐标系,用的人多了,便定义了坐标系统用来定位.地理坐标 ...

  4. Windows下安装PCL点云库

    原文链接:http://blog.csdn.net/u012337034/article/details/38270109 简介:         在Windows下安装PCL点云库的方法大概有两种: ...

  5. Windows 8 64位系统 在VS2010 32位软件上 搭建 PCL点云库 开发环境

    Windows 8 64位系统 在VS2010 32位软件上 搭建 PCL点云库 开发环境 下载PCL For windows 软件包 到这个网站下载PCL-All-In-One Installer: ...

  6. PCL学习之:将超声数据按照PCL点云方式发布出去

    前言:基于2D激光雷达的机器人,想让它跑自动导航,众所周知有2个比较明显的缺陷,1,那就是普通的激光雷达无法对玻璃或是镜面物体有反映; 2,机器人避障时只能对某一个平面的物体有反映,超过或者低于这个平 ...

  7. PCL点云分割(1)

    点云分割是根据空间,几何和纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征,点云的有效分割往往是许多应用的前提,例如逆向工作,CAD领域对零件的不同扫描表面进行分割,然后才能更好的进行空洞 ...

  8. PCL点云特征描述与提取(1)

    3D点云特征描述与提取是点云信息处理中最基础也是最关键的一部分,点云的识别.分割,重采样,配准曲面重建等处理大部分算法,都严重依赖特征描述与提取的结果.从尺度上来分,一般分为局部特征的描述和全局特征的 ...

  9. PCL点云库(Point Cloud Library)简介

    博客转载自:http://www.pclcn.org/study/shownews.php?lang=cn&id=29 什么是PCL PCL(Point Cloud Library)是在吸收了 ...

随机推荐

  1. django -- 为model 指定数据库名

    一.为model指定数据库名: django自己实现的ORM中.如果要指定一个model的表名是通过Meta类来实现的. from django.db import models # Create y ...

  2. 从github下载某个git库的4种方法[zz]

    以gerrit-trigger-plugin为例,下面的链接都是从相应页面上直接拷贝的. 法一:不用github的账号,打开这个库在github上的主页,运行下面命令即可 read only 运行命令 ...

  3. 微信小程序 confirm(删除提示)提示框,询问框,小程序操作成功提示后跳转

    微信小程序删除处理 没有 confrim 那怎么实现这个效果呢 可以使用小程序里的模态框 代码: wx.showModal({ title: '提示', content: '确定要删除吗?', suc ...

  4. metaspolit 命令大全

    一.msfconsole相关命令 二.database 三.autopwn自动化攻击工具 四.metaspolit常见渗透命令大全

  5. hdu-2045 递归

    #include <cstdio> #include <iostream> using namespace std; long long a[55] = {0,3,6}; lo ...

  6. hdoj 1874 畅通project续【SPFA】

    畅通project续 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Su ...

  7. Viewpager 的相关总结

    1.修改切换item的时间 public class FixedSpeedScroller extends Scroller { ; public FixedSpeedScroller(Context ...

  8. Vuex 实践讲解

    state 用来数据共享数据存储 mutation 用来注册改变数据状态 getters 用来对共享数据进行过滤操作 action 解决异步改变共享数据 这个四大特征就是核心,如何用怎么用 接下来还是 ...

  9. Android学习之Design Support Library中TextInputLayout的使用

    今天学习了一个Android Design Support Library 中的TextInputLayout控件,感觉还不错,较之以往的Editetxt,多了几分灵活性,使用也非常easy,故此给大 ...

  10. nginx配置长连接

    http { keepalive_timeout 20; --长连接timeout keepalive_requests 8192; --每个连接最大请求数 } events { worker_con ...