参考:https://mp.weixin.qq.com/s/FfHkVY-lmlOSf4jKoZqjEA

什么是网格

网格主要用于计算机图形学中,有三角、四角网格等很多种。
计算机图形学中的网格处理绝大部分都是基于三角网格的,三角网格在图形学和三维建模中使用的非常广泛,用来模拟复杂物体的表面,如建筑、车辆、动物等,你看下图中的兔子、球等模型都是基于三角网格的

三角形表示网格也叫三角剖分。它有如下几个优点:

  • 三角网格稳定性强。

  • 三角网格比较简单(主要原因),实际上三角网格是最简单的网格类型之一,可以非常方便并且快速生成,在非结构化网格中最常见。而且相对于一般多边形网格,许多操作对三角网格更容易。

3、有助于恢复模型的表面细节。

网格生成算法要求

网格生成算法有如下的能力:

  • 对点云噪声有一定的冗余度。

  • 能够重建出曲率变化比较大的曲面。

  • 能够处理大数据量,算法时间和空间复杂度不会太高。

  • 重建出的网格中包含尽可能少的异常三角片,比如三角片交错在一起、表面法向量不连续或不一致、同一个位置附近出现多层三角片等。

目前点云进行网格生成一般分为两大类方法:

  • 插值法。顾名思义,也就是重建的曲面都是通过原始的数据点得到的

  • 逼近法。用分片线性曲面或其他曲面来逼近原始数据点,得到的重建曲面是原始点集的一个逼近。

点云贪心三角化原理

主要介绍一种比较简单的贪心三角化法(对应的类名:pcl::GreedyProjectionTriangulation),也就是使用贪心投影三角化算法对有向点云进行三角化。
优点:可以用来处理来自一个或者多个设备扫描到得到、并且有多个连接处的散乱点云。但是也是有很大的局限性,它更适用于采样点云来自表面连续光滑的曲面,并且点云的密度变化比较均匀的情况

贪心投影三角化的大致流程是这样的:

  • 先将点云通过法线投影到某一二维坐标平面内

  • 然后对投影得到的点云做平面内的三角化,从而得到各点的拓扑连接关系。平面三角化的过程中用到了基于Delaunay三角剖分 的空间区域增长算法

  • 最后根据平面内投影点的拓扑连接关系确定各原始三维点间的拓扑连接,所得三角网格即为重建得到的曲面模型

Delaunay 三角剖分简介

对数值分析以及图形学来说,三角剖分(Triangulation)都是极为重要的一项预处理技术。而Delaunay 三角剖分是一种常用的三角剖分的方法,关于点集的很多种几何图都和Delaunay三角剖分相关,如Voronoi图。

Delaunay 三角剖分的有两个优点:

  • 最大化最小角,“最接近于规则化的“的三角网。

  • 唯一性(任意四点不能共圆)

定义:点集?的Delaunay三角剖分满足满足任意?内任意一个点都不在? 内任意一 个三角面片的外接圆内。

看下面的图就是满足了Delaunay条件,所有三角形的顶点是不是都不在其他三角形的外接圆内?

更简便的方法。你看下面最左图,观察具有公共边缘BD的两个三角形ABD和BCD,如果角度α和γ之和小于或等于180°,则三角形满足Delaunay条件。按照这个标准下图左、中都不满足Delaunay条件,只有右图满足。

贪心投影三角化

