两种法线估计方法的比较
pcl::NormalEstimation
和pcl::IntegralImageNormalEstimation
是两种常见的法线估计方法,它们的区别主要在于计算法线的方式和适用场景。
-
pcl::NormalEstimation
:- 计算方式:基于K近邻搜索的方法,通过寻找点云中每个点周围的最近邻点来估计法线。
- 优点:灵活性高,可以通过调整搜索半径或K值来控制法线估计的精度和稠密度。
- 缺点:计算复杂度较高,对于大规模点云或需要实时计算的场景可能不太适用。
-
pcl::IntegralImageNormalEstimation
:- 计算方式:基于积分图的方法,通过计算积分图并利用积分图的性质快速计算法线。
- 优点:计算速度快,适用于大规模点云或需要实时计算的场景。
- 缺点:对点云数据有一定的要求,需要有序点云或使用体素格网进行体素化。
根据具体应用的需求和点云数据的特点,可以选择合适的法线估计方法。如果需要精细控制法线估计的精度和稠密度,或者处理的点云规模较小,可以选择pcl::NormalEstimation
。如果需要快速计算法线且处理的点云规模较大,可以选择pcl::IntegralImageNormalEstimation
。
积分图估算法线方法的参数
setNormalSmoothingSize
方法是用于设置法线平滑的窗口大小的。窗口大小决定了在计算法线时要考虑多少个邻域点的影响。
pcl::IntegralImageNormalEstimation
类中的 setNormalSmoothingSize
方法有以下参数选项:
ne.AVERAGE_3D_GRADIENT
:使用3D梯度的平均作为法线平滑的窗口大小。这是默认选项。ne.AVERAGE_DEPTH_CHANGE
:使用深度变化的平均作为法线平滑的窗口大小。ne.SINGLE_NORMAL
:不进行法线平滑,仅使用单个点的法线。
选择哪个平滑窗口大小的选项取决于你的具体应用和需求。
-
如果你希望在计算法线时考虑更多的邻域点,以获得更平滑的法线结果,可以选择
ne.AVERAGE_3D_GRADIENT
。这个选项将使用3D梯度的平均作为法线平滑的窗口大小。 -
如果你更关注深度变化对法线计算的影响,并希望在计算法线时更加敏感地响应深度变化,可以选择
ne.AVERAGE_DEPTH_CHANGE
。这个选项将使用深度变化的平均作为法线平滑的窗口大小。 -
如果你不需要进行法线平滑,只关注每个点的单个法线,可以选择
ne.SINGLE_NORMAL
。这个选项将不进行法线平滑,仅使用单个点的法线。
代码:
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/visualization/cloud_viewer.h>
//---------------------------------------------------------------------------------------------------------
// 积分图估算点云法线
//---------------------------------------------------------------------------------------------------------
int main(){
// 两个点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("/home/jason/file/pcl-learning/data/table_scene_mug_stereo_textured.pcd", *cloud);
// ------------------------
// 估计点云的法线
// -----------------------
// 用于存储法向量
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
// 创建法一个用于法线估计的对象并计算法线
pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setNormalSmoothingSize(ne.AVERAGE_3D_GRADIENT); // 使用平均梯度法平滑法线
ne.setMaxDepthChangeFactor(0.02f); // 设置法线估计时的最大深度变化因子。这个参数控制法线估计的灵敏度,较小的值会使法线会对深度变化更加敏感
ne.setNormalSmoothingSize(10.0f); // 设置法线估计时的法线平滑尺寸。这个参数控制在估计法线时使用的领域大小。较大的值会考虑更多的领域点,从而平滑法线的方向
ne.setInputCloud(cloud); // 设置输入点云
ne.compute(*cloud_normals); // 计算法线
// -----------------
// 可视化法线
// -----------------
pcl::visualization::PCLVisualizer viewer("PCL Viewer");
viewer.setBackgroundColor(0.0, 0.0, 0.5);
viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, cloud_normals, 2, 0.01, "normals"); // 2 表示每隔2个点绘制一个法线,控制法线的密度
// 0.01 表示法线的长度缩放因子,控制法线的可视化长度
// 其实这些参数都可以不写,PCL会自动设置,给予一个较好的显示效果
viewer.addCoordinateSystem(1.0);
while (!viewer.wasStopped()) {
viewer.spinOnce();
}
return 0;
}
效果