点云由庞大的数据集组成,这些数据集通过距离、颜色、法线等附加信息来描述空间三维点。此外,点云能以非常高的速率被创建出来,因此需要占用相当大的存储资源,一旦点云需要存储或者通过速率受限制的通信信道进行传输,提供针对这种数据的压缩方法就变得十分有用。PCL库提供了点云压缩功能,它允许编码压缩所有类型的点云,包括“无序”点云,它具有无参考点和变化的点尺寸、分辨率、分布密度和点顺序等结构特征。而且,底层的octree数据结构允许从几个输入源高效地合并点云数据。
图1 点云压缩示意图
下面,我们解释单个点云和点云数据流是如何高效压缩的,在给出的例子中,我们用PCL点云压缩技术来压缩用OpenNIGrabber抓取到的点云。
代码:
首先,在PCL(Point Cloud Learning)中国协助发行的书提供光盘的第6章例1文件夹中,打开名为point_cloud_compression.cpp的代码文件。
解释说明
下面详细解析打开的源代码。从主函数开始,首先创建一个新的SimpleOpenNIViewer实例并调用它的run()方法。
int
main(int argc,char **argv)
{
SimpleOpenNIViewer v;
v.run();
return(0);
}
在run()函数中,创建PointCloudCompression类的对象来编码和解码,这些对象把压缩配置文件作为配置压缩算法的参数,所提供的压缩配置文件为OpenNI兼容设备采集到的点云预先确定的通用参数集。本例中,使用MED_RES_ONLINE_COMPRESSION_WITH_COLOR配置参数集,它应用5立方毫米的编码精度并且允许彩色纹理成分编码,并进一步优化,用于快速在线压缩。压缩配置文件的完整列表及其配制方法可以在文件“/io/include/pcl/compression/compression_profiles.h”中找到。在PointCloudCompression构造函数中使用MANUAL_CONFIGURATION属性就可以手动设置压缩算法全部参数。
bool showStatistics=true; //设置在标准设备上输出打印出压缩结果信息
// 压缩选项详见 /io/include/pcl/compression/compression_profiles.h
pcl::octree::compression_Profiles_e compressionProfile=pcl::octree::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;
// 初始化压缩与解压缩对象,其中压缩对象需要设定压缩参数选项,解压缩按照数据源自行判断
PointCloudEncoder=new pcl::octree::PointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
PointCloudDecoder=new pcl::octree::PointCloudCompression<pcl::PointXYZRGBA> ();
下面的代码为OpenNI兼容设备实例化一个新的采集器,并且启动循环回调接口,每从设备获取一帧数据,就调用回调函数一次,这里的回调函数实现数据压缩和可视化解压缩结果。
//创建从 OpenNI获取点云的抓取对象
pcl::Grabber* interface =new pcl::OpenNIGrabber ();
boost::function<void(constpcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);//建立回调函数
// 建立回调函数与回调信号之间绑定
boost::signals2::connection c = interface->registerCallback (f);
// 开始接收点云数据流
interface->start ();
while (!viewer.wasStopped ())
{
sleep (1);
}
interface->stop ();
在OpenNIGrabber采集循环执行的回调函数cloud_cb_中,我们首先把获取到的点云压缩到stringstream缓冲区,下一步是解压缩,它对压缩了的二进制数据进行解码,存储在新的点云对象中,解码了的点云被发送到点云可视化对象中进行实时可视化。
void
cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
{
if (!viewer.wasStopped ())
{
std::stringstream compressedData;// 存储压缩点云的字节流对象
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut // 存储输出点云
(new pcl::PointCloud<pcl::PointXYZRGBA> ());
PointCloudEncoder->encodePointCloud (cloud, compressedData);// 压缩点云
PointCloudDecoder->decodePointCloud (compressedData, cloudOut);// 解压缩点云
viewer.showCloud (cloudOut);//可视化解压缩点云
}
}
//在压缩与解压缩过程中,因为设置compressedData为true所以在标准输出上打印出压缩率帧数等信息
编译并运行该程序
利用光盘提供的CMakeLists.txt文件,在cmake中建立工程文件,并生成相应的可执行文件,生成执行文件后,就可以运行了,在cmd中键入命令:
...>point_cloud_compression.exe
可以看到如图2所示结果,左边为实时可视化带RGB纹理信息的点云结果,用户缩放可视化结果可以看到经过压缩后点云进行了重采样,纹理信息有所丢失,但数据量有所减小,在实际应用当中需折中取舍。右边则为实时压缩信息输出,可以看出压缩的帧数、点数、压缩率等信息。
图2 点云压缩运行结果