PCL点云压缩简明教程

点云由描述与距离、颜色、法线等附加信息相关的三维点的巨大数据集组成。此外,它们可以高速创建,因此占用大量内存资源。 一旦必须通过速率受限的通信通道存储或传输点云,压缩此类数据的方法就变得非常有趣。 PCL库提供点云压缩功能。 它允许对各种点云进行编码,包括“无组织”点云,其特征是不存在的点引用、不同的点大小、分辨率、密度和/或点排序。 此外,底层八叉树数据结构能够有效地合并来自多个源的点云数据。

下面,我们将解释如何有效地压缩单个点云以及点云流。 在所提供的示例中,我们使用 OpenNIGrabber 捕获点云,并使用 PCL 点云压缩技术进行压缩。

1、实现代码

首先,创建一个文件,比方说, point_cloud_compression.cpp 并将以下内容放入其中:

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>

#include <pcl/compression/octree_pointcloud_compression.h>

#include <stdio.h>
#include <sstream>
#include <stdlib.h>

#ifdef WIN32
# define sleep(x) Sleep((x)*1000)
#endif

class SimpleOpenNIViewer
{
public:
  SimpleOpenNIViewer () :
    viewer (" Point Cloud Compression Example")
  {
  }

  void
  cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
  {
    if (!viewer.wasStopped ())
    {
      // stringstream to store compressed point cloud
      std::stringstream compressedData;
      // output pointcloud
      pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());

      // compress point cloud
      PointCloudEncoder->encodePointCloud (cloud, compressedData);

      // decompress point cloud
      PointCloudDecoder->decodePointCloud (compressedData, cloudOut);


      // show decompressed point cloud
      viewer.showCloud (cloudOut);
    }
  }

  void
  run ()
  {

    bool showStatistics = true;

    // for a full list of profiles see: /io/include/pcl/compression/compression_profiles.h
    pcl::io::compression_Profiles_e compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;

    // instantiate point cloud compression for encoding and decoding
    PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
    PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();

    // create a new grabber for OpenNI devices
    pcl::Grabber* interface = new pcl::OpenNIGrabber ();

    // make callback function from member function
    std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
      [this] (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& cloud) { cloud_cb_ (cloud); };

    // connect callback function for desired signal. In this case its a point cloud with color values
    boost::signals2::connection c = interface->registerCallback (f);

    // start receiving point clouds
    interface->start ();

    while (!viewer.wasStopped ())
    {
      sleep (1);
    }

    interface->stop ();

    // delete point cloud compression instances
    delete (PointCloudEncoder);
    delete (PointCloudDecoder);

  }

  pcl::visualization::CloudViewer viewer;

  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudEncoder;
  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudDecoder;

};

int
main ()
{
  SimpleOpenNIViewer v;
  v.run ();

  return (0);
}

2、代码解读

现在,让我们详细讨论代码。 让我们从 main() 函数开始:首先我们创建一个新的 SimpleOpenNIViewer 实例并调用其 run() 方法:

int
main ()
{
  SimpleOpenNIViewer v;
  v.run ();

  return (0);
}

run() 函数中,我们创建 OctreePointCloudCompression 类的实例以进行编码和解码。 他们可以将压缩配置文件作为配置压缩算法的参数。 提供的压缩配置文件为 openNI 设备捕获的点云预定义了通用参数集。

在此示例中,我们使用 MED_RES_ONLINE_COMPRESSION_WITH_COLOR 配置文件,该配置文件应用 5 立方毫米的坐标编码精度并启用颜色分量编码。 它针对快速在线压缩进行了进一步优化。 压缩配置文件的完整列表(包括其配置)可以在文件 /io/include/pcl/compression/compression_profiles.h中找到。

使用 MANUAL_CONFIGURATION 配置文件,还可以在 OctreePointCloudCompression 构造函数中对压缩算法进行完整参数化。 有关高级参数化的更多详细信息,请参阅“高级参数化”部分。

    bool showStatistics = true;

    // for a full list of profiles see: /io/include/pcl/compression/compression_profiles.h
    pcl::io::compression_Profiles_e compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;

    // instantiate point cloud compression for encoding and decoding
    PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
    PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();

以下代码实例化 OpenNI 设备的新采集器并启动接口回调循环:

    // create a new grabber for OpenNI devices
    pcl::Grabber* interface = new pcl::OpenNIGrabber ();

    // make callback function from member function
    std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
      [this] (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& cloud) { cloud_cb_ (cloud); };

    // connect callback function for desired signal. In this case its a point cloud with color values
    boost::signals2::connection c = interface->registerCallback (f);

    // start receiving point clouds
    interface->start ();

    while (!viewer.wasStopped ())
    {
      sleep (1);
    }

    interface->stop ();

