ScanNet 数据集处理(一)

您所在的位置:网站首页 json数据集如何使用 ScanNet 数据集处理(一)

ScanNet 数据集处理(一)

2024-03-01 05:18| 来源: 网络整理| 查看: 265

最近在做毕业设计,课题研究对象就是ScanNet数据集Scannet主页,所以也学到了一些处理点云的方法。在这里记录一下。

数据集简介

下载完数据集后,内部结果如下所示,每一个场景一个文件夹。

|-- _vh_clean.ply (Updated if had remove annotations) |-- _vh_clean_2.ply (Updated if had remove annotations) |-- .aggregation.json, _vh_clean.aggregation.json Updated aggregated instance-level semantic annotations on lo-res, hi-res meshes, respectively |-- _vh_clean_2.labels.ply Updated visualization of aggregated semantic segmentation; colored by nyu40 labels (see legend referenced above; ply property 'label' denotes the ScanNet label id) |-- _2d-label.zip Updated raw 2d projections of aggregated annotation labels as 16-bit pngs with ScanNet label ids |-- _2d-instance.zip Updated raw 2d projections of aggregated annotation instances as 8-bit pngs |-- _2d-label-filt.zip Updated filtered 2d projections of aggregated annotation labels as 16-bit pngs with ScanNet label ids |-- _2d-instance-filt.zip Updated filtered 2d projections of aggregated annotation instances as 8-bit pngs

如下图所示:

其中scene0000_00_vh_clean.ply和scene0000_00_vh_clean_2.ply都是点云图像的ply文件(两者清晰度不同),可以直接用meshlab打开,也可用open3d绘制。但是可以看出,整幅点云图像对于坐标轴原点来讲是有偏移的。

在这里插入图片描述

scene0000_00_vh_clean_2.labels.ply是带标签的点云,是分隔之后的结果。 在这里插入图片描述

可以看出,以上3幅图对于远点都是有偏移的。那么如何处理便宜呢?

3D点云处理偏移

在文件夹下,有一个scene0000_00.txt文件,第一行axisAlignment就是坐标偏移。

点的处理偏移 if __name__ == '__main__': # 1. 得到 ply 文件,分别得到 x, y, z, r, g, b filename = os.path.join(ROOT, "scene0000_00_vh_clean_2.ply") with open(filename, 'rb') as f: plydata = PlyData.read(f) num_verts = plydata['vertex'].count vertices = np.zeros(shape=[num_verts, 6], dtype=np.float32) vertices[:, 0] = plydata['vertex'].data['x'] vertices[:, 1] = plydata['vertex'].data['y'] vertices[:, 2] = plydata['vertex'].data['z'] vertices[:, 3] = plydata['vertex'].data['red'] vertices[:, 4] = plydata['vertex'].data['green'] vertices[:, 5] = plydata['vertex'].data['blue'] # 2. 得到偏移 meta_file = os.path.join(ROOT, "scene0000_00.txt") lines = open(meta_file).readlines() axis_align_matrix = None for line in lines: if 'axisAlignment' in line: axis_align_matrix = [float(x) for x in line.rstrip().strip('axisAlignment = ').split(' ')] # 3. 将点云 ply 文件偏移 if axis_align_matrix != None: axis_align_matrix = np.array(axis_align_matrix).reshape((4, 4)) # 转换偏移矩阵 pts = np.ones((vertices.shape[0], 4)) pts[:, 0:3] = vertices[:, :3] pts = np.dot(pts, axis_align_matrix.transpose()) aligned_vertices = np.copy(vertices) aligned_vertices[:, 0:3] = pts[:, 0:3] # 4. 重新写回 ply points = aligned_vertices[:,:3] colors = aligned_vertices[:,3:6] write_ply_rgb(points, colors, "/root/Desktop/wbb_test/aligned.ply") print("end")

其中write_ply_rgb如下定义,只要给出点云中的点和其对应颜色,就可以写成 ply 文件。

