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

(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. Centos7源代码安装freeswitch和启动freeswitch

    centos7下安装freeswitch版本:1.6. 1.下载源代码: 进入目录 cd /usr/local/src 克隆原代码 git clone -b v1.6 https://freeswit ...

  2. go 从入门到精通(二)基本数据类型和操作符

    一.文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置别名 下面是保留关键字: ...

  3. Atitit 转移特效attilax总结

    Atitit 转移特效attilax总结 总结一般从按钮,转移到大点的方框上回比较好看点.. <!--jq ui--> <style type="text/css" ...

  4. 关于generate用法的总结

    Abtract generate语句允许细化时间(Elaboration-time)的选取或者某些语句的重复.这些语句可以包括模块实例引用的语句.连续赋值语句.always语句.initial语句和门 ...

  5. CSS中Zen Coding

    值别名 有几个常用的别名: p → % e → em x → ex 可以用这些别名来代替完整的单位: w100p → width: 100% m10p30e5x → margin: 10% 30em ...

  6. python2/3 中删除字典中value为空的键值对方法

    python2 data_info = { 'account': 1, 'remark': 2, 'sort': '', 'weight': '', } for key in data_info.ke ...

  7. vue2.0的contextmenu右键菜单

    1.事情对象 <!DOCTYPE html> <html> <head> <title></title> <meta charset= ...

  8. js设置滚动条定位到所属容器的最底部

    $('.help-gundongtiao').scrollTop($('.help-gundongtiao')[0].scrollHeight);

  9. ffmpeg抓屏输出的设置

    之前做windows下抓屏输出时使用ffmpeg.exe作为抓屏输出测试,命令行如下: ffmpeg -f gdigrab -i "desktop" -r 25 -vcodec m ...

  10. c++之五谷杂粮---1

    1.  位运算符,如果运算对象是带符号的且它的值为负,那么位运算符如何处理运算对象的“符号位”依赖于机器.此时左移操作可能会改变符号位的值,因此是一种UB. Best Practices: 关于符号位 ...