使用pcl::IntegralImageNormalEstimation计算法线输出NAN值问题
问题诱因及解决方案
以下是该问题的常见触发原因和对应解决方法:
- 诱因1:输入点云不符合有序点云要求
积分图法线估计仅支持有序点云(即点云保留类图像的行列结构,height>1且每个行列位置对应固定视场角的点,无效点坐标填充为NAN),而NormalEstimationOMP对有序、无序点云均兼容,这是该类问题最常见的诱因。
解决方案:
- 调用
transform_cloud->isOrganized()检查点云是否为有序结构,返回false则首先修正输入点云格式- 从RGB-D/双目/结构光传感器获取原始点云时不要直接删除无效点,保留原始行列结构;如果是从深度图生成点云,严格对应深度图的宽高生成有序结构,不要打乱点的排列顺序
- 如果你使用的是机械式激光雷达输出的无序点云,无法直接使用积分图法线估计,只能选择邻域搜索类的法线估计算法。
- 诱因2:点云深度方向不符合算法要求
IntegralImageNormalEstimation默认以点云Z轴为观测深度方向,如果你传入的transform_cloud经过坐标变换后,深度观测方向不是Z轴,会导致深度差计算全部判断异常,输出NAN。
解决方案:
计算法线前先将点云转换到传感器自身坐标系,保证Z轴为观测深度方向,法线计算完成后再将法线通过旋转变换转换到目标坐标系即可。
- 诱因3:参数设置与点云特性不匹配
你当前设置的setMaxDepthChangeFactor(2.0f)和setNormalSmoothingSize(10.0f)需要和点云的单位、分辨率匹配:
- 如果点云单位是毫米,2.0f的深度变化阈值仅为2毫米,场景内所有深度跳变都会被判定为边缘,直接返回NAN
- 平滑窗口尺寸如果和点云分辨率不匹配,会导致邻域计算无法找到有效点
解决方案:
- 确认点云单位,按实际场景最大允许的相邻点深度差设置
MaxDepthChangeFactor,可先调大到10.0f以上验证是否能输出有效法线,再逐步收敛到合适值NormalSmoothingSize设置为点云相邻点平均间距的510倍即可,比如点云分辨率为1cm,设置5.0f10.0f即可
- 诱因4:点类型字段不匹配
你代码中模板参数设置为pcl::IntegralImageNormalEstimation<PointType, PointType>,即输出点类型和输入一致,需确认你的自定义PointType包含normal_x/normal_y/normal_z/curvature四个字段,否则计算结果无法写入对应字段会返回NAN。
解决方案:
要么将输出模板参数改为pcl::Normal,输出到单独的法线点云,要么给自定义PointType补充法线相关字段。
- 诱因5:有序点云无效点填充格式错误
有序点云中的无效点必须将x/y/z坐标全部填充为NAN,如果你的无效点填充的是0或者其他固定值,会导致积分图计算时邻域全部为无效值,输出NAN。
解决方案:
将有序点云的无效点坐标全部设置为std::numeric_limits<float>::quiet_NaN()即可。
内容的提问来源于stack exchange,提问作者user16987341
相关产品推荐
相关产品推荐

