def save_ply(path_out, points, colors, faces=None): vertex = np.array([tuple(p) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_color = np.array([tuple(c) for c in colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) n = len(vertex) assert len(vertex_color) == n vertex_all = np.empty(n, dtype=vertex.dtype.descr + vertex_color.dtype.descr) for prop in vertex.dtype.names: vertex_all[prop] = vertex[prop] for prop in vertex_color.dtype.names: vertex_all[prop] = vertex_color[prop]\ if faces is not None: face = np.array([tuple([f]) for f in faces], dtype=[('vertex_indices', 'i4', (3, ))]) ply = plyfile.PlyData([ plyfile.PlyElement.describe(vertex_all, 'vertex'), plyfile.PlyElement.describe(face, 'face') ], text=False) else: ply = plyfile.PlyData( [plyfile.PlyElement.describe(vertex_all, 'vertex')], text=False) ply.write(path_out)
def read_ply(filename): """ Reads vertices and faces from a ply file. :param file: path to file to read :type file: str :return: vertices and faces as lists of tuples :rtype: [(float)], [(int)] """ plydata = plyfile.PlyData().read(filename) vertices = [list(x) for x in plydata['vertex']] # Element 0 is the vertex fn2 = filename[:-3] + 'labels.ply' a = plyfile.PlyData().read(fn2) label = remapper[np.array(a.elements[0]['label'])] def append_label(zipped_value): vertex, label = zipped_value vertex.append(label) return vertex vertices = list(map(append_label, zip(vertices, label))) faces = [x.tolist() for x in plydata['face'].data['vertex_indices']] return vertices, faces
def visualize_campos(campos, output_file, normals=None, transform=None): assert (len(campos.shape) == 3) verts = [] norms = [] for r in range(campos.shape[0]): for c in range(campos.shape[1]): if campos[r, c, 0] == -float('inf'): continue if normals is not None and (normals[r, c, 0] == -float('inf') or np.all(normals[r, c] == 0)): continue verts.append(campos[r, c]) if normals is not None: norms.append(normals[r, c]) verts = np.stack(verts) if norms: norms = np.stack(norms) if transform is not None: x = np.ones((verts.shape[0], 4)) x[:, :3] = verts x = np.matmul(transform, np.transpose(x)) x = np.transpose(x) verts = np.divide(x[:, :3], x[:, 3, None]) if normals is None: verts = np.array([tuple(v) for v in verts], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) el = plyfile.PlyElement.describe(verts, 'vertex') plyfile.PlyData([el]).write(output_file) else: verts = np.concatenate([verts, norms], 1) verts = np.array([tuple(v) for v in verts], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4')]) el = plyfile.PlyElement.describe(verts, 'vertex') plyfile.PlyData([el]).write(output_file)
def f(fn): fn2 = fn[:-3]+'labels.ply' a=plyfile.PlyData().read(fn) v=np.array([list(x) for x in a.elements[0]]) coords=np.ascontiguousarray(v[:,:3]-v[:,:3].mean(0)) colors=np.ascontiguousarray(v[:,3:6])/127.5-1 a=plyfile.PlyData().read(fn2) w=remapper[np.array(a.elements[0]['label'])] torch.save((coords,colors,w),fn[:-4]+'.pth') print(fn, fn2)
def f(fn): fn2 = fn[:-3] + 'labels.ply' fn3 = fn[:-15] + '_vh_clean_2.0.010000.segs.json' fn4 = fn[:-15] + '.aggregation.json' print(fn) f = plyfile.PlyData().read(fn) points = np.array([list(x) for x in f.elements[0]]) coords = np.ascontiguousarray(points[:, :3] - points[:, :3].mean(0)) colors = np.ascontiguousarray(points[:, 3:6]) / 127.5 - 1 f2 = plyfile.PlyData().read(fn2) sem_labels = remapper[np.array(f2.elements[0]['label'])] with open(fn3) as jsondata: d = json.load(jsondata) seg = d['segIndices'] segid_to_pointid = {} for i in range(len(seg)): if seg[i] not in segid_to_pointid: segid_to_pointid[seg[i]] = [] segid_to_pointid[seg[i]].append(i) instance_segids = [] labels = [] with open(fn4) as jsondata: d = json.load(jsondata) for x in d['segGroups']: if scannet_util.g_raw2scannetv2[ x['label']] != 'wall' and scannet_util.g_raw2scannetv2[ x['label']] != 'floor': instance_segids.append(x['segments']) labels.append(x['label']) assert (x['label'] in scannet_util.g_raw2scannetv2.keys()) if (fn == 'val/scene0217_00_vh_clean_2.ply' and instance_segids[0] == instance_segids[int( len(instance_segids) / 2)]): instance_segids = instance_segids[:int(len(instance_segids) / 2)] check = [] for i in range(len(instance_segids)): check += instance_segids[i] assert len(np.unique(check)) == len(check) instance_labels = np.ones(sem_labels.shape[0]) * -100 for i in range(len(instance_segids)): segids = instance_segids[i] pointids = [] for segid in segids: pointids += segid_to_pointid[segid] instance_labels[pointids] = i assert (len(np.unique(sem_labels[pointids])) == 1) torch.save((coords, colors, sem_labels, instance_labels), fn[:-15] + '_inst_nostuff.pth') print('Saving to ' + fn[:-15] + '_inst_nostuff.pth')
def f(fn): fn2 = fn[:-3] + 'labels.ply' a = plyfile.PlyData().read(fn) v = np.array([list(x) for x in a.elements[0] ]) #elements[0] stores all vertices with [x,y,z,r,g,b,alpha] coords = np.ascontiguousarray(v[:, :3] - v[:, :3].mean(0)) colors = np.ascontiguousarray(v[:, 3:6]) / 127.5 - 1 a = plyfile.PlyData().read(fn2) w = remapper[np.array(a.elements[0]['label'])] torch.save((coords, colors, w), fn[:-4] + '.pth') #saves for each vertex the coordinates, color and label print(fn, fn2)
def func(fn, ft): fn1 = dataset_dir +fn + '/'+ fn + '_vh_clean_2.ply' fn2 = fn1[:-3]+'labels.ply' a=plyfile.PlyData().read(fn1) v=np.array([list(x) for x in a.elements[0]]) #elements[0] stores all vertices with [x,y,z,r,g,b,alpha] coords=np.ascontiguousarray(v[:,:3]-v[:,:3].mean(0)) colors=np.ascontiguousarray(v[:,3:6])/127.5-1 a=plyfile.PlyData().read(fn2) w = remapper[np.array(a.elements[0]['label'])] save_path = txt_dir + ft + '_21classes/' + fn +'.pth' #save_path = txt_dir + ft + '_40classes/' + fn + '.pth' torch.save((coords,colors,w),save_path) #saves for each vertex the coordinates, color and label print(fn1, fn2)
def f(fn): fn2 = fn[:-3] + 'labels.ply' a = plyfile.PlyData().read(fn) v = np.array([list(x) for x in a.elements[0]]) # (81369, 7) coords = np.ascontiguousarray(v[:, :3] - v[:, :3].mean(0)) # (81369, 3) colors = np.ascontiguousarray(v[:, 3:6]) / 127.5 - 1 # colors a = plyfile.PlyData().read(fn2) label = np.array(a.elements[0]['label']) label = np.minimum(label, 149) w = remapper[label] fn_3 = (fn[:-4] + '.pth').replace(root_path, save_path) dir_3 = os.path.dirname(fn_3) if not os.path.exists(dir_3): os.makedirs(dir_3) torch.save((coords, colors, w), fn_3) print(fn, fn2, fn_3)
def save_ply_with_face(points, faces, filename, colors=None): vertex = np.array([tuple(p) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) faces = np.array([(tuple(p), ) for p in faces], dtype=[('vertex_indices', 'i4', (3, ))]) descr = faces.dtype.descr if colors is not None: assert len(colors) == len(faces) face_colors = np.array([tuple(c * 255) for c in colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) descr = faces.dtype.descr + face_colors.dtype.descr faces_all = np.empty(len(faces), dtype=descr) for prop in faces.dtype.names: faces_all[prop] = faces[prop] if colors is not None: for prop in face_colors.dtype.names: faces_all[prop] = face_colors[prop] ply = plyfile.PlyData([ plyfile.PlyElement.describe(vertex, 'vertex'), plyfile.PlyElement.describe(faces_all, 'face') ], text=False) ply.write(filename)
def extract_mesh_marching_cubes(path, volume, color=None, level=0.5, step_size=1.0, gradient_direction="ascent"): if level > volume.max() or level < volume.min(): return verts, faces, normals, values = marching_cubes_lewiner( volume, level=level, step_size=step_size, gradient_direction=gradient_direction) ply_verts = np.empty(len(verts), dtype=[("x", "f4"), ("y", "f4"), ("z", "f4")]) ply_verts["x"] = verts[:, 0] ply_verts["y"] = verts[:, 1] ply_verts["z"] = verts[:, 2] ply_verts = plyfile.PlyElement.describe(ply_verts, "vertex") if color is None: ply_faces = np.empty( len(faces), dtype=[("vertex_indices", "i4", (3,))]) else: ply_faces = np.empty( len(faces), dtype=[("vertex_indices", "i4", (3,)), ("red", "u1"), ("green", "u1"), ("blue", "u1")]) ply_faces["red"] = color[0] ply_faces["green"] = color[1] ply_faces["blue"] = color[2] ply_faces["vertex_indices"] = faces ply_faces = plyfile.PlyElement.describe(ply_faces, "face") with tempfile.NamedTemporaryFile(dir=".", delete=False) as tmpfile: plyfile.PlyData([ply_verts, ply_faces]).write(tmpfile.name) shutil.move(tmpfile.name, path)
def writeCorrespondencesMesh(num_verts,num_faces,mesh_points,faces,sdf_color,deltas,ply_filename_out): correspondence_debug_verts = np.zeros((num_verts * 3,), dtype=[("x", "f4"), ("y", "f4"), ("z", "f4")] + [('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) correspondence_debug_faces_building = [] for i in range(0, num_faces): correspondence_debug_faces_building.append(((faces[i,:].tolist(),))) for i in range(0, num_faces): tempFaces = num_verts+2*faces[i,:] correspondence_debug_faces_building.append(((tempFaces.tolist(),))) idx = 0 R = np.array([[0,0,1],[0,1,0],[-1,0,0]]) for i in range(0, num_verts): col = np.array([int(sdf_color[i, 0]), int(sdf_color[i, 1]), int(sdf_color[i, 2])]) temp = mesh_points[i,:].dot(R) curr_vert = temp + deltas[i, :].dot(R) + np.array([-1, 0, 0]) correspondence_debug_verts[i] = tuple(np.append(temp, col)) correspondence_debug_verts[idx + num_verts] = tuple(np.append(curr_vert, col)) correspondence_debug_verts[idx + 1 + num_verts] = tuple(np.append(curr_vert, col)) factor = int(num_verts/3000) if i%factor == 0: correspondence_debug_faces_building.append((([i, idx + num_verts, idx + 1 + num_verts],))) idx = idx + 2 correspondence_debug_faces = np.array(correspondence_debug_faces_building, dtype=[("vertex_indices", "i4", (3,))]) el_verts = plyfile.PlyElement.describe(correspondence_debug_verts, "vertex") el_faces = plyfile.PlyElement.describe(correspondence_debug_faces, "face") ply_data = plyfile.PlyData([el_verts, el_faces]) logging.info("saving mesh to %s" % (ply_filename_out)) correspondence_debug_ply_filename_out = ply_filename_out[:-4] + "_correspondences" + ".ply" ply_data.write(correspondence_debug_ply_filename_out)
def main(args=None): if args is None: args = sys.argv[1:] _mode_to_func = { 'matrix': depthMapMatrix, 'loop': depthMapLoop, } parser = argparse.ArgumentParser() parser.add_argument('--mode', default='matrix', choices=list(_mode_to_func.keys()), help='3D point calculation method, defaults to matrix') parser.add_argument('--fx', type=float, default=5.8818670481438744e+02, help='Horizontal focal length') parser.add_argument('--fy', type=float, default=5.8724220649505514e+02, help='Vertical focal length') parser.add_argument('--cx', type=float, default=3.1076280589210484e+02, help='Horzontal principal point correction') parser.add_argument('--cy', type=float, default=2.2887144980135292e+02, help='Vertical principal point correction') parser.add_argument('--skipinvalid', default=False, action='store_true', help='Flag controlling the exclusion of points with depth value of zero, defaults to False') parser.add_argument('--plyfile', default='output.ply', help='Output PLY file path, defaults to output.ply') parser.add_argument('DEPTHFILE', nargs='?', default='depth.tif', help='Input depth channel file path, defaults to depth.tif') parser.add_argument('COLORFILE', nargs='?', default='color.tif', help='Input color channel file path, defaults to color.tif') args = parser.parse_args(args) print('Reading depth channel file {:s}'.format(args.DEPTHFILE)) imgDepth = cv.imread(args.DEPTHFILE, cv.IMREAD_UNCHANGED) if imgDepth is None: raise IOError('Unable to read file {:s}'.format(args.DEPTHFILE)) print('Reading color channel file {:s}'.format(args.COLORFILE)) imgColor = cv.imread(args.COLORFILE, cv.IMREAD_UNCHANGED) if imgColor is None: raise IOError('Unable to read file {:s}'.format(args.COLORFILE)) if imgDepth.shape[:2] != imgColor.shape[:2]: raise ValueError('Dimensions of depth channel and color channel mismatch: {} != {}'.format(imgDepth.shape[:2], imgColor.shape[:2])) print('Operation mode {:s}'.format(args.mode)) print('{:s} invalid depth values'.format('Skipping' if args.skipinvalid else 'Including')) t0 = time.perf_counter() vertices = _mode_to_func[args.mode]( args.fx, args.fy, args.cx, args.cy, imgDepth, imgColor, args.skipinvalid, ) t1 = time.perf_counter() print('Took {:.4f} s'.format(t1 - t0)) print('{:d} vertices'.format(len(vertices))) plyVertices = np.array(vertices, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) plyVertices = ply.PlyElement.describe(plyVertices, 'vertex') print('Writing PLY data to {:s}'.format(args.plyfile)) ply.PlyData([plyVertices]).write(args.plyfile) return 0
def write(self, path): #coordinate_array = self.points[["x", "y", "z"]].values.T #vertex_array = list(zip(coordinate_array[0],coordinate_array[1], coordinate_array[2])) #vertex_array = np.array(vertex_array, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_array = self.points.to_records(index=False) elements = plyfile.PlyElement.describe(vertex_array, 'vertex') plyfile.PlyData([elements]).write(path)
def writeply(plydata, dataChannel, newChannelName, fname): """ Writes data to the plyfile @param data: the data to convert in ply @paramtype data: numpy.ndarray @param fname: the name of the ply file @paramtype fname: string :return: ply data :rtype: plydata """ dtype = plydata.elements[0].data.dtype.descr newdtype = dtype + [(newChannelName, 'u1')] vertex = plydata.elements[0].name data = [] for i in range(len(dataChannel)): l = tuple( list(plydata[vertex][i]) + [dataChannel[i]]) data.append(l) data = np.array(data, newdtype) el = plyfile.PlyElement.describe(data, 'vertex') plyfile.PlyData([el], text=True).write(fname) return data
def save_ply(points, colors, filename): vertex = np.array([tuple(p) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_color = np.array([tuple(c) for c in colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) n = len(vertex) assert len(vertex_color) == n vertex_all = np.empty(n, dtype=vertex.dtype.descr + vertex_color.dtype.descr) for prop in vertex.dtype.names: vertex_all[prop] = vertex[prop] for prop in vertex_color.dtype.names: vertex_all[prop] = vertex_color[prop] ply = plyfile.PlyData([plyfile.PlyElement.describe(vertex_all, 'vertex')], text=False) ply.write(filename) print("save ply to", filename)
def save_to_ply(verts, verts_warped, faces, ply_filename_out): num_verts = verts.shape[0] num_faces = faces.shape[0] # store canonical coordinates as rgb color (in float format) verts_color = 255 * (0.5 + 0.5 * verts_warped) verts_color = verts_color.astype(np.uint8) verts_tuple = np.zeros((num_verts, ), dtype=[("x", "f4"), ("y", "f4"), ("z", "f4"), ("red", "f4"), ("green", "f4"), ("blue", "f4")]) for i in range(0, num_verts): verts_tuple[i] = (verts[i][0], verts[i][1], verts[i][2], verts_color[i][0], verts_color[i][1], verts_color[i][2]) faces_building = [] for i in range(0, num_faces): faces_building.append(((faces[i, :].tolist(), ))) faces_tuple = np.array(faces_building, dtype=[("vertex_indices", "i4", (3, ))]) el_verts = plyfile.PlyElement.describe(verts_tuple, "vertex") el_faces = plyfile.PlyElement.describe(faces_tuple, "face") ply_data = plyfile.PlyData([el_verts, el_faces]) logging.debug("saving mesh to %s" % (ply_filename_out)) ply_data.write(ply_filename_out)
def f(fn): print(fn[:-4] + '.pth') if os.path.exists(fn[:-4] + '.pth'): return #fn2 = fn[:-3]+'labels.ply' a = plyfile.PlyData().read(fn) v = np.array([list(x) for x in a.elements[0]]) coords = np.ascontiguousarray(v[:, :3] - v[:, :3].mean(0)) colors = np.ascontiguousarray(v[:, 3:6]) / 127.5 - 1 #a=plyfile.PlyData().read(fn2) #w=remapper[np.array(a.elements[0]['label'])] #filename = ROOT_FOLDER + scene_id + '/' + scene_id + '.aggregation.json' data = json.load( open(fn.replace('vh_clean_2.ply', 'aggregation.json'), 'r')) aggregation = np.array(data['segGroups']) data = json.load( open(fn.replace('vh_clean_2.ply', 'vh_clean_2.0.010000.segs.json'), 'r')) segmentation = np.array(data['segIndices']) groupSegments = [] groupLabels = [] for segmentIndex in xrange(len(aggregation)): groupSegments.append(aggregation[segmentIndex]['segments']) groupLabels.append(aggregation[segmentIndex]['label']) continue segmentation = segmentation.astype(np.int32) torch.save((coords, colors, w, instance), fn[:-4] + '.pth')
def save_ply_with_face(faces, filename, points, colors=None, binary=True): if points.shape[-1] == 2: points = np.concatenate([points, np.zeros_like(points)[:, :1]], axis=-1) vertex = np.array([tuple(p) for p in points], dtype=[ ('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) faces = np.array([(tuple(p),) for p in faces], dtype=[ ('vertex_indices', 'i4', (len(faces[0]), ))]) descr = faces.dtype.descr if colors is not None: assert len(colors) == len(faces) face_colors = np.array([tuple(c * 255) for c in colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) descr = faces.dtype.descr + face_colors.dtype.descr faces_all = np.empty(len(faces), dtype=descr) for prop in faces.dtype.names: faces_all[prop] = faces[prop] if colors is not None: for prop in face_colors.dtype.names: faces_all[prop] = face_colors[prop] ply = plyfile.PlyData([plyfile.PlyElement.describe( vertex, 'vertex'), plyfile.PlyElement.describe(faces_all, 'face')], text=(not binary)) if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) ply.write(filename)
def save_ply(points, filename, colors=None, normals=None, binary=True): """ save 3D/2D points to ply file Args: points (numpy array): (N,2or3) colors (numpy uint8 array): (N, 3or4) """ if points.shape[-1] == 2: points = np.concatenate([points, np.zeros_like(points)[:, :1]], axis=-1) vertex = np.core.records.fromarrays(points.transpose(1, 0), names='x, y, z', formats='f4, f4, f4') num_vertex = len(vertex) desc = vertex.dtype.descr if normals is not None: if normals.shape[-1] == 2: normals = np.concatenate( [normals, np.zeros_like(normals)[:, :1]], axis=-1) vertex_normal = np.core.records.fromarrays(normals.transpose(1, 0), names='nx, ny, nz', formats='f4, f4, f4') assert len(vertex_normal) == num_vertex desc = desc + vertex_normal.dtype.descr if colors is not None: assert len(colors) == num_vertex if colors.max() <= 1: colors = colors * 255 if colors.shape[1] == 4: vertex_color = np.core.records.fromarrays( colors.transpose(1, 0), names='red, green, blue, alpha', formats='u1, u1, u1, u1') else: vertex_color = np.core.records.fromarrays(colors.transpose(1, 0), names='red, green, blue', formats='u1, u1, u1') desc = desc + vertex_color.dtype.descr vertex_all = np.empty(num_vertex, dtype=desc) for prop in vertex.dtype.names: vertex_all[prop] = vertex[prop] if normals is not None: for prop in vertex_normal.dtype.names: vertex_all[prop] = vertex_normal[prop] if colors is not None: for prop in vertex_color.dtype.names: vertex_all[prop] = vertex_color[prop] ply = plyfile.PlyData([plyfile.PlyElement.describe(vertex_all, 'vertex')], text=(not binary)) if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) ply.write(filename)
def main(): args = parse_args() mesh = plyfile.PlyData().read(os.path.join(args.scene_path, "mesh.ply")) ## load vertex v = np.array([list(x) for x in mesh.elements[0]]) vertex_coords = np.ascontiguousarray(v[:, :3]) vertex_normals = np.ascontiguousarray(v[:, 3:6]) vertex_colors = np.ascontiguousarray(v[:, 6:9]) num_vertex = vertex_coords.shape[0] print("There are #{} vertex in the mesh".format(num_vertex)) ## load face face_vertex_indices = mesh.elements[1]['vertex_indices'] face_vertex_indices = np.stack(face_vertex_indices, axis=0) ## rotate the scene to have Z-gravity negative_unit_z = np.array([0, 0, -1], dtype=np.float32) negative_unit_y = np.array([0, -1, 0], dtype=np.float32) rotation = quat_from_two_vectors(negative_unit_z, negative_unit_y) rotated_points = [] for i in range(num_vertex): point = vertex_coords[i, :] rotated_point = quat_rotate_vector(rotation, point) rotated_points.append(rotated_point) rotated_points = np.asarray(rotated_points) output_name = os.path.join(args.output_path, 'rotated_mesh.ply') meshwrite(output_name, rotated_points, face_vertex_indices, vertex_colors)
def create_ply(vertices, faces, save_path=None, text=True, replace_endings=False): vertex_dtype = [(dim, "f4") for dim in "xyz"] vertex_array = np.array(vertices, dtype=vertex_dtype) vertex_el = plyfile.PlyElement.describe(vertex_array, "vertex") face_dtype = [("vertex_indices", "i4", (4, ))] face_array = np.array(faces, dtype=face_dtype) face_el = plyfile.PlyElement.describe(face_array, "face") data = plyfile.PlyData([vertex_el, face_el], text=text) if save_path is not None: data.write(save_path) if replace_endings: with open(save_path, "rb") as handle: data_str = handle.read() data_str = data_str.replace("\r".encode("u8"), "".encode("u8")) with open(save_path, "wb") as handle: handle.write(data_str) return data
def save_ply(points, filename, colors=None, normals=None): vertex = np.array([tuple(p) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) n = len(vertex) desc = vertex.dtype.descr if normals is not None: vertex_normal = np.array([tuple(n) for n in normals], dtype=[('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4')]) assert len(vertex_normal) == n desc = desc + vertex_normal.dtype.descr if colors is not None: vertex_color = np.array([tuple(c * 255) for c in colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) assert len(vertex_color) == n desc = desc + vertex_color.dtype.descr vertex_all = np.empty(n, dtype=desc) for prop in vertex.dtype.names: vertex_all[prop] = vertex[prop] if normals is not None: for prop in vertex_normal.dtype.names: vertex_all[prop] = vertex_normal[prop] if colors is not None: for prop in vertex_color.dtype.names: vertex_all[prop] = vertex_color[prop] ply = plyfile.PlyData([plyfile.PlyElement.describe(vertex_all, 'vertex')], text=False) if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) ply.write(filename)
def save_simple_points_ply(out_filename, points, text=False): assert points.shape[1] == 3 assert points.ndim == 2 dirname = path.dirname(out_filename) if not path.isdir(dirname): os.makedirs(dirname) log.info('mkdir -p {}'.format(dirname)) xyz_nxyz = points vertex = np.core.records.fromarrays(xyz_nxyz.T, names='x, y, z', formats='f4, f4, f4') el = plyfile.PlyElement.describe(vertex, 'vertex') ply = plyfile.PlyData([el], text=text) ply.write(out_filename) # Replace \r\n with \n. with open(out_filename, 'rb') as f: content = f.read() beginning = content[:128] rest = content[128:] beginning = beginning.replace(b'ply\r\n', b'ply\n') with open(out_filename, 'wb') as f: f.write(beginning + rest) return ply
def save_ply(points, filename, colors=None, normals=None): vertex = np.core.records.fromarrays(points.transpose(), names='x, y, z', formats='f4, f4, f4') n = len(vertex) desc = vertex.dtype.descr if normals is not None: vertex_normal = np.core.records.fromarrays(normals.transpose(), names='nx, ny, nz', formats='f4, f4, f4') assert len(vertex_normal) == n desc = desc + vertex_normal.dtype.descr if colors is not None: vertex_color = np.core.records.fromarrays(colors.transpose() * 255, names='red, green, blue', formats='u1, u1, u1') assert len(vertex_color) == n desc = desc + vertex_color.dtype.descr vertex_all = np.empty(n, dtype=desc) for prop in vertex.dtype.names: vertex_all[prop] = vertex[prop] if normals is not None: for prop in vertex_normal.dtype.names: vertex_all[prop] = vertex_normal[prop] if colors is not None: for prop in vertex_color.dtype.names: vertex_all[prop] = vertex_color[prop] ply = plyfile.PlyData([plyfile.PlyElement.describe(vertex_all, 'vertex')], text=False) if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) ply.write(filename)
def cli(): parser = argparse.ArgumentParser() parser.add_argument('npoints', type=int, help='Number of points comprising the cube') parser.add_argument( 'noise', type=float, help='Standard deviation of the noise of the points in every axis') parser.add_argument('size', type=float, help='The size of one edge', default=1.0) parser.add_argument('output', type=str, help='The file where to output the pointcloud') args = parser.parse_args() p = points_of_cube(args.size, args.npoints, args.noise) el = plyfile.PlyElement.describe( p, 'vertex', val_types={ 'x': 'f8', 'y': 'f8', 'z': 'f8' }, ) plyfile.PlyData([el]).write(args.output)
def write_ply(output_path, pts, normals=None, rgb=None, faces=None, face_rgb=None, text=False): ''' Points should be 3 x N. Optionally, faces, normals, and RGB should be 3 x N as well ''' names = 'x,y,z' formats = 'f4,f4,f4' if normals is not None: pts = np.vstack((pts, normals)) names += ',nx,ny,nz' formats += ',f4,f4,f4' if rgb is not None: pts = np.vstack((pts, rgb)) names += ',red,green,blue' formats += ',u1,u1,u1' pts = np.core.records.fromarrays(pts, names=names, formats=formats) el = [plyfile.PlyElement.describe(pts, 'vertex')] if faces is not None: faces = faces.astype(np.int32) faces = faces.copy().ravel().view([("vertex_indices", "u4", 3)]) el.append(plyfile.PlyElement.describe(faces, 'face')) if face_rgb is not None: el.append(plyfile.PlyElement.describe(face_rgb, 'face')) plyfile.PlyData(el, text=text).write(output_path)
def save_point_cloud(path, P, edges=None, normals=None): data = [] if edges is not None: new_edges = np.empty(edges.shape, np.uint32) new_edges[:] = edges edges = new_edges.view(type=np.recarray, dtype=[('vertex1', 'u4'), ('vertex2', 'u4')])[:, 0] eel = plyfile.PlyElement.describe(edges, 'edge') data.append(eel) if normals is not None: vertices = np.empty((len(P), 6), np.float32) vertices[:, :3] = P vertices[:, 3:] = normals.astype(np.float32) vertices = vertices.view(type=np.recarray, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4')])[:, 0] vel = plyfile.PlyElement.describe(vertices, 'vertex') data.append(vel) else: vertices = np.empty((len(P), 3), np.float32) vertices[:] = P vertices = vertices.view(type=np.recarray, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])[:, 0] vel = plyfile.PlyElement.describe(vertices, 'vertex') data.append(vel) plyfile.PlyData(data).write(path)
def mesh_msg_to_ply(mesh_msg): """ :type mesh_msg: shape_msgs.msg.Mesh :rtype plyfile.PlyData """ # vertex = numpy.array([(0, 0, 0), # (0, 1, 1), # (1, 0, 1), # (1, 1, 0)], # dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) # face = numpy.array([([0, 1, 2],), # ([0, 2, 3],), # ([0, 1, 3],), # ([1, 2, 3],)], # dtype=[('vertex_indices', 'i4', (3,))]) vertices = [(x.x, x.y, x.z) for x in mesh_msg.vertices] faces = [(x.vertex_indices, ) for x in mesh_msg.triangles] vertices_np = numpy.array(vertices, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) faces_np = numpy.array(faces, dtype=[('vertex_indices', 'i4', (3, ))]) vertex_element = plyfile.PlyElement.describe(vertices_np, 'vertex') face_element = plyfile.PlyElement.describe(faces_np, 'face') return plyfile.PlyData([vertex_element, face_element], text=True)
def visualize_points(points, output_file, transform=None, colors=None): verts = points if points.shape[1] == 3 else np.transpose(points) if transform is not None: x = np.ones((verts.shape[0], 4)) x[:, :3] = verts x = np.matmul(transform, np.transpose(x)) x = np.transpose(x) verts = np.divide(x[:, :3], x[:, 3, None]) ext = os.path.splitext(output_file)[1] if colors is not None or ext == '.obj': output_file = os.path.splitext(output_file)[0] + '.obj' num_verts = len(verts) with open(output_file, 'w') as f: for i in range(num_verts): v = verts[i] if colors is None: f.write('v %f %f %f\n' % (v[0], v[1], v[2])) else: f.write('v %f %f %f %f %f %f\n' % (v[0], v[1], v[2], colors[i, 0], colors[i, 1], colors[i, 2])) elif ext == '.ply': verts = np.array([tuple(v) for v in verts], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) el = plyfile.PlyElement.describe(verts, 'vertex') plyfile.PlyData([el]).write(output_file) else: raise # unsupported extension
def write_ply( output_path, pts, # 3 x N normals=None, # 3 x N rgb=None, # 3 x N faces=None, # 3 x M face_rgb=None, # 3 x M text=False): names = 'x,y,z' formats = 'f4,f4,f4' if normals is not None: pts = np.vstack((pts, normals)) names += ',nx,ny,nz' formats += ',f4,f4,f4' if rgb is not None: pts = np.vstack((pts, rgb)) names += ',red,green,blue' formats += ',u1,u1,u1' pts = np.core.records.fromarrays(pts, names=names, formats=formats) el = [plyfile.PlyElement.describe(pts, 'vertex')] if faces is not None: faces = faces.astype(np.int32).T # Next step needs M x 3 memory layout faces = faces.copy().ravel().view([("vertex_indices", "u4", 3)]) el.append(plyfile.PlyElement.describe(faces, 'face')) if face_rgb is not None: el.append(plyfile.PlyElement.describe(face_rgb, 'face')) plyfile.PlyData(el, text=text).write(output_path)