参考文章:https://blog.csdn.net/xinguihu/article/details/78922005
KITTI数据集应该不用多做介绍了,基本上做自动驾驶的都知道这个东西。最近本人用到这个数据集想看看里面的点云长什么模样,却发现有点别扭,没有直接可以看的工具。因此想着转成PCD文件,然后用PCLViewer来看。因为不想用PCL,总感觉这东西配起来好烦,因此就想写纯C++的代码来转。因此也比较悲剧的需要了解PCD的格式,还好比较简单,下面先看看一个PCD文件:
在红色方框里的是文件的格式声明,比较少,而方框下面就是点云的XYZ坐标了。因此需要搞明白的地方比较少,就只有方框里面的声明是什么。
VERSION ---指定PCD文件版本,这个东西不写也没关系,可以正常运行
FIELDS ---指定一个点可以有的每一个维度和字段的名字,比如:
FIELDS x y z #正常的XYZ数据
FIELDS x y z rgb #正常的XYZ数据+点的颜色数据
SIZE ---用字节数指定每一个维度的大小,比如unsigned char或者char 就用1个byte,而unsigned int或者int或者float有4个byte
TYPE ---用一个字符指定每一个维度的类型
I –表示有符号类型int8(char)、int16(short)和int32(int);
U – 表示无符号类型uint8(unsigned char)、uint16(unsigned short)和uint32(unsigned int);
F –表示浮点类型。
COUNT ---指定每一个维度包含的元素数目。默认情况下,如果没有COUNT,所有维度的数目被设置成1。
WIDTH ---用点的数量表示点云数据集的宽度。根据是有序点云还是无序点云,WIDTH有两层解释:
1)它能确定无序数据集的点云中点的个数(和下面的POINTS一样);
2)它能确定有序点云数据集的宽度(一行中点的数目)。
注意:有序点云数据集,意味着点云是类似于图像(或者矩阵)的结构,数据分为行和列。这种点云的实例包括立体摄像机和时间飞行摄像机生成的数据。有序数据集的优势在于,预先了解相邻点(和像素点类似)的关系,邻域操作更加高效,这样就加速了计算并降低了PCL中某些算法的成本。
HEIGHT ---用点的数目表示点云数据集的高度。类似于WIDTH ,HEIGHT也有两层解释:
1)它表示有序点云数据集的高度(行的总数);
2)对于无序数据集它被设置成1(被用来检查一个数据集是有序还是无序)。
VIEWPOINT ---指定数据集中点云的获取视点。
VIEWPOINT有可能在不同坐标系之间转换的时候应用,在辅助获取其他特征时也比较有用,例如曲面法线,在判断方向一致性时,需要知道视点的方位,视点信息被指定为平移(txtytz)+四元数(qwqxqyqz)。
默认值是:VIEWPOINT 0 0 0 1 0 0 0
POINTS ---指定点云中点的总数。从0.7版本开始,该字段就有点多余了,因此有可能在将来的版本中将它移除。
OK,字段的释义就到这里,知道了这些我们可以将其中默认的字段删掉,也就是把上面截图中的数据格式改的更加简单一点,如下:
下面我们就只需要照着格式编写就可以了,KITTI的点云bin文件的解析因为相当简单请参考官方说明,下面放出读取bin文件并转为PCD的代码:
#include <iostream>
void main()
{
int32_t num = 1000000;
float *data = (float*)malloc(num * sizeof(float));
// 点
float *px = data + 0;
float *py = data + 1;
float *pz = data + 2;
float *pr = data + 3;//反射强度
// 读取点云数据
FILE *stream;
fopen_s(&stream, "um_000000.bin", "rb");
num = fread(data, sizeof(float), num, stream) / 4;//读入点云数据,大概10万+个点
fclose(stream);
/**转换成PCD**/
//写文件声明
FILE *writePCDStream;
fopen_s(&writePCDStream, "um_000000.pcd", "wb");
fprintf(writePCDStream, "VERSION 0.7\n");//版本说明
fprintf(writePCDStream, "FIELDS x y z\n");//维度说明
fprintf(writePCDStream, "SIZE 4 4 4\n");//占用字节说明
fprintf(writePCDStream, "TYPE F F F\n");//具体数据类型定义
fprintf(writePCDStream, "WIDTH %d\n", num);//点数量
fprintf(writePCDStream, "HEIGHT 1\n");//无序点云默认为1
fprintf(writePCDStream, "POINTS %d\n", num);//点数量
fprintf(writePCDStream, "DATA ascii\n");//文档使用字符类型shuom
//写点云数据
for (int32_t i = 0; i < num; i++)
{
fprintf(writePCDStream, "%f %f %f\n",*px,*py,*pz);
px += 4; py += 4; pz += 4; pr += 4;
}
fclose(writePCDStream);
}
转换出来的文件可以用PCLViewer打开,效果如下:
另外,如果需要PCLViewer,本人已经提取了最小的可运行包,可在这里下载:(比较贵哈哈,如果运行不了请自己安装VS2017运行库,再运行不了可以留言骂我哈哈哈)