关于从asc格式到pcd格式的转换

本文介绍如何将.asc格式的点云数据转换为PCL库所需的.pcd格式,并解决了转换过程中遇到的实际问题。

最近一直在学习点云处理,从同学那里拿到的是asc格式,而点云库只认pcd格式(也是非常的任性),所以进行数据处理的第一步就是转换格式.
文章的主要内容有:


1.asc格式的说明

许多点云数据都是asc格式,如果做点云处理很可能会遇到.asc源于ascii,asc格式意味着该文件里的数据以ascii码的形式存储.如果要打开的话,可以用notepad++.

2.pcd格式的说明

如果打算用pcl来处理点云的话,那么点云需要先转化为pcd格式.pcd格式有很多版本,在点云库官网给的点云数据中,最常配到的版本为0.5版本和0.7版本.下面我以0.7版本为例说明.
每一个PCD文件包含一个文件头,它确定和声明文件中存储的点云数据的某种特性。PCD文件头必须用ASCII码来编码。PCD文件中指定的每一个文件头字段以及ascii点数据都用一个新行(\n)分开了,从0.7版本开始,PCD文件头包含下面的字段:

1.·VERSION –指定PCD文件版本

2 ·FIELDS –指定一个点可以有的每一个维度和字段的名字。例如:
FIELDS x y z # XYZ data
FIELDS x y z rgb # XYZ + colors
FIELDS x y z normal_xnormal_y normal_z # XYZ + surface normals
FIELDS j1 j2 j3 # moment invariants

3. SIZE –用字节数指定每一个维度的大小。例如:
unsigned char/char has 1 byte
unsigned short/short has 2 bytes
unsignedint/int/float has 4 bytes
double has 8 bytes

4.·TYPE –用一个字符指定每一个维度的类型。现在被接受的类型有:
I –表示有符号类型int8(char)、int16(short)和int32(int);
U – 表示无符号类型uint8(unsigned char)、uint16(unsigned short)和uint32(unsigned int);
F –表示浮点类型。

5.·COUNT –指定每一个维度包含的元素数目。例如,x这个数据通常有一个元素,但是像VFH这样的特征描述子就有308个。实际上这是在给每一点引入n维直方图描述符的方法,把它们当做单个的连续存储块。默认情况下,如果没有COUNT,所有维度的数目被设置成1。

6.·WIDTH –用点的数量表示点云数据集的宽度。根据是有序点云还是无序点云,WIDTH有两层解释:
1)它能确定无序数据集的点云中点的个数(和下面的POINTS一样);
2)它能确定有序点云数据集的宽度(一行中点的数目)。
注意:有序点云数据集,意味着点云是类似于图像(或者矩阵)的结构,数据分为行和列。这种点云的实例包括立体摄像机和时间飞行摄像机生成的数据。有序数据集的优势在于,预先了解相邻点(和像素点类似)的关系,邻域操作更加高效,这样就加速了计算并降低了PCL中某些算法的成本。

7.·HEIGHT –用点的数目表示点云数据集的高度。类似于WIDTH ,HEIGHT也有两层解释:
1)它表示有序点云数据集的高度(行的总数);
2)对于无序数据集它被设置成1(被用来检查一个数据集是有序还是无序)。

8.·VIEWPOINT–指定数据集中点云的获取视点。VIEWPOINT有可能在不同坐标系之间转换的时候应用,在辅助获取其他特征时也比较有用,例如曲面法线,在判断方向一致性时,需要知道视点的方位,
视点信息被指定为平移(txtytz)+四元数(qwqxqyqz)。默认值是:
VIEWPOINT 0 0 0 1 0 0 0

9.·POINTS–指定点云中点的总数。从0.7版本开始,该字段就有点多余了,因此有可能在将来的版本中将它移除。
例子:
POINTS 307200 #点云中点的总数为307200

10.·DATA –指定存储点云数据的数据类型。从0.7版本开始,支持两种数据类型:ascii和二进制。查看下一节可以获得更多细节。

注意:
文件头最后一行(DATA)的下一个字节就被看成是点云的数据部分了,它会被解释为点云数据。

警告:
PCD文件的文件头部分必须以上面的顺序精确指定,也就是如下顺序:
VERSION、FIELDS、SIZE、TYPE、COUNT、WIDTH、HEIGHT、VIEWPOINT、POINTS、DATA
之间用换行隔开。

3.代码思路

从pcd文件的格式可知,从asc到pcd转换的关键在于使其文件开头符合pcd格式要求。其中最主要的问题是的是如何动态设置WIDTH和POINTS的值,对于散乱点云,这两个值都可以表示点数.点数的获得可用asc文件的行数表示.
本文代码参考了python将指定点云文件(asc)转换为PCD格式。但在实际中,我发现一个问题:
asc文件的最后两行并非数字,而是如下图。这带来了两个麻烦,一是WIDTH的值会比实际值大2,二是生成的pcd文件中,最后两行并非数据。这两个现象会导致生成的数据无法无法被pcl程序读取。换句话说,生成的pcd文件不能用。
这里写图片描述

针对这个问题,我的解决思路如下:
1.将asc文件改为txt文件,将最后两行删除并保存。
2.程序读取txt文件,将其内容pcd文件中。

4. 代码

代码块语法遵循标准markdown代码,例如:

import time

from sys import argv
#script,filename = argv
filename = "2.txt"
print ("the input file name is:%r." %filename)

start = time.time()
print("open the file.....")
file = open(filename,"r+")
count = 0

for line in file:
    count=count+1
print("size is %d" %count)
file.close()

#output = open("out.pcd","w+")
f_prefix = filename.split('.')[0]
output_filename = '{prefix}.pcd'.format(prefix=f_prefix)
output = open(output_filename,"w+")

list = ['# .PCD v.5 - Point Cloud Data file format\n','VERSION .5\n','FIELDS x y z\n','SIZE 4 4 4\n','TYPE F F F\n','COUNT 1 1 1\n']
output.writelines(list)
output.write('WIDTH ')
output.write(str(count))
output.write('\nHEIGHT ')
output.write(str(1))
output.write('\nPOINTS ')
output.write(str(count))
output.write('\nDATA ascii\n')

file1 = open(filename,"r")
all = file1.read()
output.write(all)
output.close()
file1.close()

end = time.time()
print("run time is:",end-start)

5.效果图

这里写图片描述

补充

存储点云数据可以用简单的ascii形式,每点占据一行,用空格键或Tab键分开,没有其他任何字符。也可以用二进制存储格式,它既简单又快速,当然这依赖于用户应用。ascii格式允许用户打开点云文件,使用例如gunplot这样的标准软件工具更改点云文件数据,或者用sed、awk等工具来对它们进行操作。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值