PCL——从点云到网格(三)点云到Mesh
参考:
https://mp.weixin.qq.com/s/GFDWOudJ08In6jFyrZ7hhg
https://mp.weixin.qq.com/s/FfHkVY-lmlOSf4jKoZqjEA
通过之前的两篇文章,从得到点云,到对点云的下采样,去离群点。接着就是对点云的平滑,计算法线,最后生成Mesh。
点云平滑
平滑也是滤波的一种,让点云看起来稍微光滑一些。存在一些不规则数据,很难用前面提到过的统计分析等滤波方法消除,就需要平滑来处理和修复漏洞。
平滑操作在配准之后。
我使用的平滑的方法是重采样,实质上是移动最小二乘(MLS)。
主要的类是 pcl::MovingLeastSquares ,用它进行重采样操作。
参数啥的我其实还是不会调,还是用的别人的东西。
//重采样平滑点云
void SmoothPointcloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud_in, pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud_out)
{// 对点云重采样 std::cout<<"begin smooth: size " << cloud_in->size() << std::endl;pcl::search::KdTree<pcl::PointXYZRGB>::Ptr treeSampling(new pcl::search::KdTree<pcl::PointXYZRGB>); // 创建用于最近邻搜索的KD-Treepcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB> mls; // 定义最小二乘实现的对象mlsmls.setSearchMethod(treeSampling); // 设置KD-Tree作为搜索方法mls.setComputeNormals(false); //设置在最小二乘计算中是否需要存储计算的法线mls.setInputCloud(cloud_in); //设置待处理点云mls.setPolynomialOrder(2); // 拟合2阶多项式拟合mls.setPolynomialFit(false); // 设置为false可以 加速 smoothmls.setSearchRadius(0.05); // 单位m.设置用于拟合的K近邻半径mls.process(*cloud_out); //输出std::cout << "success smooth, size: " << cloud_out->size() << std::endl;}
KdTree我理解为方便管理点云中的点的一个结构,通过这个二叉树可以方便的找到我们所要的某个点。
KDTree参考: https://blog.csdn.net/fandq1223/article/details/53176098
setSearchRadius 搜索某个点周围5cm处的所有点,用二阶多项式拟合这些点。
平滑点云之后,开始下一步操作:
点云的法向量计算
由于计算点云的法向量而不是Mesh的法向量,因此比较麻烦。目前是两种重建算法,使用曲面重建的方法 和 使用近似值直接从点云中推断法线。
由于刚刚接触,参考资料中使用的是后一种方法,从该点最近邻计算的协方差矩阵的特征向量和特征值的分析,直接调用PCL封装好的函数即可。
pcl::NormalEstimation 估计法线的类
//计算法线
pcl::PointCloud<pcl::Normal>::Ptr CalculateNormal(pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud_in)
{// 法线估计pcl::StopWatch time;std::cout << "begin compute normal.... " << std::endl;pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> normalEstimation; //创建法线估计的对象normalEstimation.setInputCloud(cloud_in); //输入点云pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>); // 创建用于最近邻搜索的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 << "success compute normal,time(s): "<< time.getTimeSeconds() << std::endl;return normals;
}
这个函数是我写的函数,接受输入点云Ptr,返回法向量Ptr。normalEstimation.setKSearch(10) 这个参数对于法向量的估计影响还是比较大的,不能太大,也不能太小。
之后在计算好了法向量,就可以得到Mesh了。
贪心三角化算法得到Mesh
点云构成三角网格的流程。Mesh存储的信息为:顶点索引,边索引,面片索引。
目前网格生成分为两大类算法,插值法(通过原始数据点得到)和逼近法(用分片线性曲面逼近原始点集)。
pcl::GreedyProjectionTriangulation 贪心三角化算法计算Mesh,使用贪心投影三角化对有向点云进行三角化,它更适用于采样点云来自表面连续光滑的曲面,并且点云的密度变化比较均匀的情况。
流程(参考资料上很详细,PCL都封装好了):
- 先将点云根据法向量投影到某个二维平面上(为某一个样本三角面片);
- 对该平面内的投影后的点云做三角化(基于Delaunay三角剖分 )得到投影后的点的拓扑连接关系
- 得到拓扑连接之后各三维点的拓扑链接就出来了,得到了Mesh。
在平滑之后要处理掉 InvalidPoints 否则无法进行Mesh。
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/mls.h> //最小二乘 重采样平滑
#include <pcl/surface/poisson.h> //泊松重建
#include <pcl/geometry/polygon_mesh.h> //MESH
#include <pcl/surface/gp3.h> //贪心三角形//贪心三角化算法得到Mesh
pcl::PolygonMesh greedy_traingle_GenerateMesh(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_in, pcl::PointCloud<pcl::Normal>::Ptr normals)
{ pcl::StopWatch time;std::cout << "begin mesh..." << std::endl;pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZRGB>());SmoothPointcloud(cloud_in, cloud_out);EraseInvalidPoints(cloud_out);// 将点云位姿、颜色、法线信息连接到一起pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);pcl::concatenateFields(*cloud_in, *normals, *cloud_with_normals);//定义搜索树对象pcl::search::KdTree<pcl::PointXYZRGBNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGBNormal>);tree2->setInputCloud(cloud_with_normals);// 三角化pcl::GreedyProjectionTriangulation<pcl::PointXYZRGBNormal> 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); //重建提取三角化cloud_with_normals->width = cloud_with_normals->height = 0;std::cout << "success traingles, time(s) "<< time.getTimeSeconds() << std::endl;return triangles;
}
pcl::concatenateFields 的两个输入点云的大小一定要是一样的(点云个数),否则在处理的时候会报错。
点云到Mesh的流程大概就是:
下采样,滤波,平滑,法向量,Mesh
Mesh的效果和点云质量相关。我这里用的是RGB点云,Mesh里面就自带颜色的,因此没有Texture也可以看到颜色(否则还得自己做Texture,UV啥的都不会),如果要导入Unity,就得改一下输出格式和Shader。
这些流程不是最好的,可以做优化,等我学的多一些了。。。应该会做一下吧
PCL——从点云到网格(三)点云到Mesh相关推荐
- 深入小程序云开发之云函数 第三部分 云函数经验谈
以下是我总结的要点: A. 云函数的文件组织 开发环境: 1. 假如你的项目根目录下project.config.json配置了: "cloudfunctionRoot": &qu ...
- 阿里云进阶课程三——基于云服务器构建微信公众号管理系统
基于阿里云服务器构建微信公众号管理系统 准备工作 阿里云服务器镜像配置 FileZilla和终端工具安装 下载微擎压缩包 微擎的安装和配置 在云服务器上配置微擎文件 设置数据库信息 云服务器上安装微擎 ...
- 阿里云服务网格ASM集成SLS告警
简介:随着微服务的流行,微服务的架构也在不断的发展演进,Spring Cloud 与 Dubbo为代表的微服务开发框架也得到了普及和落地:在云原生时代,无侵入的服务网格(Service Mesh)开始 ...
- 云上“两地三中心”,中小企业都用得起的多保险灾备方案
在云时代,大部分中小型企业都奔跑在云上或是服务器托管公司.任何规模的数据中心服务中断都会让你的企业踩雷.据统计,80%的数据中心服务中断都是由服务器硬件造成的. 据万博智云不完全统计: 2021年3月 ...
- PCL点云使用贪婪三角化进行曲面重构
一.PCL点云平滑和法线估计 题目:https://mp.weixin.qq.com/s?__biz=MzIxOTczOTM4NA==&mid=2247486705&idx=1& ...
- PCL——从点云到网格(一)利用OpenNI2和深度相机生成点云
最近做毕设,学习了一下PCL的使用(C++).这几篇博客就记录一下自己做毕设的时候利用深度相机得到点云,最后生成Mesh的过程.效果应该不是最好的,但是先把流程记录下来,自己下次看的时候就知道大体流程 ...
- PCL点云处理之点云质心的三种计算方法(七十六)
PCL点云处理之点云质心的三种计算方法(七十六) 一.质心? 二.算法实验 1.代码 2.效果 一.质心? 就计算某块点云坐标均值,可以调库,也可以自己算,easy 二.算法实验 1.代码 代码如下( ...
- 从零开始一起学习SLAM | 点云到网格的进化
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 小白:师兄,师兄,你在<从零开始一起学习SLAM | 给点云 ...
- CloudCompare:三维点云(网格)编辑和处理工具
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 本文来源:公众号@点云PCL,原文:CloudCompare的介绍 CloudCompare是一个三维 ...
最新文章
- Linux统计行数命令wc(转)
- javascript 通过键获取值
- git 撤销提交的文件
- 高层管理者对于大数据的6个误解
- 网站程序员的程序员成长之路大概分几个阶段 和未来的发展
- HDU-3729 二分匹配 匈牙利算法
- Mybatis源码阅读(一):Mybatis初始化1.1 解析properties、settings
- e0312 不存在用户定义的_更加灵活的参数校验,Spring-boot自定义参数校验注解
- 本周论文推荐 -- 对抗生成网络、知识图谱补全、对话系统、文本生成
- We Recommend a Singular Value Decomposition
- Combobox MVVM绑定并设置选中
- Java设计模式系列之迭代器模式
- DropDownList的AppendDataBoundItems属性
- VS2013过期激活,VS2013激活,vs2013序列号,VS2013密钥,VS013产品密匙
- 可以放游戏网站云服务器,游戏网站选择哪个云服务器好?游戏服务器配置方案?...
- 【自动驾驶】华为车BU介绍(2021-11-23晚直播记录)
- 保存下载图片(taro h5)
- 2008年8月6号,晴,今天天气已经变热了。少壮不努力,老大徒悲伤。 —— 汉乐府古辞《长歌行》
- 北科计算机研究生导师推荐,北京科技大学计算机与通信工程学院-【喜报】我院班晓娟老师荣获第三届“研师亦友——我最喜爱的导师”称号...
- mysql直方图_MySQL · 特性分析 · 直方图的实现与分析