在研究生的一些项目中,会用python语言读取3D模型,3D模型通常有很多种类,但我的研究领域,通常用到ply格式的文件,因此,我今天晚上写一个博客来实现用python读取3D模型。
我的项目是位姿估计,往往用到3D模型,一般在数据预处理的时候用,代码通常在dataset之类的文件中。
我目前知道两种方式来读取,一种是非常原始的自己写代码去实现,另一种是导入plyfile库来实现,下文实现一下两种方法。
ply数据格式如下:
ply
format ascii 1.0
comment created by MATLAB plywrite
element vertex 15736
property float x
property float y
property float z
property float nx
property float ny
property float nz
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 31468
property list uchar int vertex_indices
end_header
-0.010831 -0.053978 -0.019356 -0.102670 -0.925927 0.363479 185 114 125 255
-0.017599 0.049901 0.031044 -0.332934 0.007306 0.942922 219 142 156 255
-0.026096 0.033232 0.026992 -0.795885 0.288249 0.532428 219 148 164 255
-0.008255 0.042918 -0.010170 -0.308618 0.734994 -0.603770 188 119 133 255
//下面还有很多,还有面的信息,省略不写了,我的项目用不到
上图中,有用的只有数据行里的签上列,也就是x、y、z坐标,3个合在一起就是一个点的坐标,得到所有点的坐标(往往得上千个)。
调库的实现方法:
from plyfile import PlyData
def load_ply_vtx(pth):
"""
load object vertices
:param pth: str
:return: pts: (N, 3)
"""
# ply就是得到的对象
ply = PlyData.read(pth)
# vtx相当于得到的所有的点的信息,每个点有10个属性
vtx = ply['vertex']
# 只要有用的3个属性,stack得到的列表是一堆x,一堆y,一堆z,
# 我们要对其进行转换,axis=-1是在列的维度拼接,
# 变成一个x,一个y,一个z这种的格式,
pts = np.stack([vtx['x'], vtx['y'], vtx['z']], axis=-1)
return pts
自己写的方式:
def ply_vtx(path):
f = open(path)
# 断言必是ply格式的3D模型
assert f.readline().strip() == "ply"
# 读取不需要的行
f.readline()
f.readline()
# 第4行的最后一列是模型的点数,读出来
N = int(f.readline().split()[-1])
# 读取不需要的行,strip()代表除掉行前后多余的空格
while f.readline().strip() != "end_header":
continue
# 读取点
pts = []
for _ in range(N):
# 每行可能有超过3列的数据,只要前3个,分别是x、y、z
pts.append(np.float32(f.readline().split()[:3]))
return np.array(pts)
显然调库的方式更简单,代码少,出问题的概率也比较小。