// 将点云位姿、颜色、法线信息连接到一起
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud_smoothed, *normals, *cloud_with_normals);//定义搜索树对象
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud(cloud_with_normals);// 三角化
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;   // 定义三角化对象
pcl::PolygonMesh triangles; //存储最终三角化的网络模型// 设置三角化参数
gp3.setSearchRadius(0.1);  //设置搜索时的半径,也就是KNN的球半径
gp3.setMu (2.5);  //设置样本点搜索其近邻点的最远距离为2.5倍(典型值2.5-3),这样使得算法自适应点云密度的变化
gp3.setMaximumNearestNeighbors (100);    //设置样本点最多可搜索的邻域个数,典型值是50-100gp3.setMinimumAngle(M_PI/18); // 设置三角化后得到的三角形内角的最小的角度为10°
gp3.setMaximumAngle(2*M_PI/3); // 设置三角化后得到的三角形内角的最大角度为120°gp3.setMaximumSurfaceAngle(M_PI/4); // 设置某点法线方向偏离样本点法线的最大角度45°,如果超过,连接时不考虑该点
gp3.setNormalConsistency(false);  //设置该参数为true保证法线朝向一致,设置为false的话不会进行法线一致性检查gp3.setInputCloud (cloud_with_normals);     //设置输入点云为有向点云
gp3.setSearchMethod (tree2);   //设置搜索方式
gp3.reconstruct (triangles);  //重建提取三角化

实践

操作步骤:下采样和滤波、重采样平滑、法线计算,贪心投影网格化

#include <pcl/point_types.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/surface/mls.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/surface/poisson.h>
typedef pcl::PointXYZ PointT;int main(int argc, char** argv)
{// Load input filepcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);pcl::PointCloud<PointT>::Ptr cloud_downSampled(new pcl::PointCloud<PointT>);pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>);pcl::PointCloud<PointT>::Ptr cloud_smoothed(new pcl::PointCloud<PointT>);if (pcl::io::loadPCDFile("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/fusedCloud.pcd", *cloud) == -1){cout << "点云数据读取失败!" << endl;}std::cout << "Orginal points number: " << cloud->points.size() << std::endl;// ----------------------开始你的代码--------------------------//// 请参考之前文章中点云下采样,滤波、平滑等内容,以及PCL官网实现以下功能。代码不难。// 下采样pcl::VoxelGrid<PointT> downSampled;  //创建滤波对象downSampled.setInputCloud (cloud);            //设置需要过滤的点云给滤波对象downSampled.setLeafSize (0.01f, 0.01f, 0.01f);  //设置滤波时创建的体素体积为1cm的立方体downSampled.filter (*cloud_downSampled);           //执行滤波处理,存储输出pcl::io::savePCDFile ("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/downsampledPC.pcd", *cloud_downSampled);// 统计滤波pcl::StatisticalOutlierRemoval<PointT> statisOutlierRemoval;       //创建滤波器对象statisOutlierRemoval.setInputCloud (cloud_downSampled);            //设置待滤波的点云statisOutlierRemoval.setMeanK (50);                                //设置在进行统计时考虑查询点临近点数statisOutlierRemoval.setStddevMulThresh (3.0);                     //设置判断是否为离群点的阀值:均值+1.0*标准差statisOutlierRemoval.filter (*cloud_filtered);                     //滤波结果存储到cloud_filteredpcl::io::savePCDFile ("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/filteredPC.pcd", *cloud_filtered);// 对点云重采样  pcl::search::KdTree<PointT>::Ptr treeSampling (new pcl::search::KdTree<PointT>);// 创建用于最近邻搜索的KD-Treepcl::PointCloud<PointT> mls_point;    //输出MLSpcl::MovingLeastSquares<PointT,PointT> mls; // 定义最小二乘实现的对象mlsmls.setComputeNormals(false);  //设置在最小二乘计算中是否需要存储计算的法线mls.setInputCloud(cloud_filtered);         //设置待处理点云mls.setPolynomialOrder(2);            // 拟合2阶多项式拟合mls.setPolynomialFit(false);     // 设置为false可以 加速 smoothmls.setSearchMethod(treeSampling);         // 设置KD-Tree作为搜索方法mls.setSearchRadius(0.05);           // 单位m.设置用于拟合的K近邻半径mls.process(mls_point);                 //输出// 输出重采样结果cloud_smoothed = mls_point.makeShared();std::cout<<"cloud_smoothed: "<<cloud_smoothed->size() <<std::endl;//save cloud_smoothedpcl::io::savePCDFileASCII("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/cloud_smoothed.pcd",*cloud_smoothed);// 法线估计pcl::NormalEstimation<PointT,pcl::Normal> normalEstimation;             //创建法线估计的对象normalEstimation.setInputCloud(cloud_smoothed);                         //输入点云pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);// 创建用于最近邻搜索的KD-TreenormalEstimation.setSearchMethod(tree);pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); // 定义输出的点云法线// K近邻确定方法,使用k个最近点,或者确定一个以r为半径的圆内的点集来确定都可以,两者选1即可normalEstimation.setKSearch(10);// 使用当前点周围最近的10个点//normalEstimation.setRadiusSearch(0.03);            //对于每一个点都用半径为3cm的近邻搜索方式normalEstimation.compute(*normals);               //计算法线// 输出法线std::cout<<"normals: "<<normals->size()<<", "<<"normals fields: "<<pcl::getFieldsList(*normals)<<std::endl;pcl::io::savePCDFileASCII("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/normals.pcd",*normals);// 将点云位姿、颜色、法线信息连接到一起pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields(*cloud_smoothed, *normals, *cloud_with_normals);pcl::io::savePCDFileASCII("/home/xiaohu/learn_SLAM/zuoye15/作业15-点云平滑及法线估计及显示/data/cloud_with_normals.pcd",*cloud_with_normals);// 贪心投影三角化//定义搜索树对象pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);tree2->setInputCloud(cloud_with_normals);// 三角化pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;   // 定义三角化对象pcl::PolygonMesh triangles; //存储最终三角化的网络模型// 设置三角化参数gp3.setSearchRadius(0.1);  //设置搜索时的半径,也就是KNN的球半径gp3.setMu (2.5);  //设置样本点搜索其近邻点的最远距离为2.5倍(典型值2.5-3),这样使得算法自适应点云密度的变化gp3.setMaximumNearestNeighbors (100);    //设置样本点最多可搜索的邻域个数,典型值是50-100gp3.setMinimumAngle(M_PI/18); // 设置三角化后得到的三角形内角的最小的角度为10°gp3.setMaximumAngle(2*M_PI/3); // 设置三角化后得到的三角形内角的最大角度为120°gp3.setMaximumSurfaceAngle(M_PI/4); // 设置某点法线方向偏离样本点法线的最大角度45°,如果超过,连接时不考虑该点gp3.setNormalConsistency(false);  //设置该参数为true保证法线朝向一致,设置为false的话不会进行法线一致性检查gp3.setInputCloud (cloud_with_normals);     //设置输入点云为有向点云gp3.setSearchMethod (tree2);   //设置搜索方式gp3.reconstruct (triangles);  //重建提取三角化// 显示网格化结果boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer->setBackgroundColor(0, 0, 0);  //viewer->addPolygonMesh(triangles, "wangge");  //while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}return 1;
}

