点云处理
概要
记录一下点云处理的细节、算法和坑
环境配置
先后在Wsl2和虚拟机里都尝试了配置
Wsl2的问题是性能拉跨,一可视化就严重卡死
虚拟机的好处是可以直接用apt安装PCL,问题是我的Ubuntu镜像似乎自带了VTK9.1,而apt默认下载PCL1.12,两者会在可视化点云时发生冲突,在窗口出现的一瞬间段错误
遂又自行拉源代码编译安装,奈何make过程中不是虚拟机内存不够就是虚拟机存储空间不够
最后干脆Docker拉取了pointcloudlibrary/env:22.04这个镜像(虽然不知道这个镜像里为什么没有安装pcl库,还是得自己装),加上VcXsrv作为XServer,终于解决了环境配置
由于pcl_viewer无法可视化.ply文件(Mesh化后的文件),还安装了一个Python Open3D环境用来可视化Mesh化后的点云,在第三方库这方面,自带包管理器的语言确实方便,pip一下就完事
去噪
降采样
由于每一个pcd文件都有几百兆,基本每个pcd文件里都有千万个点,笔记本上跑一个半径滤波都跑不动
一开始以为是电脑问题,等了很久还是跑不出来
然后发现有个东西叫降采样,类似于主动降低图片分辨率的原理
pcl库里的VoxelGrid可以做这件事,原理是可以指定某个大小的三维立方体,然后在每个三位立方体内部求取所有点云的重心,用这个重心点表示立方体
1 | [pcl::VoxelGrid::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow. |
用pcl的VoxelGrid的时候可能会报这个错,然后降采样会无效,原因是当前设置的三维立方体太小,而点又太多,导致索引溢出
Open3D就没这个问题,最后我在pcl里设了$5\times 5\times 5$的立方体,Open3D设了$2\times 2\times 2$
1 | root@447194bfa0c9:/pcd_files/build# ./denoise_pcl ../test.pcd ../denoised.pcd |
上面是我在运行pcl程序的时候打印的日志,降采样缩小了将近十分之一的数据量,降采样完以后连可视化也会流畅许多
朴素去噪
可视化了几个钢板的pcd,主要的噪声应该是激光扫描的时候把旁边的不知道是桌子还是垫子也给扫进去了,离群点倒不是很多
目前看了几个去噪算法,感觉经典算法大部分是针对离群点的
直通滤波是对X、Y、Z轴做简单约束的滤波,原理很简单,就是在三个轴上进行截断,PassThrough能做这个事
于是我目前通过不断可视化不断调参调出了一个能比较好针对这些实验室钢板的约束,能做到去得只剩钢板和部分离群点
对于剩下来的离群点,主要用了半径滤波,通过判定指定半径内的点数量是否满足阈值来判定是否为离群点,进而进行剔除,RadiusOutlierRemoval能做这件事
1 | root@447194bfa0c9:/pcd_files/build# ./denoise_pcl ../test.pcd ../denoised.pcd |
目前的问题
目前基于PassThrough和RadiusOutlierRemoval的滤波只能处理实验室数据里钢板的点云
我看实验室里还有一些奇怪的pcd文件,可视化出来好像不是钢板,但也看不出是什么东西
可能最好的方法还是应该利用深度学习进行点云去噪,尤其是这种离群点不多的点云数据,后续我会尝试
似乎还有一个叫RANSAC平面拟合的方法,可以从点云里分割出主要平面,听上去也很适合提取钢板
Mesh化
一开始用了一个基于解泊松方程的表面重建方法,步骤是先估计每个点的法线方向(可指定搜索半径和考虑的最大邻居数来平滑法线估计)
然后一致化法线方向,最后解泊松方程生成网络
于是又尝试了贪心三角化算法
原理是根据法向量将点云投影到某个二维平面上
然后在二维平面上做Delaunay三角剖分(上次看到你还是ACM,好亲切)得到投影后的点的拓扑连接关系
将得到的拓扑关系应用到三维点