KITTI数据集的点云格式转PCD格式

参考文章: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运行库,再运行不了可以留言骂我哈哈哈)

如果要存成带颜色的点,则修改代码如下即可(颜色值设置过小会显示不出来,不知道为什么):

//将点云存成pcd文件
void saveaspcd(vector<pointcloud> &mPoint)
{
	FILE *writePCDStream;
	fopen_s(&writePCDStream, "save.pcd", "wb");
	fprintf(writePCDStream, "VERSION 0.7\n");//版本说明
	fprintf(writePCDStream, "FIELDS x y z rgb\n");//维度说明
	fprintf(writePCDStream, "SIZE 4 4 4 4\n");//占用字节说明
	fprintf(writePCDStream, "TYPE F F F F\n");//具体数据类型定义
	fprintf(writePCDStream, "WIDTH %d\n", mPoint.size());//点数量
	fprintf(writePCDStream, "HEIGHT 1\n");//无序点云默认为1
	fprintf(writePCDStream, "POINTS %d\n", mPoint.size());//点数量
	fprintf(writePCDStream, "DATA ascii\n");//文档使用字符类型shuom
	//写点云数据
	for (int i = 0; i < mPoint.size(); i++)
	{
		int r = 10, g = 255, b = 0;//这里红色取太小就不能正确显示出颜色,原因不明。有需要再来研究下为什么。
		int rgb = (r << 16 | g << 8 | b);
		float frgb = (float)rgb;
		fprintf(writePCDStream, "%10.6f %10.6f %10.6f %+e\n", mPoint[i].x, mPoint[i].y, mPoint[i].z, frgb);
	}
	fclose(writePCDStream);
}

 

 

 

 

 

  • 11
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值