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 点云压缩能够有效地压缩任何类型的点云和点云流。
BimAnt翻译整理,转载请标明出处