在 OpenNIGrabber 捕获循环执行的回调函数中,我们首先将捕获的点云压缩到字符串流缓冲区中。 接下来是解压缩步骤,将压缩的二进制数据解码为新的点云对象。 然后将解码的点云发送到点云查看器:

  void
  cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
  {
    if (!viewer.wasStopped ())
    {
      // stringstream to store compressed point cloud
      std::stringstream compressedData;
      // output pointcloud
      pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());

      // compress point cloud
      PointCloudEncoder->encodePointCloud (cloud, compressedData);

      // decompress point cloud
      PointCloudDecoder->decodePointCloud (compressedData, cloudOut);


      // show decompressed point cloud
      viewer.showCloud (cloudOut);
    }
  }

3、编译并运行程序

将以下行添加到你的 CMakeLists.txt 文件中:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(point_cloud_compression)

find_package(PCL 1.2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (point_cloud_compression point_cloud_compression.cpp)
target_link_libraries (point_cloud_compression ${PCL_LIBRARIES})

制作可执行文件后,可以运行它。 只需执行以下操作:

$ ./point_cloud_compression

你将看到类似以下内容的内容:

[OpenNIGrabber] Number devices connected: 1
[OpenNIGrabber] 1. device on bus 002:17 is a Xbox NUI Camera (2ae) from Microsoft (45e) with serial id 'B00364707960044B'
[OpenNIGrabber] device_id is not set or has unknown format: ! Using first device.
[OpenNIGrabber] Opened 'Xbox NUI Camera' on bus 2:17 with serial number 'B00364707960044B'
streams alive:  image,  depth_image
*** POINTCLOUD ENCODING ***
Frame ID: 1
Encoding Frame: Intra frame
Number of encoded points: 192721
XYZ compression percentage: 3.91049%
XYZ bytes per point: 0.469259 bytes
Color compression percentage: 15.4717%
Color bytes per point: 0.618869 bytes
Size of uncompressed point cloud: 3011.27 kBytes
Size of compressed point cloud: 204 kBytes
Total bytes per point: 1.08813 bytes
Total compression percentage: 6.8008%
Compression ratio: 14.7042

*** POINTCLOUD ENCODING ***
Frame ID: 2
Encoding Frame: Prediction frame
Number of encoded points: 192721
XYZ compression percentage: 3.8132%
XYZ bytes per point: 0.457584 bytes
Color compression percentage: 15.5448%
Color bytes per point: 0.62179 bytes
Size of uncompressed point cloud: 3011.27 kBytes
Size of compressed point cloud: 203 kBytes
Total bytes per point: 1.07937 bytes
Total compression percentage: 6.74609%
Compression ratio: 14.8234

*** POINTCLOUD ENCODING ***
Frame ID: 3
Encoding Frame: Prediction frame
Number of encoded points: 192721
XYZ compression percentage: 3.79962%
XYZ bytes per point: 0.455954 bytes
Color compression percentage: 15.2121%
Color bytes per point: 0.608486 bytes
Size of uncompressed point cloud: 3011.27 kBytes
Size of compressed point cloud: 200 kBytes
Total bytes per point: 1.06444 bytes
Total compression percentage: 6.65275%
Compression ratio: 15.0314

...

4、压缩配置文件

压缩配置文件(compression profile)定义 PCL 点云编码器的参数集。 它们针对从 OpenNI 采集器检索的常见点云的压缩进行了优化。 请注意,解码器不需要参数化,因为它会检测并采用编码期间使用的配置。 可以使用以下压缩配置文件:

  • LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR : 1立方厘米分辨率,无颜色,快速在线编码
  • LOW_RES_ONLINE_COMPRESSION_WITH_COLOR : 1立方厘米分辨率、颜色、快速在线编码
  • MED_RES_ONLINE_COMPRESSION_WITHOUT_COLOR :5立方毫米分辨率,无颜色,快速在线编码
  • MED_RES_ONLINE_COMPRESSION_WITH_COLOR : 5立方毫米分辨率、颜色、快速在线编码
  • HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR : 1立方毫米分辨率,无颜色,快速在线编码
  • HIGH_RES_ONLINE_COMPRESSION_WITH_COLOR : 1立方毫米分辨率、颜色、快速在线编码
  • LOW_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR : 1立方厘米分辨率,无颜色,高效离线编码
  • LOW_RES_OFFLINE_COMPRESSION_WITH_COLOR : 1立方厘米分辨率、颜色、高效离线编码
  • MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR : 5立方毫米分辨率,无颜色,高效离线编码
  • MED_RES_OFFLINE_COMPRESSION_WITH_COLOR : 5立方毫米分辨率、颜色、高效离线编码
  • HIGH_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR : 1立方毫米分辨率,无颜色,高效离线编码
  • HIGH_RES_OFFLINE_COMPRESSION_WITH_COLOR : 1立方毫米分辨率、颜色、高效离线编码
  • MANUAL_CONFIGURATION : 启用高级参数化的手动配置

5、高级参数化

为了完全访问所有与压缩相关的参数, OctreePointCloudCompression 类的构造函数可以使用附加压缩参数进行初始化。

注意,要启用高级参数化, compressionProfile_arg 应设置 MANUAL_CONFIGURATION

OctreePointCloudCompression (compression_Profiles_e compressionProfile_arg,
                             bool showStatistics_arg,
                             const double pointResolution_arg,
                             const double octreeResolution_arg,
                             bool doVoxelGridDownDownSampling_arg,
                             const unsigned int iFrameRate_arg,
                             bool doColorEncoding_arg,
                             const unsigned char colorBitResolution_arg
                            )

高级参数化解释如下:

  • compressionProfile_arg:此参数应设置为 MANUAL_CONFIGURATION 以启用高级参数化。
  • showStatistics_arg:将压缩相关统计信息打印到标准输出。
  • pointResolution_arg:定义点坐标的编码精度。 该参数应设置为低于传感器噪声的值。
  • octreeResolution_arg:此参数定义部署的八叉树的体素大小。 较低的体素分辨率可以实现更快的压缩,但压缩性能会降低。 这可以在高帧/更新率和压缩效率之间进行权衡。
  • doVoxelGridDownDownSampling_arg:如果激活,则仅对分层八叉树数据结构进行编码。 解码器在体素中心生成点。 这样,点云在压缩过程中被下采样,同时实现高压缩性能。
  • iFrameRate_arg:点云压缩方案对点云进行差分编码。 通过这种方式,对传入点云和先前编码的点云之间的差异进行编码,以实现最大的压缩性能。 iFrameRate_arg 允许指定流中传入点云不进行差分编码的帧速率(类似于视频编码中的 I/P 帧)。
  • doColorEncoding_arg:此选项启用颜色分量编码。
  • colorBitResolution_arg:此参数定义要编码的每个颜色分量的位数。

6、用于PCL点云流压缩的命令行工具

pcl 应用程序组件包含用于点云压缩和流传输的命令行工具:只需执行 ./pcl_openni_octree_compression -? 查看完整的选项列表(注意:屏幕上的输出可能有所不同):

PCL point cloud stream compression

usage: ./pcl_openni_octree_compression [mode] [profile] [parameters]

I/O:
    -f file  : file name

file compression mode:
    -x: encode point cloud stream to file
    -d: decode from file and display point cloud stream

network streaming mode:
    -s       : start server on localhost
    -c host  : connect to server and display decoded cloud stream

optional compression profile:
    -p profile : select compression profile:
                   -"lowC"  Low resolution with color
                   -"lowNC" Low resolution without color
                   -"medC" Medium resolution with color
                   -"medNC" Medium resolution without color
                   -"highC" High resolution with color
                   -"highNC" High resolution without color

optional compression parameters:
    -r prec  : point precision
    -o prec  : octree voxel size
    -v       : enable voxel-grid downsampling
    -a       : enable color coding
    -i rate  : i-frame rate
    -b bits  : bits/color component
    -t       : output statistics
    -e       : show input cloud during encoding

example:
    ./pcl_openni_octree_compression -x -p highC -t -f pc_compressed.pcc

为了通过 TCP/IP 传输压缩点云,可以使用以下命令启动服务器:

$ ./pcl_openni_octree_compression -s
It will listen on port 6666 for incoming conne

它将在端口 6666 上侦听传入连接。 现在启动客户端:

$ ./pcl_openni_octree_compression -c SERVER_NAME

远程捕获的点云将在点云查看器中本地显示。

7、结论

这种 PCL 点云压缩能够有效地压缩任何类型的点云和点云流。


原文链接:Point Cloud Compression

BimAnt翻译整理,转载请标明出处