3D点云系列———pcl:点云网格化相关推荐

  1. 点云系列之点云数据格式的认识

    点云系列之点云数据格式的认识 文章目录 点云系列之点云数据格式的认识 一.常见的点云数据格式 二.格式的具体介绍 2.1 off格式 2.2PLY格式 2.1.1header的特别说明 2.1.2 带 ...

  2. 3D点云系列——pcl:点云平滑及法线估计

    通过重采样实现点云平滑 需要平滑的情况: 用RGB-D激光扫描仪等设备扫描物体,尤其是比较小的物体时,往往会有测量误差.这些误差所造成的不规则数据如果直接拿来曲面重建的话,会使得重建的曲面不光滑或者有 ...

  3. 阿里云系列——7.阿里云IIS系列详解(过程+通用+最新)

    网站部署之~阿里云系列汇总 http://www.cnblogs.com/dunitian/p/4958462.html 先讲IIS系列,Linux部署以后再继续讲 先打开主机管理平台,确认域名绑定 ...

  4. 3D点云系列———pcl:点云融合

    题目:将给定3帧(不连续)RGB-D相机拍摄的 RGB + depth 图像,以及他们之间的变换矩阵RGB-D图像转换为点云,并融合出最终的点云输出 pointCloudFusion.cpp #inc ...

  5. pcl点云处理基本步骤

    一.功能描述 本项目主要为计算机视觉方面的应用,可以实现障碍物或目标物体的检测.提取或识别,文章为项目基础步骤的描述,希望能够帮到一些不知从何下手的同学,也算是为了以后自己的复习吧.(因为项目不是自己 ...

  6. PCL入门系列 —— StatisticalOutlierRemoval 点云统计滤波

    PCL入门系列 -- StatisticalOutlierRemoval 点云统计滤波 前言 程序说明 输出结果 代码示例 总结 前言 随着工业自动化.智能化的不断推进,机器视觉(2D/3D)在工业领 ...

  7. 【点云系列】综述: Deep Learning for 3D Point Clouds: A Survey

    文章目录 起因 题目 摘要 1 简介 2 背景 2.1 数据集 2.2 衡量指标 3 3D形状分类 3.1基于多视角的方法 3.2基于体素的方法 3.3 基于点的方法 3.3.1逐点MLP网络 3.3 ...

  8. 3D点云系列(一)点云介绍

    点云数据简介 点云数据(point cloud data)是指在一个三维坐标系统中的一组向量的集合.扫描资料以点的形式记录,每一个点包含有三维坐标,有些可能含有颜色信息(RGB)或反射强度信息(Int ...

  9. 点云地图PCL转换成为八叉树地图octomap

    //TODO //完成离线点云地图到八叉树地图的转换 //进一步在线实时完成点云地图到八叉树地图的转换 转载自高翔的博客:SLAM拾萃(1):octomap *******************我是 ...

最新文章

  1. python爬虫教程下载-Python爬虫文件下载图文教程
  2. python变量和常量_python变量与常量内容:
  3. 力扣559. N 叉树的最大深度(JavaScript)
  4. CCNA认证(2)--网络互联基础
  5. Taro-library:Taro + Redux + 本地 Mock Server 示例项目
  6. Atitit.每周计划日程表 流程表 v9 r829.docx
  7. 一道经典的C++题,关于分钱的问题,适合新手阅读(黑客X档案论坛题目) [c#]...
  8. 考研政治---马克思主义基本原理概论---绪论
  9. oracle认证考试试题及答案,Oracle DBA认证考试存储管理试题及答案
  10. 《CSS菜鸟教程》学习
  11. werfault进程使用CPU率高
  12. Python数据分析-NumPy模块-选取数组元素
  13. 实验:GNS3中创建PC机与连接交换机实现互联互通
  14. 如何安装成英文版本的vmware
  15. dlink网络打印服务器如何修改ip地址,DLINK路由器如何更改登陆IP地址
  16. brpc搭建、编译和使用
  17. 辅助类GenericOptionsParser,Tool和ToolRunner
  18. python-东方财富网贴吧评论数据爬取
  19. Linux常用命令(4)-磁盘管理
  20. 纯小白通过服务器搭建yolov5环境训练coco数据集

热门文章

  1. appserv php5.3,Appserv2.5.10升级PHPfromversion5.2to5.3
  2. 华硕天选2安装win10专业版记录
  3. 怎么解决Win7看视频绿屏的问题?
  4. 基本命令 Linux操作系统与实训 CentOS 7.4 RHEL 7.4
  5. unity学习之环境光遮挡 (Ambient Occlusion)
  6. BTS环球俱乐部,去中心化价值回归第一站
  7. 用requests包爬取今日头条新闻标题
  8. 【科普】一文弄懂监督式学习、非监督式学习以及强化式学习
  9. python伪代码怎么写_word怎么写代码 word怎么写伪代码
  10. 架构师成长之路(5)--架构师具备的思维