PCL显示double类型的点云方案

2023-12-13 15:35:25

前言

我们知道,PCL和OpenGL等三维可视化软件一样,为了兼顾性能需求,只支持加载Float类型的点云数据,但是当我们对精度要求太高时,Float类型支持不了我们的精度要求,我们的数据必须用Double类型存储才可以,要怎么解决呢?

解决方法 一

网上一个比较流行的解决方法是使用一个自定义的PCL数据类型 ,例如这样

// 自定义点云类型
namespace pcl
{
#define PCL_ADD_UNION_POINT4D_DOUBLE \
union EIGEN_ALIGN16 { \
        double data[4]; \
        struct { \
            double x; \
            double y; \
            double z; \
    }; \
};

struct _PointXYZDouble
{
    PCL_ADD_UNION_POINT4D_DOUBLE; // This adds the members x,y,z which can also be accessed using the point (which is float[4])

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

struct EIGEN_ALIGN16 PointXYZDouble : public _PointXYZDouble
{
    inline PointXYZDouble(const _PointXYZDouble& p)
    {
        x = p.x; y = p.y; z = p.z; data[3] = 1.0;
    }

    inline PointXYZDouble()
    {
        x = y = z = 0.0;
        data[3] = 1.0;
    }

    inline PointXYZDouble(double _x, double _y, double _z)
    {
        x = _x; y = _y; z = _z;
        data[3] = 1.0;
    }

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
}

POINT_CLOUD_REGISTER_POINT_STRUCT(pcl::_PointXYZDouble,
                                  (double, x, x)
                                  (double, y, y)
                                  (double, z, z)
                                  )
POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::PointXYZDouble, pcl::_PointXYZDouble)

然后在加载点云时使用pcl::XYZDouble这个自定义类型即可。
但是这个有个弊端,因为我还要使用PCL的其他函数接口,例如鼠标点击事件的回调函数,这些函数不支持我自定义的数据格式,如果要完美适配我的自定义数据类型,需要大范围的修改源码才行,工作量巨大。

解决方法二

这里我参考了一个大名鼎鼎的点云显示软件:CloudCompare
当使用CloudCompare加载精度较大的点云时,会提示
在这里插入图片描述

这里我引入官方的解释

在这里插入图片描述

大致意思就是:
因为CloudCompare和OpenGL都使用32位浮点值。与64位值相比,这允许增加速度和50%的存储器增益。然而,32位表示具有有限的分辨率,也就是精度。可以说,数字越大,可以存储的小数就越少。然而,如果在地理参考坐标系中表示的点坐标非常大,在这种情况下,数据表示精度上升到1或10厘米,32位浮点值支持不了这么高的精度,这就是为什么在CloudCompare中加载文件时“移动"点非常重要的原因。否则,原始精度将丢失。

它的移动规则也很简单, 默认情况下,CloudCompare尝试自动猜测最佳偏移向量(通常在加载文件时,CloudCompare将使用第一个点坐标作为偏移量)。后面的点都使用相同的偏移量。用TX、TY、 TZ 分别表示x、y、z坐标的偏移量,S表示倍数,LX、LY、LZ表示计算后的坐标,用公式表示就是:

L X = ( X + T X ) ? S L_X=(X+T_X)*S LX?=X+TX??S
L Y = ( Y + T Y ) ? S L_Y=(Y+T_Y)*S LY?=Y+TY??S
L Z = ( Z + T Z ) ? S L_Z=(Z+T_Z)*S LZ?=Z+TZ??S

在CloudCompare中这个偏移量默认是以第一个坐标计算得到的,倍数默认为1倍。
偏移量计算的时候没有特定公式,我举几个例子大家应该就知道是怎么回事了。

  • 原始坐标是 1850351.79723,那么偏移量就是 -1850300,偏移后的坐标是51.79723
  • 原始坐标是 -1850351.79723,那么偏移量就是 1850300,偏移后的坐标是51.79723
  • 原始坐标是 446.100006,那么偏移量就是-400,偏移后的坐标是46.100006,当然由于这个坐标比较小,偏移量也可以设置为0.00,这样偏移后的坐标和原来一致。

为什么以第一个坐标计算偏移量呢?因为大部分情况下,我们的点云坐标都是非常非常密集的,坐标的最大值和最小值差距很小,使用第一个坐标计算得到的偏移量往往是适用于所有坐标的。当然你也可以取平均值来计算偏移量。计算的时候要根据具体的数据来确定偏移量的数量级,说了这些,大家应该都知道偏移量怎么计算了吧?

那么剩下的就简单了,我就可以在PCL读取我的数据的时候,先将原始的x、y、z坐标分别存放到三个double类型的变量中,然后根据我的数据情况,来分别确定x、y、z的偏移量的正负符号和数量级,最终分别得到我x、y、z的偏移量,然后让我全部的原始坐标加上这个偏移量即可。
原始坐标记得也要存放起来,这样就可以实现这样的效果:PCL可视化的点云坐标是我偏移后的坐标,鼠标点击显示的坐标是我的原始坐标,是不是很6😁

文章来源:https://blog.csdn.net/KK_2018/article/details/134970153
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。