PCL1.7 bug: 使用ASCII存储点云时导致的颜色丢失问题

问题说明

最近在做实验时,使用pcl存储点云到pcd文件后,发生了颜色丢失的问题。
比如,在Pangolin的界面下看到了一个点云:
PCL1.7 bug: 使用ASCII存储点云时导致的颜色丢失问题_第1张图片

相当地正常。

接下来使用
pcl::io::savePCDFileASCII(“map.pcd”, cloud);
保存到了 .pcd 文件。然后使用 pcl_viewer .pcd 打开瞅瞅,咦???

PCL1.7 bug: 使用ASCII存储点云时导致的颜色丢失问题_第2张图片
墙壁、天花板和地板一坨坨黑不溜秋的东西是什么。难道点云少了?
于是按数字3进入 x,y,z轴显示,发现:
PCL1.7 bug: 使用ASCII存储点云时导致的颜色丢失问题_第3张图片
Z轴模式下,发现点云还是齐全的。只是RGB颜色丢失了,变成了黑色。

好,那就得查查看了。

系统

  • Ubuntu 16.04
  • PCL 1.7

PCL下点云的存储

我使用的pcl点云格式是标准的 pcl::XYZRGB。
查询pcl 内部处理逻辑:
1) XYZRGB 格式点的存储, r,g,b 使用 uchar 8位, 并使用一个 int (32)位保存.
看一个官方给的例子(来自pcl的 .h文件):

* uint8_t r = 255, g = 0, b = 0; // Example: Red color
* uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
* p.rgb = *reinterpret_cast<float*>(&rgb);

// the RGB information is packed into an integer and casted to a float

官方说rgb信息打包成一个整数,并且映射为一个float。
回顾一下对于C++, float型存储是32位,r,g,b分别用uchar形式存储,即8位(范围0~255),所以占用了24位,还有高8位空着。

由于我们使用ASCII形式存储的.pcd文件,意味着可以直接用文本文档打开它。
打开存储的pcd文件可以看到:

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z rgb
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
WIDTH 834860
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 834860
DATA ascii
...
-1.1053224 -0.39003652 -3.7877879 2.3509886e-38
-1.0972281 -0.38901636 -3.7972879 2.3509886e-38
-1.0696843 -0.39042562 -3.7926621 2.3509886e-38
-0.99043459 -0.38627636 -3.7838209 2.3509886e-38
-0.97979802 -0.39112651 -3.7991109 2.3509886e-38
0.99955446 -0.39190739 -3.7850635 0
1.0004861 -0.39113209 -3.7883377 0
2.2351372 -0.38830552 -3.7930415 0
2.2506943 -0.38853291 -3.7924984 0
2.2710302 -0.39026159 -3.792146 0

头部存储了该pcd文件的格式,下面每一列都是一个点,按 x,y,z,rgb的方式存储。而第四列rgb显然就是以float形式保存的值了。注意到 很多都是 e-38 数量级,呼应了前面提到的高8位是空的,只有低24位存储了r,g,b值。

那么,这么多0 rgb,是不是就代表了前方缺失颜色的那部分点云呢。

思考缺失原因

pcl::io::savePCDFileASCII() 函数的.h文件中,作者提到了这么一句。

Caution: PointCloud structures containing an RGB field have traditionally used packed float values to store RGB data. Storing a float as ASCII can introduce variations to the smallest bits, and thus significantly alter the data. This is a known issue, and the fix involves switching RGB data to be stored as a packed integer in future versions of PCL.

即,使用ASCII存储float会导致最小位有一些偏差,这是已知的问题,将来pcl会尝试修复。

由于前面看到,rgb值达到 e-38 很小的数量级了,若引入一些偏差是否可能在保存过程中被约到0,于是产生颜色变黑的丢失情况?
当然这里只是作者的一个猜想。

问题解决

既然有问题在这,那么试试另一种存储方式。
pcl给了另一个格式的存储:
pcl::io::savePCDFileBinary()

Binary形式则无法按ASCII方式查看里面的文字了,但由于紧凑封装不会导致数据丢失。

尝试后,成功!!

PCL1.7 bug: 使用ASCII存储点云时导致的颜色丢失问题_第4张图片
原本黑色的颜色回来了。

希望对大家有所帮助。

参考资料

pcl/io/pcd_io.h
pcl/impl/point_types.hpp

你可能感兴趣的:(三维点云)