PCL点云压缩总结

PCL点云压缩总结

调用代码

#define _SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
     
	pcl::PointCloud<pcl::PointXYZRGB> sourceCloud;
	pcl::PLYReader reader;
	if (pcl::io::loadPLYFile("Egyptian_mask_vox12.ply", sourceCloud) == -1)//输入点云文件
	{
     
		PCL_ERROR("Failed to load PLYFile!");
		return -1;
	}
	bool showStatistics = true;
	pcl::io::compression_Profiles_e compressionProfile = pcl::io::MANUAL_CONFIGURATION;
	pcl::io::OctreePointCloudCompression<pcl::PointXYZRGB>* PointCloudEncoder;
	PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGB>(compressionProfile, showStatistics, 0.001, 0.01,
		true, 100, true, 8);//输入参数
	std::stringstream compressedData;
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudOut(new pcl::PointCloud<pcl::PointXYZRGB>());
	
	PointCloudEncoder->encodePointCloud(sourceCloud.makeShared(), compressedData);
	compressedData.write("compressed.bin", sizeof(compressedData));
	PointCloudEncoder->decodePointCloud(compressedData, cloudOut);
	pcl::PLYWriter writer;
	writer.write("high_true.ply", *cloudOut, false, false);
	system("pause");
	return 0;
}

参数设置

PCL输入参数配置有两种方式:在compression_profiles.h文件中选择输入参数的方式:选择系统自带的配置(如LOW_RES_ONLINE_COMPRESSION_WITH_COLOR、MED_RES_ONLINE_COMPRESSION_WITH_COLOR、HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR等)或者自定义(选择MANUAL_CONFIGURATION,然后如上面的代码中所示)。输入的参数共六个,见下图所示:PCL点云压缩总结_第1张图片

参数说明

其中pointResolution是指点的分辨率,该变量决定了点的坐标在编码时可以精确的程度,但是该变量只在进行细节编码(detail coding)时才会生效;octreeResolution是指划分八叉树时最小块,即voxel的边长;布尔变量doVoxelGridDownSampling为true时,对点云文件进行下采样,以体素的中心点的坐标来代替整个体素内的点的坐标,而颜色则以体素内所有点的颜色的均值为代表,此时pointResolution不会生效;如果pointResolution为false,则进行细节编码,即编码一个体素内的具体坐标与颜色,实现方式是计算体素内每个点到体素左下角的偏移量,并通过整除pointResolution来得到整数坐标,而颜色则需编码体素内每个点的颜色相对于平均值的残差,colorResolution用来表示颜色的RGB的保留的有效位数。iFrameRate是用来决定进行I帧编码的频率,如果此数值为30,则每隔30帧进行一次I帧编码,中间的帧则进行P帧编码。doColorEncoding决定是否进行颜色编码。如果该值为false,则不会对颜色进行编码,如果为true但是输入的点云文件没有颜色信息,则在解码时赋予其默认值。

PCL点云编码流程流程图

PCL点云压缩总结_第2张图片
在该流程图前,还需判定当前帧是I帧还是P帧,如果是I帧,则按此流程图正常进行编码,而如果是P帧,则在编码八叉树占位码时,编码的是和之前帧的异或之后的差值。八叉树的结构编码就是在进行八叉树划分之后,编码体素的占位码,如果doVoxelGridDownSampling为true,则跳过细节编码部分,解码端在解码时只要根据八叉树的结构信息,恢复出八叉树结构,以其体素中心点为代表即可。

关键技术

1. 双缓存八叉树

PCL中使用了“double-buffering octree”,即双缓冲八叉树结构,使用这种结构在实现动态压缩时或者第三类点云时,可以减少时间冗余,它的使用效果为:首先对第一个点云文件执行一次完整的编码,然后对后续的点云文件,只对前后的差值进行编码。双八叉树数据结构使用的过程是:每个分支节点都有两个缓冲区,当需要创建新的子节点时,会在当前分支节点中执行对前面指针缓冲区的查找,如果找不到相关的引用指针,即在之前处理过的八叉树结构中不存在相应的体素,则创建新的子节点,且两个缓冲区都初始化为0,如下图3左所示;如果在前面的指针缓冲区中可以找到对应的子节点指针,就采用它的引用,并只是初始化所选的子指针缓冲区为0,如下图3右图所示。初始化完成之后,可以通过对两个缓存区进行异或操作,得到两个八叉树缓存区之间的差异,类似于视频编码中的帧间预测,编码两个帧间的差异,如下图4所示。
PCL点云压缩总结_第3张图片

2. 细节编码

细节编码就是编码体素内的细节。如果八叉树划分时,体素的大小较大,例如我们输入的ply文件中,点云中的点的单位是毫米级的,即每个点对应一个边长为1mm的正方体块。如果我们在设置octreeResolution时,设置其值为5mm,则八叉树划分时划分到边长5mm的立方体就停止,一个体素内会有多个点。如果我们不进行细节编码,即doVoxelGridDownSampling为true时,在解码时一个体素内只会在其中心位置恢复一个点,其属性为几个点的均值,这样会导致点的损失。如果我们进行细节编码,那就会编码一个体素内点的细节信息,即编码点的具体位置与属性。如图5所示:
PCL点云压缩总结_第4张图片
首先计算每个体素的左下角坐标,然后计算每个点到左下角的偏移量,然后与pointResolution相除,得到最终的编码信息是整数diffX、 diffY、 diffZ,属性编码则是先计算这几个点的均值,然后计算每个点相对于均值的颜色偏移量,每个R、G、B的位数由colorResolution所决定。

你可能感兴趣的:(PCL,八叉树,点云压缩)