def write_ply_rgb(points, colors, filename, text=True, num_classes=None): """ Color (N,3) points with RGB colors (N,3) within range [0,255] as OBJ file """ colors = colors.astype(int) points = [(points[i,0], points[i,1], points[i,2], colors[i,0], colors[i,1], colors[i,2]) for i in range(points.shape[0])] vertex = np.array(points, dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4'),('red', 'u1'), ('green', 'u1'),('blue', 'u1')]) el = PlyElement.describe(vertex, 'vertex', comments=['vertices']) PlyData([el], text=text).write(filename)

但是这个是没有加面片的,效果如下: 在这里插入图片描述

点+面片的偏移处理

如果想得到 vertices 和 mesh的偏移,必须从ply文件中读取这两个东西。当我们用plydata = PlyData.read(f)打开我们的ply文件之后,发现有两个element:vertex 和 face,所以我们必须读两个东西。

def read_mesh(filename): """ read XYZ for each vertex. """ assert os.path.isfile(filename) with open(filename, 'rb') as f: plydata = PlyData.read(f) num_verts = plydata['vertex'].count vertices = np.zeros(shape=[num_verts, 6], dtype=np.float32) vertices[:, 0] = plydata['vertex'].data['x'] vertices[:, 1] = plydata['vertex'].data['y'] vertices[:, 2] = plydata['vertex'].data['z'] vertices[:, 3] = plydata['vertex'].data['red'] vertices[:, 4] = plydata['vertex'].data['green'] vertices[:, 5] = plydata['vertex'].data['blue'] return vertices, plydata['face'] def write_mesh(vertices, faces): new_vertices = [] for i in range(vertices.shape[0]): new_vertices.append( ( vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3], vertices[i][4], vertices[i][5], ) ) vertices = np.array( new_vertices, dtype=[ ("x", np.dtype("float32")), ("y", np.dtype("float32")), ("z", np.dtype("float32")), ("red", np.dtype("uint8")), ("green", np.dtype("uint8")), ("blue", np.dtype("uint8")) ] ) vertices = PlyElement.describe(vertices, "vertex") mesh = PlyData([vertices, faces]) mesh.write("/root/Desktop/aligned_mesh.ply")

face用点的索引来构成,所以只要点的索引不变,只需要处理点就可以达到面片的偏移。

# 1. read pc filename = os.path.join(ROOT, "scene0000_00_vh_clean_2.ply") vertices, faces = read_mesh(filename) # 2. 得到偏移 meta_file = os.path.join(ROOT, "scene0000_00.txt") lines = open(meta_file).readlines() axis_align_matrix = None for line in lines: if 'axisAlignment' in line: axis_align_matrix = [float(x) for x in line.rstrip().strip('axisAlignment = ').split(' ')] # 3. 将点云 ply 文件偏移 if axis_align_matrix != None: axis_align_matrix = np.array(axis_align_matrix).reshape((4, 4)) pts = np.ones((vertices.shape[0], 4)) pts[:, 0:3] = vertices[:, :3] pts = np.dot(pts, axis_align_matrix.transpose()) aligned_vertices = np.copy(vertices) aligned_vertices[:, 0:3] = pts[:, 0:3] write_mesh(aligned_vertices, faces)

在这里插入图片描述 可以发现,已经在原点了。

点的标签

scene0000_00_vh_clean.aggregation.json 文件如下所示: 在这里插入图片描述 segGroups的总数就是这副场景中的实例个数。如果label相同,但是objectId不同,说明是同种类但是不是同物体。所以可以从中得到实例数,也可以得到同种类别的物体的数量。

scene0000_00_vh_clean_2.0.010000.segs.json文件中表示每个点的seg标签,即所有的点的segIndices是什么。 在这里插入图片描述

总结起来就是,对于每个点有一个标签,对应segIndices。根据这个标签和scene0000_00_vh_clean.aggregation.json中的数据,就可以给不同实例/类别打上标签。

bounding-box

接下来是如何提取一个物体的 bounding-box(bbox)。 假设bbox = [center_x, center_y, center_z, length_x, length_y, length_z]

就是根据实例标签,获得对应的所有点以及(x,y,z)坐标。找到3个方向的边缘: x min , x max , y min , y max , z min , z max x_{\text{min}}, x_{\text{max}},y_{\text{min}}, y_{\text{max}},z_{\text{min}}, z_{\text{max}} xmin​,xmax​,ymin​,ymax​,zmin​,zmax​得到bbox的表示形式 代码如下: xmin = np.min(obj_pc[:, 0]) ymin = np.min(obj_pc[:, 1]) zmin = np.min(obj_pc[:, 2]) xmax = np.max(obj_pc[:, 0]) ymax = np.max(obj_pc[:, 1]) zmax = np.max(obj_pc[:, 2]) bbox = np.array([(xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2, xmax - xmin, ymax - ymin, zmax - zmin) 画出bounding-box

根据给的(cx, cy, cz, lx, ly, lz)画出边界框。具体下篇再介绍。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3