公众号致力于点云处理,SLAM,三维视觉,高精地图等领域相关内容的干货分享,欢迎各位加入,有兴趣的可联系dianyunpcl@163.com。未经作者允许请勿转载,欢迎各位同学积极分享和交流。
什么是LOD(Level of Detail)?
LOD(Level of Detail)是一种在计算机图形学中用于优化渲染性能的技术,主要应用于三维模型、地形等复杂几何数据的渲染中。LOD通过在不同的距离和尺寸下使用不同的模型细节级别,使得在近处显示高细节的模型,而在远处则只显示简化的模型。这样可以减少需要渲染的数据量,提高渲染性能。LOD将一个复杂的模型分成多个不同的细节层次,每个层次都有一个相应的模型表示。随着视点的移动,系统会根据视点与模型的距离和大小,自动切换显示不同的细节层次,从而在不影响视觉效果的前提下,提高渲染性能。
在点云可视化中,LOD技术也可以应用于优化点云的渲染性能。例如,在近处可以显示点云的所有细节,而在远处只需要显示部分点云或者采用一些简化的点云表示方式,从而提高点云可视化的效率。
之前的一篇文章:PCL中outofcore模块---基于核外八叉树的大规模点云的显示
LOD算法的基本思想
对于每一个点云数据,将其表示为不同层次的细节级别,即将每个点云数据分解成若干层,每一层代表一种不同的细节级别,每一层的点云数量比前一层减少,同时每层点云之间存在一定的关联关系。一般来说,每一层的点云数据都可以通过前一层数据进行重建或者近似重建。这样,在可视化时,根据需要,选择合适的细节级别进行显示,能够在保证精度的前提下,减少计算和存储的开销。
LOD(Level of Detail)算法的基本思想是根据视点距离和显示需求等因素,对模型进行适当的简化和优化,以提高显示效率和减少计算开销。LOD算法也常用于对点云数据进行适当的简化和优化,以提高点云渲染的效率。LOD算法的基本思想可以分为两个方面:
减少数据量:LOD算法根据视点距离,将大范围的点云数据进行适当的简化和压缩,减少数据量,提高点云数据的渲染效率。
保持数据的精度:LOD算法在简化数据的同时,尽可能地保留数据的精度。例如,在点云数据简化时,可以保留重要的点和局部细节信息,从而避免丢失重要的特征信息,保持数据的精度和可视化效果。
LOD算法通常会将点云数据分为不同的层级,每个层级对应不同的点云分辨率。在视点距离较远时,可以使用较低分辨率的点云数据来显示,以提高渲染效率;在视点距离较近时,则可以使用更高分辨率的点云数据来显示,以保证显示精度和细节。
LOD算法常见的实现方式
LOD(Level of Detail)算法的实现方式有多种,其中常见的有两种:基于采样的LOD(金字塔层次结构、变形网格)和基于分割的LOD(空间分割)。
基于采样的LOD是指通过对点云数据进行采样,从而得到不同密度的点云表示不同的细节层次。这种方法的优点是简单易实现,可以方便地对不同层次的点云进行展示和处理。常见的实现方式包括:体素化采样和随机采样。其中,体素化采样是指将点云数据按照一定的体素大小进行采样,从而得到不同精度的点云。CloudCompare中就使用了体素化采样的方法来实现LOD算法,用户可以通过设置不同的体素大小来控制不同细节层次的显示。
基于分割的LOD是指将点云数据按照不同的特征进行分割,从而得到不同密度的点云表示不同的细节层次。这种方法的优点是可以更加准确地表达点云数据的特征信息。常见的实现方式包括:基于颜色和法向量的分割、基于曲率的分割等。但是,这种方法相对于基于采样的LOD来说更加复杂,实现起来也更加困难。
CloudCompare和PCL库中LOD的实现
LOD算法可以帮助我们更好地展示和处理大规模的点云数据,常见的实现方式包括基于采样的LOD和基于分割的LOD。在CloudCompare中,主要采用了基于体素化采样的方法实现LOD算法。
这是CloudCompare中实现LOD算法的函数,函数原型为
void CCViewer::computeLOD(std::vector& comps, const unsigned int maxPoints, const unsigned int maxVoxels)。
该函数会接收一个点云组件列表和最大点数和最大体素数,然后计算总点数,并根据总点数和最大点数计算采样因子。然后,根据采样因子和最大体素数计算体素大小,并将其应用于点云组件。这种方法使用体素化采样,可以快速地减少点云数据的密度,从而实现LOD效果。下面对其进行详细的注释:
void CCViewer::computeLOD(std::vector& comps, const unsigned int maxPoints, const unsigned int maxVoxels)
{
// compute the total number of points
unsigned long long totalPoints = 0;
for (size_t i = 0; i < comps.size(); i++)
{
totalPoints += comps[i]->getPointCloud().size();
}
首先,该函数接收一个CloudGLComponent指针的向量comps,表示所有待处理的点云组件,以及两个参数maxPoints和maxVoxels,分别表示采样后最大的点数和最大的体素数。函数的第一步是计算所有点云的点数总和,这个总和保存在变量totalPoints中。
// compute the sampling factor
float factor = (float)totalPoints / (float)maxPoints;
float voxelFactor = factor * 0.3f; // arbitrary factor to take into account the voxelization process
接下来,函数计算采样系数。采样系数是一个与总点数和采样后最大点数有关的浮点数,用于指导采样时的点数选择。LOD算法的基本思想是,在显示远处的点云时,选择相对较少的点来表示,从而减小渲染的负担。因此,采样系数越大,表示点云被采样得越稠密。voxelFactor是一个用于考虑体素化过程的任意系数。
// compute the voxel size
double voxels = totalPoints / voxelFactor;
voxels /= maxVoxels;
voxels = pow(voxels, 1.0 / 3.0);
voxels = std::max(voxels, 0.005);
接下来,函数根据采样系数和最大体素数计算体素大小。计算方法是:先计算所有点云的点数与voxelFactor的比值,再除以maxVoxels,最后开三次方根。这样计算出来的结果就是每个体素的边长。另外,函数还对计算结果进行了一个限制,保证每个体素的大小不小于0.005。
// update the voxel size
for (size_t i = 0; i < comps.size(); i++)
{
comps[i]->updateVoxelSize(voxels);
}
}
最后,函数更新每个点云组件的体素大小,将之前计算出来的边长voxels作为参数传递给updateVoxelSize函数。这个函数的作用是更新点云组件的体素,并在必要时重新计算点云的LOD信息。
PCL中outofcore模块实现了大规模点云的可视化,其中采用了基于体素的LOD算法,该算法的具体实现过程如下所示:
初始化体素树:首先,需要在内存中初始化一个体素树,即根据点云数据生成一个体素层级结构,最底层为点云的原始数据,然后不断上采样生成更高分辨率的体素层。
选择当前LOD:根据视点位置,计算出当前视点在体素树中的层数,进而确定当前需要显示的LOD层数。
加载数据:根据当前需要显示的LOD,从磁盘中加载相应的数据,即体素、八叉树节点、点云块等。
体素渲染:将加载的体素通过OpenGL渲染到屏幕上,根据当前LOD选择体素的大小,以保证视觉效果。
八叉树渲染:对于体素层次结构中的内部节点,需要采用递归的方式对其子节点进行渲染。
点云块渲染:对于叶子节点(即点云块),则需要根据当前LOD选择加载部分点云块的数据,并通过OpenGL渲染到屏幕上。
点云渲染:在点云块渲染的过程中,还需要对其中的点云进行LOD处理,即根据当前LOD选择保留一定比例的点云数据进行渲染,而剩余的点云则被抽样或者丢弃。
总的来说,outofcore模块的LOD算法主要利用了体素结构的层次性质,根据视点位置动态选择LOD并采用不同程度的采样对点云数据进行处理,以实现大规模点云的可视化。
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/outofcore/visualization/outofcore_visualizer.h>
int main(int argc, char **argv)
{
// 创建一个可视化窗口
boost::shared_ptrviewer(new pcl::visualization::PCLVisualizer("PCL Outofcore Viewer"));
// 创建一个outofcore可视化器
pcl::outofcore::visualization::OutofcoreVisualizervis(viewer);
// 加载点云数据
vis.load(argv[1]);
// 初始化体素树
vis.initOctree();
// 设置视点位置
Eigen::Vector3d eye(0.0, 0.0, 200.0);
// 设置目标位置
Eigen::Vector3d target(0.0, 0.0, 0.0);
// 设置向上方向
Eigen::Vector3d up(0.0, 1.0, 0.0);
// 设置视口大小
int width = 640;
int height = 480;
// 设置近点距和远点距
double near = 0.1;
double far = 1000.0;
// 根据视点位置计算当前LOD
int lod = vis.computeLOD(eye);
// 设置背景颜色
viewer->setBackgroundColor(0.0, 0.0, 0.0);
// 开始渲染
while (!viewer->wasStopped())
{
// 加载当前需要显示的LOD层数的数据
vis.loadLOD(lod);
// 渲染体素
vis.renderVoxels(lod);
// 渲染八叉树节点
vis.renderOctree(lod);
// 渲染点云块
vis.renderBlocks(lod);
// 渲染点云
vis.renderPoints(lod);
// 更新窗口
viewer->spinOnce(100);
// 更新视点位置
eye = viewer->getCameras()[0].pos;
lod = vis.computeLOD(eye);
}
return 0;
}
当点云数据非常大时,对于每次的渲染操作,需要从磁盘中加载相应的数据,会导致大量的IO操作,从而导致渲染效率非常低下。为了提高渲染效率,PCL中的outofcore模块还提供了一些性能优化手段,例如预加载数据、异步加载数据等。
预加载数据:在初始化体素树时,可以预加载一些体素、八叉树节点、点云块等数据到内存中,这样可以在后续渲染操作时避免磁盘IO操作,从而提高渲染效率。
异步加载数据:在渲染操作中,可以采用异步加载数据的方式,即将数据加载的过程放在后台线程中进行,这样可以避免阻塞主线程,从而提高渲染效率。
PCL中的outofcore模块可以有效地实现对大规模点云数据的可视化,不仅可以提供高效的渲染效果,还支持LOD、性能优化等一系列功能。
LOD算法的优缺点
优点:
高效性:通过降低点云数据的分辨率,减少需要处理的数据量,提高算法的处理效率,可以根据需要选择不同的细节级别进行渲染,减少点云数量,从而提高渲染效率。
可视化效果好:通过降低点云数据的分辨率,可以实现在不损失重要信息的情况下,显示更大规模的点云数据。即使在较低的细节级别下,也能够提供足够的可视化信息。
可以减少内存占用:可以将点云数据集分解成多层,每一层点云数据数量逐层减少,从而节省存储空间,通过降低点云数据的分辨率,可以减少存储数据所需的内存。
缺点:
精度受限:LOD算法降低了点云数据的分辨率,因此对于需要高精度的应用,可能会出现信息丢失的情况。
不能完全代替原始数据:虽然通过LOD算法可以降低点云数据的分辨率,但是不能完全代替原始数据,因为降低分辨率会损失一些重要信息。
-
LOD算法本身需要设计:需要在算法实现时进行一些设计,例如选择何种算法、决定采样率等,这可能需要一些经验和实验验证。
因此,LOD算法适用于大规模点云数据的可视化和处理,但对于需要高精度和完整性的应用,需要谨慎使用。
DEMO展示
更多详细内容请加入智驾全栈与3D视觉学习星球
智驾全栈与3D视觉学习星球:主要针对智能驾驶全栈相关技术,3D/2D视觉技术学习分享的知识星球,将持续进行干货技术分享,知识点总结,代码解惑,最新paper分享,解疑答惑等等。星球邀请各个领域有持续分享能力的大佬加入我们,对入门者进行技术指导,对提问者知无不答。同时,星球将联合各知名企业发布自动驾驶,机器视觉等相关招聘信息和内推机会,创造一个在学习和就业上能够相互分享,互帮互助的技术人才聚集群。
资源
自动驾驶及定位相关分享
【点云论文速读】基于激光雷达的里程计及3D点云地图中的定位方法
自动驾驶中基于光流的运动物体检测
基于语义分割的相机外参标定
综述:用于自动驾驶的全景鱼眼相机的理论模型和感知介绍
高速场景下自动驾驶车辆定位方法综述
Patchwork++:基于点云的快速、稳健的地面分割方法
PaGO-LOAM:基于地面优化的激光雷达里程计
多模态路沿检测与滤波方法
多个激光雷达同时校准、定位和建图的框架
动态的城市环境中杆状物的提取建图与长期定位
非重复型扫描激光雷达的运动畸变矫正
快速紧耦合的稀疏直接雷达-惯性-视觉里程计
基于相机和低分辨率激光雷达的三维车辆检测
用于三维点云语义分割的标注工具和城市数据集
ROS2入门之基本介绍
固态激光雷达和相机系统的自动标定
激光雷达+GPS+IMU+轮速计的传感器融合定位方案
基于稀疏语义视觉特征的道路场景的建图与定位
自动驾驶中基于激光雷达的车辆道路和人行道实时检测(代码开源)
用于三维点云语义分割的标注工具和城市数据集
更多文章可查看:点云学习历史文章大汇总
SLAM及AR相关分享
TOF相机原理介绍
TOF飞行时间深度相机介绍
结构化PLP-SLAM:单目、RGB-D和双目相机使用点线面的高效稀疏建图与定位方案
开源又优化的F-LOAM方案:基于优化的SC-F-LOAM
【开源方案共享】ORB-SLAM3开源啦!
【论文速读】AVP-SLAM:自动泊车系统中的语义SLAM
【点云论文速读】StructSLAM:结构化线特征SLAM
SLAM和AR综述
常用的3D深度相机
AR设备单目视觉惯导SLAM算法综述与评价
SLAM综述(4)激光与视觉融合SLAM
Kimera实时重建的语义SLAM系统
SLAM综述(3)-视觉与惯导,视觉与深度学习SLAM
易扩展的SLAM框架-OpenVSLAM
高翔:非结构化道路激光SLAM中的挑战
基于鱼眼相机的SLAM方法介绍
以上内容如有错误请留言评论,欢迎指正交流。如有侵权,请联系删除
扫描二维码
关注我们
让我们一起分享一起学习吧!期待有想法,乐于分享的小伙伴加入知识星球注入爱分享的新鲜活力。分享的主题包含但不限于三维视觉,点云,高精地图,自动驾驶,以及机器人等相关的领域。
分享及合作方式:微信“920177957”(需要按要求备注) 联系邮箱:dianyunpcl@163.com,欢迎企业来联系公众号展开合作。
点一下“在看”你会更好看耶文章来源:https://www.toymoban.com/news/detail-476083.html
文章来源地址https://www.toymoban.com/news/detail-476083.html
到了这里,关于学习PCL库:基于LOD的大规模点云可视化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!