def write_ply_file(points): ''' Given a string of comma-separated values that represent 2d points, parse the string, create a ply file in the temp storage directory representing the shape formed by the string, and return the filepath. ''' import voxel_globe.tools with voxel_globe.tools.storage_dir('event_trigger_ply') as ply_dir: num_files = len([name for name in os.listdir(ply_dir)]) filepath = os.path.join(ply_dir, 'mesh_%d.ply' % num_files) import numpy import plyfile from plyfile import PlyData, PlyElement vertex = numpy.array(points, dtype=[('x', 'double'), ('y', 'double'), ('z', 'double')]) face = numpy.array([(range(len(points)),)], [('vertex_indices', '|O')]) el1 = PlyElement.describe(vertex, 'vertex') el2 = PlyElement.describe(face, 'face') PlyData([el1, el2], text=True, comments=['mesh-feature'], obj_info=['a bmsh3d_mesh object']).write(filepath) return filepath
def tet_ply(text, byte_order): 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], 255, 255, 255), ([0, 2, 3], 255, 0, 0), ([0, 1, 3], 0, 255, 0), ([1, 2, 3], 0, 0, 255)], dtype=[("vertex_indices", "i4", (3,)), ("red", "u1"), ("green", "u1"), ("blue", "u1")], ) return PlyData( [PlyElement.describe(vertex, "vertex", comments=["tetrahedron vertices"]), PlyElement.describe(face, "face")], text=text, byte_order=byte_order, comments=["single tetrahedron with colored faces"], )
def save_ply(self, filename): vertex = np.array([tuple(i) for i in self.v], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) face = np.array([(tuple(i), 0, 100, 255) for i in self.f] , dtype=[('vertex_indices', 'i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) edge = np.array([(tuple(i)[0], tuple(i)[1], 255, 255, 255) for i in self.e] , dtype=[('vertex1', 'i4'), ('vertex2', 'i4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) el = PlyElement.describe(vertex, 'vertex') el2 = PlyElement.describe(face, 'face') el3 = PlyElement.describe(edge, 'edge') plydata = PlyData([el, el2, el3]) plydata.write(filename)
def write_ply(self, coords, normals, path): l = [] size = coords.shape[0] for i in range(0, size): l.append((coords[i][0], coords[i][1], coords[i][2], normals[i][0], normals[i][1], normals[i][2])) vertex = np.array(l, dtype=[('x', 'f4'),('y', 'f4'),('z', 'f4'),('nx','f4'),('ny','f4'),('nz','f4')]) el = PlyElement.describe(vertex, 'vertex') PlyData([el]).write(path)
def test_assign_elements(tet_ply_txt): test = PlyElement.describe(numpy.zeros(1, dtype=[("a", "i4")]), "test") tet_ply_txt.elements = [test] assert len(tet_ply_txt.elements) == 1 assert len(tet_ply_txt) == 1 assert "vertex" not in tet_ply_txt assert "face" not in tet_ply_txt assert "test" in tet_ply_txt for (k, elt) in enumerate(tet_ply_txt): assert elt.name == "test" assert k == 0
def CreatePLY(P1,parameters,filename,surf_type,originalPLYfile): x1 = P1[:,0] y1 = P1[:,1] z1 = P1[:,2] if surf_type == 'lin': z1new = np.hstack((x1,y1,np.matrix(np.ones(np.size(P1,0))).T))*parameters else: z1new = np.hstack((np.multiply(x1,x1),np.multiply(y1,y1), np.multiply(x1,y1), x1, y1,np.matrix(np.ones(np.size(P1,0))).T))*parameters originalPLY = PLYLoader(originalPLYfile) point_cloud = (originalPLY.get_points()).T color_matrix = (originalPLY.get_colors()).T normals_matrix = (originalPLY.get_normals()).T x1 = np.array(x1) y1 = np.array(y1) z1new = np.array(z1new) x = point_cloud[:,0] y = point_cloud[:,1] z = point_cloud[:,2] new_pointcloud = np.zeros((np.size(P1,0), 9)) pdb.set_trace() for Prow in range(len(x1)): print 'Prow = ' print Prow for originalPLY_row in range(len(x)): if ((x[originalPLY_row] == x1[Prow]) and (y[originalPLY_row] == y1[Prow])): print 'found' print Prow #point_cloud[originalPLY_row,2] = z1new[Prow] new_pointcloud[Prow,0:2] = (P1[Prow,0:2]) new_pointcloud[Prow,2] = (z1new[Prow]) new_pointcloud[Prow,3:6] = (normals_matrix[originalPLY_row,:]) new_pointcloud[Prow,6:9] = color_matrix[originalPLY_row,:] pdb.set_trace() #vertex = point_cloud #new_mat = np.concatenate((vertex,normals_matrix,color_matrix),axis=1) new_mat = new_pointcloud vertex_new = map(tuple, new_mat) vertex_new = np.array(vertex_new, dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4'),('nx','f4'),('ny','f4'),('nz','f4'),('diffuse_red', 'u1'), ('diffuse_green', 'u1'),('diffuse_blue', 'u1')]) el = PlyElement.describe(vertex_new, 'vertex') PlyData([el], text=True).write(filename)
def test_list_property_type(tmpdir, np_type): a = numpy.array([([0],), ([1, 2, 3],)], dtype=[("x", object)]) ply0 = PlyData([PlyElement.describe(a, "test", val_types={"x": np_type})]) assert ply0.elements[0].name == "test" assert ply0.elements[0].properties[0].name == "x" assert ply0.elements[0].properties[0].val_dtype == np_type ply1 = write_read(ply0, tmpdir) assert ply1.elements[0].name == "test" assert ply1.elements[0].data[0]["x"].dtype == numpy.dtype(np_type) verify(ply0, ply1)
def test_property_type(tmpdir, np_type): dtype = [("x", np_type), ("y", np_type), ("z", np_type)] a = numpy.array([(1, 2, 3), (4, 5, 6)], dtype=dtype) ply0 = PlyData([PlyElement.describe(a, "test")]) assert ply0.elements[0].name == "test" assert ply0.elements[0].properties[0].name == "x" assert ply0.elements[0].properties[0].val_dtype == np_type assert ply0.elements[0].properties[1].name == "y" assert ply0.elements[0].properties[1].val_dtype == np_type assert ply0.elements[0].properties[2].name == "z" assert ply0.elements[0].properties[2].val_dtype == np_type ply1 = write_read(ply0, tmpdir) assert ply1.elements[0].name == "test" assert ply1.elements[0].data.dtype == dtype verify(ply0, ply1)
def filter_depth(scan_folder, out_folder, plyfilename): # the pair file pair_file = os.path.join(scan_folder, "pair.txt") # for the final point cloud vertexs = [] vertex_colors = [] pair_data = read_pair_file(pair_file) nviews = len(pair_data) # TODO: hardcode size # used_mask = [np.zeros([296, 400], dtype=np.bool) for _ in range(nviews)] # for each reference view and the corresponding source views for ref_view, src_views in pair_data: # load the camera parameters ref_intrinsics, ref_extrinsics = read_camera_parameters( os.path.join(scan_folder, 'cams/{:0>8}_cam.txt'.format(ref_view))) # load the reference image ref_img = read_img( os.path.join(scan_folder, 'images/{:0>8}.jpg'.format(ref_view))) # load the estimated depth of the reference view ref_depth_est = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(ref_view)))[0] # load the photometric mask of the reference view confidence = read_pfm( os.path.join(out_folder, 'confidence/{:0>8}.pfm'.format(ref_view)))[0] photo_mask = confidence > 0.8 all_srcview_depth_ests = [] all_srcview_x = [] all_srcview_y = [] all_srcview_geomask = [] # compute the geometric mask geo_mask_sum = 0 for src_view in src_views: # camera parameters of the source view src_intrinsics, src_extrinsics = read_camera_parameters( os.path.join(scan_folder, 'cams/{:0>8}_cam.txt'.format(src_view))) # the estimated depth of the source view src_depth_est = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(src_view)))[0] geo_mask, depth_reprojected, x2d_src, y2d_src = check_geometric_consistency( ref_depth_est, ref_intrinsics, ref_extrinsics, src_depth_est, src_intrinsics, src_extrinsics) geo_mask_sum += geo_mask.astype(np.int32) all_srcview_depth_ests.append(depth_reprojected) all_srcview_x.append(x2d_src) all_srcview_y.append(y2d_src) all_srcview_geomask.append(geo_mask) depth_est_averaged = (sum(all_srcview_depth_ests) + ref_depth_est) / (geo_mask_sum + 1) # at least 3 source views matched geo_mask = geo_mask_sum >= 3 final_mask = np.logical_and(photo_mask, geo_mask) os.makedirs(os.path.join(out_folder, "mask"), exist_ok=True) save_mask( os.path.join(out_folder, "mask/{:0>8}_photo.png".format(ref_view)), photo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_geo.png".format(ref_view)), geo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_final.png".format(ref_view)), final_mask) print("processing {}, ref-view{:0>2}, photo/geo/final-mask:{}/{}/{}". format(scan_folder, ref_view, photo_mask.mean(), geo_mask.mean(), final_mask.mean())) if args.display: import cv2 cv2.imshow('ref_img', ref_img[:, :, ::-1]) cv2.imshow('ref_depth', ref_depth_est / 800) cv2.imshow('ref_depth * photo_mask', ref_depth_est * photo_mask.astype(np.float32) / 800) cv2.imshow('ref_depth * geo_mask', ref_depth_est * geo_mask.astype(np.float32) / 800) cv2.imshow('ref_depth * mask', ref_depth_est * final_mask.astype(np.float32) / 800) cv2.waitKey(0) height, width = depth_est_averaged.shape[:2] x, y = np.meshgrid(np.arange(0, width), np.arange(0, height)) # valid_points = np.logical_and(final_mask, ~used_mask[ref_view]) valid_points = final_mask print("valid_points", valid_points.mean()) x, y, depth = x[valid_points], y[valid_points], depth_est_averaged[ valid_points] color = ref_img[1:-16:4, 1::4, :][valid_points] # hardcoded for DTU dataset xyz_ref = np.matmul(np.linalg.inv(ref_intrinsics), np.vstack((x, y, np.ones_like(x))) * depth) xyz_world = np.matmul(np.linalg.inv(ref_extrinsics), np.vstack((xyz_ref, np.ones_like(x))))[:3] vertexs.append(xyz_world.transpose((1, 0))) vertex_colors.append((color * 255).astype(np.uint8)) # # set used_mask[ref_view] # used_mask[ref_view][...] = True # for idx, src_view in enumerate(src_views): # src_mask = np.logical_and(final_mask, all_srcview_geomask[idx]) # src_y = all_srcview_y[idx].astype(np.int) # src_x = all_srcview_x[idx].astype(np.int) # used_mask[src_view][src_y[src_mask], src_x[src_mask]] = True vertexs = np.concatenate(vertexs, axis=0) vertex_colors = np.concatenate(vertex_colors, axis=0) vertexs = np.array([tuple(v) for v in vertexs], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_colors = np.array([tuple(v) for v in vertex_colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) vertex_all = np.empty(len(vertexs), vertexs.dtype.descr + vertex_colors.dtype.descr) for prop in vertexs.dtype.names: vertex_all[prop] = vertexs[prop] for prop in vertex_colors.dtype.names: vertex_all[prop] = vertex_colors[prop] el = PlyElement.describe(vertex_all, 'vertex') PlyData([el]).write(plyfilename) print("saving the final model to", plyfilename)
def write_ply(points, filename, text=True): """ input: Nx3, write points to filename as PLY format. """ points = [(points[i,0], points[i,1], points[i,2]) for i in range(points.shape[0])] vertex = np.array(points, dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4')]) el = PlyElement.describe(vertex, 'vertex', comments=['vertices']) PlyData([el], text=text).write(filename)
programSV3DRegion = glumpy_setting.ProgramSV3DRegion( data=data, name=None, point_size=1, anchor=anchor_matrix_whole) gpyWindow.add_program(programSV3DRegion) print(data['a_position'][0, 0, 0]) print(np.isnan(data['a_position'][0, 0, 0])) print(~np.isnan(data['a_position'][0, 0, 0])) data['a_color'] *= 255 data['a_color'].astype(int) data = data[np.nonzero(~np.isnan(data['a_position'][:, :, 0]))] xyzzz = np.zeros(len(data), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('r', 'f4'), ('g', 'f4'), ('b', 'f4')]) xyzzz['x'] = data['a_position'][:, 0] xyzzz['y'] = data['a_position'][:, 1] xyzzz['z'] = data['a_position'][:, 2] xyzzz['r'] = data['a_color'][:, 0] xyzzz['g'] = data['a_color'][:, 1] xyzzz['b'] = data['a_color'][:, 2] el = PlyElement.describe(xyzzz, 'vertex') PlyData([el]).write('some_binary.ply') PlyData([el], text=True).write('some_ascii.ply') programAxis = glumpy_setting.ProgramAxis(line_length=5) gpyWindow.add_program(programAxis) gpyWindow.run()
func = np.exp(-mesh[0]**2 / 500.0) * np.exp(-mesh[1]**2 / 750.0) * surf x, y, z = mesh[0].flatten(), mesh[1].flatten(), surf.flatten() data = func.flatten() n0, n1 = func.shape v_list, f_list = [], [] for i0 in range(n0): for j0 in range(n1): i1, j1 = i0 + 1, j0 + 1 v_list.append( (mesh[0][i0, j0], mesh[1][i0, j0], surf[i0, j0], func[i0, j0])) for i0 in range(n0 - 1): for j0 in range(n1 - 1): i1, j1 = i0 + 1, j0 + 1 v_n00 = i0 * n1 + j0 v_n01 = v_n00 + 1 v_n10 = v_n00 + n1 v_n11 = v_n10 + 1 val = (func[i0, j0] + func[i0, j1] + func[i1, j0] + func[i1, j1]) / 4 f_list.append(([v_n00, v_n01, v_n11, v_n10], val)) vertex = np.array(v_list, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('data', 'f4')]) face = np.array(f_list, dtype=[('vertex_indices', 'i4', (4, )), ('face_color', 'f4')]) elv = PlyElement.describe(vertex, "vertex") elf = PlyElement.describe(face, "face") PlyData([elv, elf], text=True).write('./create_ply_simple1.ply')
def test_element_parse_error_repr(): prop = PlyProperty('x', 'f4') elt = PlyElement('test', [prop], 0) e = PlyElementParseError('text', elt, 0, prop) assert repr(e)
def test_invalid_array(a): with Raises(ValueError): PlyElement.describe(a, 'test')
def gen_box_and_pl(ply_fn, box_vertexes, pl_xyz=None, extra=''): ''' Generate box and points together in the same file. box_vertexes and pl_xyz independently. The 8 vertexs are included automatically in the box. pl_xyz is used to provide other points. box_vertexes:[num_box,8,3] pl_xyz: [num_point,3] ''' assert box_vertexes.ndim == 3 assert box_vertexes.shape[1] == 8 assert box_vertexes.shape[-1] == 3 box_vertexes = np.reshape(box_vertexes, (-1, 3)) num_box = box_vertexes.shape[0] // 8 if type(pl_xyz) != type(None): assert pl_xyz.shape[-1] == 3 pl_xyz = np.reshape(pl_xyz, (-1, 3)) num_vertex = box_vertexes.shape[0] + pl_xyz.shape[0] else: num_vertex = box_vertexes.shape[0] vertex = np.zeros(shape=(num_vertex)).astype([('x', 'f8'), ('y', 'f8'), ('z', 'f8')]) for i in range(box_vertexes.shape[0]): vertex[i] = (box_vertexes[i, 0], box_vertexes[i, 1], box_vertexes[i, 2]) if type(pl_xyz) != type(None): for i in range(pl_xyz.shape[0]): vertex[i + box_vertexes.shape[0]] = (pl_xyz[i, 0], pl_xyz[i, 1], pl_xyz[i, 2]) el_vertex = PlyElement.describe(vertex, 'vertex') # define the order of the 8 vertexs for a box edge_basic = np.array([(0, 1, 255, 0, 0), (1, 2, 255, 0, 0), (2, 3, 255, 0, 0), (3, 0, 255, 0, 0), (4, 5, 255, 0, 0), (5, 6, 255, 0, 0), (6, 7, 255, 0, 0), (7, 4, 255, 0, 0), (0, 4, 255, 0, 0), (1, 5, 255, 0, 0), (2, 6, 255, 0, 0), (3, 7, 255, 0, 0)]) if extra == 'random_color_between_boxes': color = np.random.randint(0, 256, 3) color[2] = 255 - color[0] - color[1] edge_basic[:, 2:5] = color edge_val = np.concatenate([edge_basic] * num_box, 0) for i in range(num_box): edge_val[i * 12:(i + 1) * 12, 0:2] += (8 * i) edge = np.zeros(shape=(edge_val.shape[0])).astype( dtype=[('vertex1', 'i4'), ('vertex2', 'i4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) for i in range(edge_val.shape[0]): edge[i] = (edge_val[i, 0], edge_val[i, 1], edge_val[i, 2], edge_val[i, 3], edge_val[i, 4]) el_edge = PlyElement.describe(edge, 'edge') dirname = os.path.dirname(ply_fn) if not os.path.exists(dirname): os.makedirs(dirname) PlyData([el_vertex, el_edge], text=True).write(ply_fn) print('write %s ok' % (ply_fn))
##### Until mesh extraction here, it is the same as the original repo. ###### vertices_ = (vertices/N).astype(np.float32) ## invert x and y coordinates (WHY? maybe because of the marching cubes algo) x_ = (ymax-ymin) * vertices_[:, 1] + ymin y_ = (xmax-xmin) * vertices_[:, 0] + xmin vertices_[:, 0] = x_ vertices_[:, 1] = y_ vertices_[:, 2] = (zmax-zmin) * vertices_[:, 2] + zmin vertices_.dtype = [('x', 'f4'), ('y', 'f4'), ('z', 'f4')] face = np.empty(len(triangles), dtype=[('vertex_indices', 'i4', (3,))]) face['vertex_indices'] = triangles PlyData([PlyElement.describe(vertices_[:, 0], 'vertex'), PlyElement.describe(face, 'face')]).write(f'{args.scene_name}.ply') # remove noise in the mesh by keeping only the biggest cluster print('Removing noise ...') mesh = o3d.io.read_triangle_mesh(f"{args.scene_name}.ply") idxs, count, _ = mesh.cluster_connected_triangles() max_cluster_idx = np.argmax(count) triangles_to_remove = [i for i in range(len(face)) if idxs[i] != max_cluster_idx] mesh.remove_triangles_by_index(triangles_to_remove) mesh.remove_unreferenced_vertices() print(f'Mesh has {len(mesh.vertices)/1e6:.2f} M vertices and {len(mesh.triangles)/1e6:.2f} M faces.') vertices_ = np.asarray(mesh.vertices).astype(np.float32) triangles = np.asarray(mesh.triangles)
def write_PLY(fn, disp, Q, flagFlip=False, distLimit=100., mask=None, color=None, binary=True): """ fn: The output filename. disp: The disparity. A NumPy array with dimension (H, W). mask: Logical NumPy array. Q: The reprojection matrix. A NumP array of dimension 4x4. color: The color image. The image could be (H, W) or (H, W, C). C could be 1 or 3. If color==None, no color properties will be in the output PLY file. binary: Set True to write a binary format PLY file. Set False for a ASCII version. """ disp = disp.copy() # Get the size of the image. H = disp.shape[0] W = disp.shape[1] # Make x and y. xLin = np.linspace( 0, W-1, W, dtype=np.float32 ) yLin = np.linspace( 0, H-1, H, dtype=np.float32 ) x, y = np.meshgrid( xLin, yLin ) x = x.reshape((-1,)) y = y.reshape((-1,)) # Make the coordinate array. d = disp.reshape((-1,)) hg = np.ones((1, d.shape[0]), dtype=np.float32).reshape((-1,)) # Mask. m = d > 0 nm = np.logical_not(m) m = m.reshape((-1,)) d[nm] = 1.0 if ( mask is not None ): m = np.logical_and( m, mask.reshape((-1,)) ) coor = np.stack( [ x, y, d, hg ], axis=-1 ).transpose() # Calculate the world coordinate. if ( flagFlip ): Q = Q.copy() Q[1, 1] *= -1 Q[1, 3] *= -1 Q[2, 3] *= -1 coor = Q.dot( coor ) coor[0, :] = coor[0, :] / coor[3, :] coor[1, :] = coor[1, :] / coor[3, :] coor[2, :] = coor[2, :] / coor[3, :] coor = coor.transpose()[:, 0:3] # Filter the points. Only keep the points within distLimit. dispMask = np.abs( coor[:, 2] ) <= distLimit m = np.logical_and( m, dispMask.reshape((-1,)) ) # Handle color. if ( color is not None ): if ( 2 == len( color.shape ) ): color = np.stack([ color, color, color ], axis=-1) color = color.reshape(-1, 3) color = color[m, 0:3] coor = coor[m, 0:3] color = np.clip( color, 0, 255 ).astype(np.uint8) # Concatenate. vertex = np.concatenate([coor, color], axis=1) # Create finial vetex array. vertex = convert_2D_array_2_1D_list(vertex) vertex = np.array( vertex, dtype=[\ ( "x", "f4" ), \ ( "y", "f4" ), \ ( "z", "f4" ), \ ( "red", "u1" ), \ ( "green", "u1" ), \ ( "blue", "u1" ) \ ] ) else: coor = convert_2D_array_2_1D_list(coor) vertex = np.array( coor, dtype=[\ ( "x", "f4" ), \ ( "y", "f4" ), \ ( "z", "f4" ) \ ] ) # Save the PLY file. el = PlyElement.describe(vertex, "vertex") PlyData([el], text= (not binary) ).write(fn)
def getMakerXYZ(self, markercolumnid, markerrowid, markerdepth): if markerdepth > 0: point3d = self.kinect.mapper().MapDepthPointToCameraSpace( PyKinectV2._DepthSpacePoint(ctypes.c_float(markercolumnid), ctypes.c_float(markerrowid)), ctypes.c_ushort(markerdepth)) return [point3d.x, point3d.y, point3d.z] else: return [] if __name__=='__main__': base = pandactrl.World(camp=[0,0,3000], lookatp=[0,0,0]) kapi = KinectAPI() # points pntclds = kapi.getPointCloud() colors = [] color = [np.random.rand(), np.random.rand(), np.random.rand(), np.random.rand()] for pnt in pntclds: colors.append(color) pntsnp = pg.genPntsnp(pntclds, colors=colors) pntsnp.reparentTo(base.render) from plyfile import PlyData, PlyElement verts = np.array(pntclds, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) el = PlyElement.describe(verts, 'vertex') PlyData([el], text=True).write('pythoncloud.ply') base.run()
def save_to_ply(points, filename): points = np.array(points, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) el = PlyElement.describe(points, 'vertex') PlyData([el]).write(filename)
from plyfile import PlyData, PlyElement import numpy as np # p = PlyData.read("../data/feature_1.ply") # print(p) a = np.array([(0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0)], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) print(a) el = PlyElement.describe(a, 'myvertices') PlyData([el]).write('some_binary.ply') PlyData([el], text=True).write('some_ascii.ply')
def create_ply(xyz0, ply_fn, label=None, label2color=None, force_color=None, box=None, cut_threshold=[1, 1, 1]): ''' xyz0: (num_block,num_point,3) or (num_point,3) or (num_block,num_point,6) or (num_point,6) label: (num_block,num_point) or (num_point) force_color: (3,) (1) color in xyz0: xyz0.shape[-]==6, label=None, label2color=None (2) no color: xyz0.shape[-1]==3, label=None, label2color=None (3) color by label: xyz0.shape[-1]==3,label.shape= (num_block,num_point) or (num_point) (4) set consistent color: xyz0.shape[-1]==3, label=None, label2color=None, force_color=[255,0,0] ''' print(ply_fn) folder = os.path.dirname(ply_fn) if not os.path.exists(folder): os.makedirs(folder) new_xyz_ls = [] is_keep_ls = [] is_cut = xyz0.ndim >= 3 if is_cut: for i in range(xyz0.shape[0]): new_xyz_i, is_keep_i = cut_xyz(xyz0[i], cut_threshold) new_xyz_ls.append(new_xyz_i) is_keep_ls.append(is_keep_i) xyz = np.concatenate(new_xyz_ls, 0) is_keep = np.concatenate(is_keep_ls, 0) else: xyz = xyz0 if xyz.shape[-1] == 3: if type(label) != type(None) and label2color != None: #(3) color by label: xyz0.shape[-1]==3,label.shape= (num_block,num_point) or (num_point) label2color_ls = [] for i in range(len(label2color)): label2color_ls.append( np.reshape(np.array(label2color[i]), (1, 3))) label2colors = np.concatenate(label2color_ls, 0) color = np.take(label2colors, label, axis=0) color = np.reshape(color, (-1, 3)) if is_cut: color = color[is_keep, :] xyz = np.concatenate([xyz, color], -1) elif type(force_color) != type(None): #(4) set consistent color: xyz0.shape[-1]==3, label=None, label2color=None, force_color=[255,0,0] color = np.reshape(np.array(force_color), [1, 3]) color = np.tile(color, [xyz.shape[0], 1]) xyz = np.concatenate([xyz, color], -1) if xyz.shape[-1] == 3: #(2) no color: xyz0.shape[-1]==3, label=None, label2color=None vertex = np.zeros(shape=(xyz.shape[0])).astype([('x', 'f8'), ('y', 'f8'), ('z', 'f8')]) for i in range(xyz.shape[0]): vertex[i] = (xyz[i, 0], xyz[i, 1], xyz[i, 2]) elif xyz.shape[-1] == 6: vertex = np.zeros(shape=(xyz.shape[0])).astype([('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) for i in range(xyz.shape[0]): vertex[i] = (xyz[i, 0], xyz[i, 1], xyz[i, 2], xyz[i, 3], xyz[i, 4], xyz[i, 5]) else: raise NotImplementedError el_vertex = PlyElement.describe(vertex, 'vertex') PlyData([el_vertex], text=True).write(ply_fn) print('save ply file: %s' % (ply_fn))
def write_ply(array, filepath): ply_el = PlyElement.describe(array, 'vertex') target_path, _ = os.path.split(filepath) if target_path != '' and not os.path.exists(target_path): os.makedirs(target_path) PlyData([ply_el]).write(filepath)
##### Until mesh extraction here, it is the same as the original repo. ###### vertices_ = (vertices / N).astype(np.float32) ## invert x and y coordinates (WHY? maybe because of the marching cubes algo) x_ = (ymax - ymin) * vertices_[:, 1] + ymin y_ = (xmax - xmin) * vertices_[:, 0] + xmin vertices_[:, 0] = x_ vertices_[:, 1] = y_ vertices_[:, 2] = (zmax - zmin) * vertices_[:, 2] + zmin vertices_.dtype = [('x', 'f4'), ('y', 'f4'), ('z', 'f4')] face = np.empty(len(triangles), dtype=[('vertex_indices', 'i4', (3, ))]) face['vertex_indices'] = triangles PlyData([ PlyElement.describe(vertices_[:, 0], 'vertex'), PlyElement.describe(face, 'face') ]).write(f'{args.scene_name}.ply') # remove noise in the mesh by keeping only the biggest cluster print('Removing noise ...') mesh = o3d.io.read_triangle_mesh(f"{args.scene_name}.ply") idxs, count, _ = mesh.cluster_connected_triangles() max_cluster_idx = np.argmax(count) triangles_to_remove = [ i for i in range(len(face)) if idxs[i] != max_cluster_idx ] mesh.remove_triangles_by_index(triangles_to_remove) mesh.remove_unreferenced_vertices() print( f'Mesh has {len(mesh.vertices)/1e6:.2f} M vertices and {len(mesh.triangles)/1e6:.2f} M faces.'
# for i0 in range(n0): # for j0 in range(n1): # i1, j1 = i0 + 1, j0 + 1 # v_list.append(( # mesh[0][i0, j0], # mesh[1][i0, j0], # surf[i0, j0], # func[i0, j0] # )) # for i0 in range(n0 - 1): # for j0 in range(n1 - 1): # i1, j1 = i0 + 1, j0 + 1 # v_n00 = i0 * n1 + j0 # v_n01 = v_n00 + 1 # v_n10 = v_n00 + n1 # v_n11 = v_n10 + 1 # val = (func[i0, j0] + func[i0, j1] + func[i1, j0] + func[i1, j1]) / 4 # f_list.append(( # [v_n00, v_n01, v_n11, v_n10], # val # )) vertex = np.array(v_list, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('data', 'f4')]) elv = PlyElement.describe(vertex, "vertex") # face = np.array( # f_list, dtype=[('vertex_indices', 'i4', (4,)), ('face_color', 'f4')]) #elf = PlyElement.describe(face, "face") PlyData([elv], text=True).write('./create_ply_simple3.ply')
def export_ply(pc, filename): vertex = np.zeros(pc.shape[0], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) for i in range(pc.shape[0]): vertex[i] = (pc[i][0], pc[i][1], pc[i][2]) ply_out = PlyData([PlyElement.describe(vertex, 'vertex', comments=['vertices'])]) ply_out.write(filename)
def test_invalid_array_type(): with Raises(TypeError): PlyElement.describe([0, 1, 2], 'test')
def filter_depth(scan_folder, out_folder, plyfilename, geo_pixel_thres, geo_depth_thres, photo_thres, img_wh, geo_mask_thres): # the pair file pair_file = os.path.join(scan_folder, "pair.txt") # for the final point cloud vertexs = [] vertex_colors = [] pair_data = read_pair_file(pair_file) nviews = len(pair_data) # for each reference view and the corresponding source views for ref_view, src_views in pair_data: # load the reference image ref_img, original_h, original_w = read_img( os.path.join(scan_folder, 'images/{:0>8}.jpg'.format(ref_view)), img_wh) ref_intrinsics, ref_extrinsics = read_cam_file( os.path.join(scan_folder, 'cams_1/{:0>8}_cam.txt'.format(ref_view)))[0:2] ref_intrinsics[0] *= img_wh[0] / original_w ref_intrinsics[1] *= img_wh[1] / original_h # load the estimated depth of the reference view ref_depth_est = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(ref_view)))[0] ref_depth_est = np.squeeze(ref_depth_est, 2) # load the photometric mask of the reference view confidence = read_pfm( os.path.join(out_folder, 'confidence/{:0>8}.pfm'.format(ref_view)))[0] photo_mask = confidence > photo_thres photo_mask = np.squeeze(photo_mask, 2) all_srcview_depth_ests = [] # compute the geometric mask geo_mask_sum = 0 for src_view in src_views: # camera parameters of the source view _, original_h, original_w = read_img( os.path.join(scan_folder, 'images/{:0>8}.jpg'.format(src_view)), img_wh) src_intrinsics, src_extrinsics = read_cam_file( os.path.join(scan_folder, 'cams_1/{:0>8}_cam.txt'.format(src_view)))[0:2] src_intrinsics[0] *= img_wh[0] / original_w src_intrinsics[1] *= img_wh[1] / original_h # the estimated depth of the source view src_depth_est = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(src_view)))[0] geo_mask, depth_reprojected, x2d_src, y2d_src = check_geometric_consistency( ref_depth_est, ref_intrinsics, ref_extrinsics, src_depth_est, src_intrinsics, src_extrinsics, geo_pixel_thres, geo_depth_thres) geo_mask_sum += geo_mask.astype(np.int32) all_srcview_depth_ests.append(depth_reprojected) depth_est_averaged = (sum(all_srcview_depth_ests) + ref_depth_est) / (geo_mask_sum + 1) geo_mask = geo_mask_sum >= geo_mask_thres final_mask = np.logical_and(photo_mask, geo_mask) os.makedirs(os.path.join(out_folder, "mask"), exist_ok=True) save_mask( os.path.join(out_folder, "mask/{:0>8}_photo.png".format(ref_view)), photo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_geo.png".format(ref_view)), geo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_final.png".format(ref_view)), final_mask) if args.display: import cv2 cv2.imshow('ref_img', ref_img[:, :, ::-1]) cv2.imshow('ref_depth', ref_depth_est) cv2.imshow('ref_depth * photo_mask', ref_depth_est * photo_mask.astype(np.float32)) cv2.imshow('ref_depth * geo_mask', ref_depth_est * geo_mask.astype(np.float32)) cv2.imshow('ref_depth * mask', ref_depth_est * final_mask.astype(np.float32)) cv2.waitKey(1) height, width = depth_est_averaged.shape[:2] x, y = np.meshgrid(np.arange(0, width), np.arange(0, height)) valid_points = final_mask x, y, depth = x[valid_points], y[valid_points], depth_est_averaged[ valid_points] color = ref_img[valid_points] xyz_ref = np.matmul(np.linalg.inv(ref_intrinsics), np.vstack((x, y, np.ones_like(x))) * depth) xyz_world = np.matmul(np.linalg.inv(ref_extrinsics), np.vstack((xyz_ref, np.ones_like(x))))[:3] vertexs.append(xyz_world.transpose((1, 0))) vertex_colors.append((color * 255).astype(np.uint8)) vertexs = np.concatenate(vertexs, axis=0) vertex_colors = np.concatenate(vertex_colors, axis=0) vertexs = np.array([tuple(v) for v in vertexs], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_colors = np.array([tuple(v) for v in vertex_colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) vertex_all = np.empty(len(vertexs), vertexs.dtype.descr + vertex_colors.dtype.descr) for prop in vertexs.dtype.names: vertex_all[prop] = vertexs[prop] for prop in vertex_colors.dtype.names: vertex_all[prop] = vertex_colors[prop] el = PlyElement.describe(vertex_all, 'vertex') PlyData([el]).write(plyfilename) print("saving the final model to", plyfilename)
quality_list_with_statistical_outliers = pointcloud_with_outliers[ 'vertex'].data['quality'] mean = numpy.mean(quality_list_with_statistical_outliers, axis=0) print("The mean of the vertex radius is: " + mean.__str__()) sd = numpy.std(quality_list_with_statistical_outliers, axis=0) print("The Standard Deviation of the vertex radius is: " + sd.__str__()) print("Removing all vertices above sigma of " + remove_all_vertices_above_sd_sigma_of.__str__()) list_of_vertices_without_SO = [] for index, x in enumerate(quality_list_with_statistical_outliers): if x < mean + remove_all_vertices_above_sd_sigma_of * sd: list_of_vertices_without_SO.append( pointcloud_with_outliers["vertex"][index]) print("Removed " + (len(quality_list_with_statistical_outliers) - len(list_of_vertices_without_SO)).__str__() + " outlier vertices") print("Creating PLY file now") vertex = numpy.array(list_of_vertices_without_SO, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('quality', 'f4'), ('radius', 'f4')]) new_ply_element = PlyElement.describe(vertex, "vertex") PlyData([new_ply_element]).write("Temp_File_Without_Outliers.ply")
def write_scene_pc(points, output_path): vertex = np.array([tuple(x) for x in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ]) vertex_el = PlyElement.describe(vertex, 'vertex') PlyData([vertex_el]).write(output_path) # write the new ply file
def match(self, perceivedpnts, perceivednormals, ddist = 5.0, dangle = 30.0): """ do a match :return: rotmats of top matches author: weiwei date: 20170802 """ # save txt pverts = np.array([tuple(x) for x in perceivedpnts], dtype=[('x', 'f4'),('y', 'f4'),('z', 'f4')]) el = PlyElement.describe(pverts, 'vertex') PlyData([el], text = True).write('perceivedpnts.ply') # save txt vandnarray = [] for i in range(len(self.temppnts)): v = self.temppnts[i] n = self.tempnormals[i] vandn = (v[0],v[1],v[2],n[0],n[1],n[2]) vandnarray.append(vandn) pverts = np.array(vandnarray, dtype=[('x', 'f4'),('y', 'f4'),('z', 'f4'),\ ('nx','f4'),('ny','f4'),('nz','f4')]) el = PlyElement.describe(pverts, 'vertex') PlyData([el], text = True).write('ttube.ply') accspace = {} # get the preceived global model descriptor nperceivedpnts = perceivedpnts.shape[0] i = np.argmax(perceivedpnts, axis = 0)[2] for j in range(0,nperceivedpnts): print j, nperceivedpnts m_0 = np.asarray(perceivedpnts[i]) m_1 = np.asarray(perceivedpnts[j]) v_m0m1 = m_0-m_1 v_m1m0 = m_1-m_0 n_m0 = perceivednormals[i] n_m1 = perceivednormals[j] # f1, namely ||d||2 f1 = np.linalg.norm(m_0-m_1) # f2, namely angle between n_m0 and v_m1m0 f2 = rm.degree_between(n_m0, v_m1m0) # f3, namely angle between n_m1 and v_m0m1 f3 = rm.degree_between(n_m1, v_m0m1) # f4, namely angle between n_m0 and n_m1 f4 = rm.degree_between(n_m0, n_m1) # discretize the values try: f1d = int(math.floor(f1/ddist)*ddist+ddist) f2d = int(math.floor(f2/dangle)*dangle+dangle) f3d = int(math.floor(f3/dangle)*dangle+dangle) f4d = int(math.floor(f4/dangle)*dangle+dangle) except: continue key = (f1d, f2d, f3d, f4d) # angle between n_m0 and x+ xplus = np.asarray([1,0,0]) yplus = np.asarray([0,1,0]) nm0xangle = math.degrees(rm.radian_between(n_m0, xplus)) rotax = np.cross(xplus, n_m0) if np.isnan(rotax).any() or not rotax.any(): continue rotmat = rm.rodrigues(rotax, nm0xangle) v_m1m0onxplus = np.dot(v_m1m0, rotmat) v_m1m0onxplusyzproj = np.asarray([0, v_m1m0onxplus[1], v_m1m0onxplus[2]]) alpha_m0 = rm.radian_between(v_m1m0onxplusyzproj, yplus) if v_m1m0onxplus[2] < 0: alpha_m0 = 2*math.pi - alpha_m0 if key in self.gmd.keys(): malist = self.gmd[key] print len(malist) for maslot in malist: alpha = math.degrees(alpha_m0-maslot[2]) try: alphadiscrete = int(math.floor(alpha/dangle)*dangle+dangle) except: continue acckey = (maslot[0], alphadiscrete) if acckey in accspace.keys(): accspace[acckey] += 1 else: accspace[acckey] = 1 if len(accspace.keys()) is 0: return (None, None) # find top matches and rot matrices maxn = sorted(accspace.iteritems(), key=operator.itemgetter(1), reverse=True)[:5] rotmat4list = [] silist = [] milist = [] for maxnele in maxn: mi, alpha = maxnele[0] # step1 move to temppnts[mi] displacement0 = -self.temppnts[mi] rotmat4_0 = Mat4.translateMat(displacement0[0], displacement0[1], displacement0[2]) # step2 rotate to goal normalangle = math.degrees(rm.radian_between(self.tempnormals[mi], perceivednormals[i])) normalrotax = np.cross(self.tempnormals[mi], perceivednormals[i]) normalrotmat = rm.rodrigues(normalrotax, normalangle) anglerotmat = rm.rodrigues(perceivednormals[i], -alpha) rotmat = np.dot(anglerotmat, normalrotmat) rotmat4_1 = pg.npToMat4(rotmat) # step3 move to perceivedpnts[i] displacement1 = perceivedpnts[i] rotmat4_2 = Mat4.translateMat(displacement1[0], displacement1[1], displacement1[2]) rotmat4 = rotmat4_0*rotmat4_1*rotmat4_2 rotmat4list.append(rotmat4) silist.append(i) milist.append(mi) return rotmat4list, silist, milist
def write_ply(cloud, file_name): el = PlyElement.describe(cloud, 'vertex') PlyData([el]).write(file_name)
def convert_tsdf_to_ply(tsdf_bin_filename, tsdf_mesh_filename): """ Converts the tsdf binary file to a mesh file in ply format The indexing in the tsdf is (x,y,z) <--> (x + y * dim_x + z * dim_x * dim_y) """ start_time = time.time() fin = open(tsdf_bin_filename, "rb") tsdfHeader = array.array("f") # f is the typecode for float32 tsdfHeader.fromfile(fin, 8) # print tsdfHeader # print type(tsdfHeader) voxelGridDim = tsdfHeader[0:3] voxelGridDim = np.asarray(voxelGridDim, dtype=np.int) voxelGridOrigin = tsdfHeader[3:6] voxelSize = tsdfHeader[6] truncMargin = tsdfHeader[7] dim_x = voxelGridDim[0] dim_y = voxelGridDim[1] dim_z = voxelGridDim[2] headerSize = 8 tsdf_vec = np.fromfile(tsdf_bin_filename, np.float32) tsdf_vec = tsdf_vec[headerSize:] tsdf = np.reshape(tsdf_vec, voxelGridDim, order='F') # reshape using Fortran order # for loop version of the above reshape operation # for x in xrange(0, dim_x): # for y in xrange(0, dim_y): # for z in xrange(0, dim_z): # idx = x + y * dim_x + z * dim_x * dim_y # tsdf[x,y,z] = tsdf_vec[idx] print "tsdf.shape:", tsdf.shape print "voxelGridDim: ", voxelGridDim print "voxeGridOrigin: ", voxelGridOrigin print "tsdf.shape:", tsdf.shape verts, faces, normals, values = measure.marching_cubes_lewiner( tsdf, spacing=[voxelSize] * 3) print "type(verts): ", type(verts) print "verts.shape: ", verts.shape print "faces.shape:", faces.shape print "np.max(verts[:,0]): ", np.max(verts[:, 0]) print "np.min(verts[:,0]): ", np.min(verts[:, 0]) print "verts[0,:] = ", verts[0, :] print "faces[0,:] = ", faces[0, :] # transform from voxel coordinates to camera coordinates # note x and y are flipped in the output of marching_cubes mesh_points = np.zeros_like(verts) # mesh_points = verts mesh_points[:, 0] = voxelGridOrigin[0] + verts[:, 0] mesh_points[:, 1] = voxelGridOrigin[1] + verts[:, 1] mesh_points[:, 2] = voxelGridOrigin[2] + verts[:, 2] # permute faces to get visualization # faces = np.flip(faces, 1) # try writing to the ply file print "converting numpy arrays to format for ply file" ply_conversion_start_time = time.time() num_verts = verts.shape[0] num_faces = faces.shape[0] verts_tuple = np.zeros((num_verts, ), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) faces_tuple = np.zeros((num_faces, ), dtype=[('vertex_indices', 'i4', (3, ))]) for i in xrange(0, num_verts): verts_tuple[i] = tuple(mesh_points[i, :]) for i in xrange(0, num_faces): faces_tuple[i] = faces[i, :].tolist() # save it out # try to save it el_verts = PlyElement.describe(verts_tuple, 'vertex') el_faces = PlyElement.describe(faces_tuple, 'face') ply_data = PlyData([el_verts, el_faces]) print "saving mesh to %s" % (tsdf_mesh_filename) ply = ply_data.write(tsdf_mesh_filename) print "converting to ply format and writing to file took", time.time( ) - start_time
''' programSV3DRegion = glumpy_setting.ProgramSV3DRegion(data=data, name=None, point_size=1, anchor=anchor_matrix_whole) gpyWindow.add_program(programSV3DRegion) print(data['a_position'][0, 0, 0]) print(np.isnan(data['a_position'][0, 0, 0])) print(~np.isnan(data['a_position'][0, 0, 0])) data['a_color'] *= 255 data['a_color'].astype(int) data = data[np.nonzero(~np.isnan(data['a_position'][:, :, 0]))] xyzzz = np.zeros(len(data), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('r', 'f4'), ('g', 'f4'), ('b', 'f4')]) xyzzz['x'] = data['a_position'][:, 0] xyzzz['y'] = data['a_position'][:, 1] xyzzz['z'] = data['a_position'][:, 2] xyzzz['r'] = data['a_color'][:, 0] xyzzz['g'] = data['a_color'][:, 1] xyzzz['b'] = data['a_color'][:, 2] el = PlyElement.describe(xyzzz, 'vertex') PlyData([el]).write('some_binary.ply') PlyData([el], text=True).write('some_ascii.ply') programAxis = glumpy_setting.ProgramAxis(line_length=5) gpyWindow.add_program(programAxis) gpyWindow.run()
for f in mesh.faces: faces.append((np.array(f[0:3]) + len(verts0),)) n0 = cad_mesh.parser.normals[f[3]] v0 = cad_mesh.vertices[f[0]] v1 = cad_mesh.vertices[f[1]] v2 = cad_mesh.vertices[f[2]] if len(v0) == 3: cad_mesh.vertices[f[0]] = v0 + n0 + color if len(v1) == 3: cad_mesh.vertices[f[1]] = v1 + n0 + color if len(v2) == 3: cad_mesh.vertices[f[2]] = v2 + n0 + color faces0.extend(faces) for v in cad_mesh.vertices[:]: if len(v) != 9: v = (0, 0, 0) + (0, 0, 0) + (0, 0, 0) vi = tuple(np.dot(Mcad, np.array([v[0], v[1], v[2], 1]))[0:3]) ni = tuple(np.dot(np.linalg.inv(Mcad).transpose(), np.array([v[3], v[4], v[5], 1]))[0:3]) ci = tuple(v[6:9]) verts.append(vi + ni + ci) verts0.extend(verts) verts0 = np.asarray(verts0, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) faces0 = np.asarray(faces0, dtype=[('vertex_indices', 'i4', (3,))]) objdata = PlyData([PlyElement.describe(verts0, 'vertex', comments=['vertices']), PlyElement.describe(faces0, 'face')], comments=['faces']) with open(outdir + "/alignment.ply", mode='wb') as f: PlyData(objdata).write(f)
return face if __name__ == "__main__": # load image img0 = np.array(Image.open("gargoyle/disp1.pgm"), dtype="int64") img1 = np.array(Image.open("gargoyle/view3.png")) img2 = np.array(Image.open("gargoyle/disp5.pgm"), dtype="int64") # construct 3d coordinates coords3d = [] coords3d1 = construct3D(img0, 1) coords3d2 = construct3D(img2, 5) coords3d = coords3d1 + coords3d2 # get disp map # depth_map = project_nearest(coords3d) disp_map = project_nearest(coords3d) # scipy.misc.imsave('disp3.png', disp_map) # connect raw_face = generate_mesh(disp_map) raw_vertex = construct_and_texture(disp_map, img1, 3) vertex = np.array( raw_vertex, dtype=[("x", "f4"), ("y", "f4"), ("z", "f4"), ("red", "u1"), ("green", "u1"), ("blue", "u1")] ) face = np.array(raw_face, dtype=[("vertex_indices", "int32", (3,))]) elv = PlyElement.describe(vertex, "vertex") elf = PlyElement.describe(face, "face") PlyData([elv, elf]).write("mesh.ply")
parser.add_argument('--bbmax', nargs=3, type=float, help='bounding box max', default=[np.inf, np.inf, np.inf]) args = parser.parse_args() minx, miny, minz, maxx, maxy, maxz = args.bbmin[0], args.bbmin[1], args.bbmin[ 2], args.bbmax[0], args.bbmax[1], args.bbmax[2] print(args) vertex = [] with open(args.infile) as f: for line in f: if line[0] != '#': ls = line.strip().split() x, y, z = float(ls[0]), float(ls[1]), float(ls[2]) nx, ny, nz = float(ls[3]), float(ls[4]), float(ls[5]) if (x >= minx) and (x <= maxx) and (y >= miny) and ( y <= maxy) and (z >= minz) and (z <= maxz): vertex.append( (x, y, z, nx, ny, nz, int(ls[6]), int(ls[7]), int(ls[8]))) print('num vertices', len(vertex)) vertex = np.array(vertex, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('nx', 'f4'), ('ny', 'f4'), ('nz', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) el = PlyElement.describe(vertex, 'vertex') PlyData([el]).write(args.outfile)
def save_ply(vert,face,fname): el1 = PlyElement.describe(np.array([(x[0],x[1],x[2]) for x in vert],dtype=[('x', 'f8'), ('y', 'f8'),('z', 'f8')]), 'vertex') el2 = PlyElement.describe(np.array([([x[0],x[1],x[2]], 0) for x in face],dtype=[('vertex_indices', 'i4', (3,)), ('red', 'u1')]), 'face') PlyData([el1,el2], text=True).write(fname)
(0, 1, 1), (1, 0, 1), (1, 1, 0)], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) face = numpy.array([([0, 1, 2], 255, 255, 255), ([0, 2, 3], 255, 0, 0), ([0, 1, 3], 0, 255, 0), ([1, 2, 3], 0, 0, 255)], dtype=[('vertex_indices', 'i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) print "Assembling initial PlyData instance..." ply0 = PlyData([PlyElement.describe(vertex, 'vertex', comments=['tetrahedron vertices']), PlyElement.describe(face, 'face')], text=True, comments=['single tetrahedron with colored faces']) print "Writing test0.ply (ascii)..." ply0.write('test0.ply') print "Reading test0.ply..." ply1 = PlyData.read('test0.ply') print "(verifying result...)" verify(ply0, ply1) print "Writing test1.ply (binary_little_endian)..." ply1.text = False
vertex_normal[index3] = np.add(vertex_normal[index3], normal2) # 3, normalize vector for i in range(0, vertex_number): vertex_normal[i] = normalize(vertex_normal[i]) # 4, write to ply result = [] # The properties are 'x, y, z, nx, ny, nz' for i in range(0, vertex_number): record = ( plyData["vertex"][i][0], plyData["vertex"][i][1], plyData["vertex"][i][2], vertex_normal[i][0], vertex_normal[i][1], vertex_normal[i][2], ) result.append(record) # print(result) new_vertex_data = np.array( result, dtype=[("x", "float32"), ("y", "float32"), ("z", "float32"), ("nx", "float"), ("ny", "float"), ("nz", "float")], ) elv = PlyElement.describe(new_vertex_data, "vertex") PlyData([elv]).write("p1.ply") # 5, write to txt np.savetxt("test.txt", new_vertex_data, delimiter=" ", fmt="%.6f")
def test_invalid_property_names(): with Raises(ValueError): PlyElement.describe(numpy.zeros(1, dtype=[('\xb0', 'i4')]), 'test') with Raises(ValueError): PlyElement.describe(numpy.zeros(1, dtype=[('a b', 'i4')]), 'test')
def filter_depth(dataset_root, scan, out_folder, plyfilename): print("Starting fusion for:" + out_folder) # the pair file pair_file = os.path.join(dataset_root, 'Cameras/pair.txt') # for the final point cloud vertexs = [] vertex_colors = [] pair_data = read_pair_file(pair_file) nviews = len(pair_data) # for each reference view and the corresponding source views for ref_view, src_views in pair_data: # load the camera parameters ref_intrinsics, ref_extrinsics = read_camera_parameters( os.path.join(dataset_root, 'Cameras/{:0>8}_cam.txt'.format(ref_view))) # load the reference image ref_img = read_img( os.path.join( dataset_root, "Rectified", scan, 'rect_{:03d}_3_r5000.png'.format(ref_view + 1))) # Image start from 1. # load the estimated depth of the reference view ref_depth_est, scale = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(ref_view))) # load the photometric mask of the reference view confidence, scale = read_pfm( os.path.join(out_folder, 'confidence/{:0>8}.pfm'.format(ref_view))) photo_mask = confidence > 0.9 all_srcview_depth_ests = [] all_srcview_x = [] all_srcview_y = [] all_srcview_geomask = [] # compute the geometric mask geo_mask_sum = 0 for src_view in src_views: # camera parameters of the source view src_intrinsics, src_extrinsics = read_camera_parameters( os.path.join(dataset_root, 'Cameras/{:0>8}_cam.txt'.format(src_view))) # the estimated depth of the source view src_depth_est, scale = read_pfm( os.path.join(out_folder, 'depth_est/{:0>8}.pfm'.format(src_view))) geo_mask, depth_reprojected, x2d_src, y2d_src = check_geometric_consistency( ref_depth_est, ref_intrinsics, ref_extrinsics, src_depth_est, src_intrinsics, src_extrinsics) geo_mask_sum += geo_mask.astype(np.int32) all_srcview_depth_ests.append(depth_reprojected) all_srcview_x.append(x2d_src) all_srcview_y.append(y2d_src) all_srcview_geomask.append(geo_mask) depth_est_averaged = (sum(all_srcview_depth_ests) + ref_depth_est) / (geo_mask_sum + 1) # at least 3 source views matched geo_mask = geo_mask_sum >= 3 final_mask = np.logical_and(photo_mask, geo_mask) os.makedirs(os.path.join(out_folder, "mask"), exist_ok=True) save_mask( os.path.join(out_folder, "mask/{:0>8}_photo.png".format(ref_view)), photo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_geo.png".format(ref_view)), geo_mask) save_mask( os.path.join(out_folder, "mask/{:0>8}_final.png".format(ref_view)), final_mask) print("processing {}, ref-view{:0>2}, photo/geo/final-mask:{}/{}/{}". format(scan, ref_view, photo_mask.mean(), geo_mask.mean(), final_mask.mean())) height, width = depth_est_averaged.shape[:2] x, y = np.meshgrid(np.arange(0, width), np.arange(0, height)) # valid_points = np.logical_and(final_mask, ~used_mask[ref_view]) valid_points = final_mask print("valid_points", valid_points.mean()) x, y, depth = x[valid_points], y[valid_points], depth_est_averaged[ valid_points] ref_img = np.array(ref_img) color = ref_img[valid_points] xyz_ref = np.matmul(np.linalg.inv(ref_intrinsics), np.vstack((x, y, np.ones_like(x))) * depth) xyz_world = np.matmul(np.linalg.inv(ref_extrinsics), np.vstack((xyz_ref, np.ones_like(x))))[:3] vertexs.append(xyz_world.transpose((1, 0))) vertex_colors.append((color).astype(np.uint8)) vertexs = np.concatenate(vertexs, axis=0) vertex_colors = np.concatenate(vertex_colors, axis=0) vertexs = np.array([tuple(v) for v in vertexs], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) vertex_colors = np.array([tuple(v) for v in vertex_colors], dtype=[('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) vertex_all = np.empty(len(vertexs), vertexs.dtype.descr + vertex_colors.dtype.descr) for prop in vertexs.dtype.names: vertex_all[prop] = vertexs[prop] for prop in vertex_colors.dtype.names: vertex_all[prop] = vertex_colors[prop] el = PlyElement.describe(vertex_all, 'vertex') print("Saving the final model to", plyfilename) PlyData([el], comments=['Model created by AACVP-MVSNet.']).write(plyfilename) print("Model saved.")
if createSV and needOutput: data = programSV3DRegion.data data['a_color'] *= 255 data['a_color'].astype(int) dataPLY = np.zeros(len(data), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) dataPLY['x'] = data['a_position'][:, 0] dataPLY['y'] = data['a_position'][:, 1] dataPLY['z'] = data['a_position'][:, 2] dataPLY['red'] = data['a_color'][:, 0] dataPLY['green'] = data['a_color'][:, 1] dataPLY['blue'] = data['a_color'][:, 2] el = PlyElement.describe(dataPLY, 'vertex') # PlyData([el], text=True).write('137_4_ascii.ply') PlyData([el]).write('/home/andy/src/ply/' + fileID + '_non_ground_binary.ply') if needGround: dataGnd = programSV3DRegion.data dataGnd['a_color'] *= 255 dataGnd['a_color'].astype(int) dataPLY = np.zeros(len(dataGnd), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) dataPLY['x'] = dataGnd['a_position'][:, 0] dataPLY['y'] = dataGnd['a_position'][:, 1] dataPLY['z'] = dataGnd['a_position'][:, 2]
""" ALL PLY EXPORT IN HERE """ data = programSV3DRegion.data data['a_color'] *= 255 data['a_color'].astype(int) xyzzz = np.zeros(len(data), dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) xyzzz['x'] = data['a_position'][:, 0] xyzzz['y'] = data['a_position'][:, 1] xyzzz['z'] = data['a_position'][:, 2] xyzzz['red'] = data['a_color'][:, 0] xyzzz['green'] = data['a_color'][:, 1] xyzzz['blue'] = data['a_color'][:, 2] el = PlyElement.describe(xyzzz, 'vertex') face = np.zeros(len(tri), dtype=[('vertex_indices', 'i4', 3)]) face['vertex_indices'] = tri tri = PlyElement.describe(face, 'face') PlyData([el, tri], text=True).write('some_ascii.ply') #PlyData([el]).write('over_simple_binary.ply') """ ALL PLY EXPORT IN HERE """ programAxis = glumpy_setting.ProgramAxis(line_length=5) gpyWindow.add_program(programAxis) gpyWindow.run()
def save_point_cloud(points_3d, filename, binary=True, with_label=False, verbose=True): """Save an RGB point cloud as a PLY file. Args: points_3d: Nx6 matrix where points_3d[:, :3] are the XYZ coordinates and points_3d[:, 4:] are the RGB values. If Nx3 matrix, save all points with [128, 128, 128] (gray) color. """ assert points_3d.ndim == 2 if with_label: assert points_3d.shape[1] == 7 or points_3d.shape[1] == 8 if points_3d.shape[1] == 7: python_types = (float, float, float, int, int, int, int) npy_types = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ('label', 'u1')] else: python_types = (float, float, float, int, int, int, int, int) npy_types = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ('label_class', 'u1'), ('label_instance', 'u2')] else: if points_3d.shape[1] == 3: gray_concat = np.tile(np.array([128], dtype=np.uint8), (points_3d.shape[0], 3)) points_3d = np.hstack((points_3d, gray_concat)) assert points_3d.shape[1] == 6 python_types = (float, float, float, int, int, int) npy_types = [('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')] if binary is True: # Format into NumPy structured array vertices = [] for row_idx in range(points_3d.shape[0]): cur_point = points_3d[row_idx] vertices.append( tuple( dtype(point) for dtype, point in zip(python_types, cur_point))) vertices_array = np.array(vertices, dtype=npy_types) el = PlyElement.describe(vertices_array, 'vertex') # Write PlyData([el]).write(filename) else: # PlyData([el], text=True).write(filename) with open(filename, 'w') as f: f.write('ply\n' 'format ascii 1.0\n' 'element vertex %d\n' 'property float x\n' 'property float y\n' 'property float z\n' 'property uchar red\n' 'property uchar green\n' 'property uchar blue\n' 'property uchar alpha\n' 'end_header\n' % points_3d.shape[0]) for row_idx in range(points_3d.shape[0]): X, Y, Z, R, G, B = points_3d[row_idx] f.write('%f %f %f %d %d %d 0\n' % (X, Y, Z, R, G, B)) if verbose is True: print('Saved point cloud to: %s' % filename)
def make_ply_string(dest_path, indices, vertices, rgba_color): """ Creates a ply str that can be included into a .k.zip for rendering in KNOSSOS. # TODO: write out normals Parameters ---------- indices : np.array vertices : np.array rgba_color : Tuple[uint8] or np.array Returns ------- str """ # create header vertices = vertices.astype(np.float32) indices = indices.astype(np.int32) if not indices.ndim == 2: indices = np.array(indices, dtype=np.int).reshape((-1, 3)) if not vertices.ndim == 2: vertices = np.array(vertices, dtype=np.float32).reshape((-1, 3)) if len(rgba_color) != len(vertices) and len(rgba_color) == 4: # TODO: create per tree color instead of per vertex color rgba_color = np.array([rgba_color for i in range(len(vertices))], dtype=np.uint8) else: if not (len(rgba_color) == len(vertices) and len(rgba_color[0]) == 4): msg = 'Color array has to be RGBA and to provide a color value f' \ 'or every vertex!' log_proc.error(msg) raise ValueError(msg) if not rgba_color.ndim == 2: rgba_color = np.array(rgba_color, dtype=np.int).reshape((-1, 4)) if type(rgba_color) is list: rgba_color = np.array(rgba_color, dtype=np.uint8) log_proc.warn("Color input is list. It will now be converted " "automatically, data will be unusable if not normalized" " between 0 and 255. min/max of data:" " {}, {}".format(rgba_color.min(), rgba_color.max())) elif rgba_color.dtype.kind != "u1": log_proc.warn("Color array is not of type integer or unsigned integer." " It will now be converted automatically, data will be " "unusable if not normalized between 0 and 255." "min/max of data: {}, {}".format(rgba_color.min(), rgba_color.max())) rgba_color = np.array(rgba_color, dtype=np.uint8) # ply file requires 1D object arrays, vertices = np.concatenate( [vertices.astype(np.object), rgba_color.astype(np.object)], axis=1) vertices = np.array([tuple(el) for el in vertices], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1'), ('alpha', 'u1')]) # ply file requires 1D object arrays. indices = np.array([tuple([el], ) for el in indices], dtype=[('vertex_indices', 'i4', (3, ))]) PlyData([ PlyElement.describe(vertices, 'vertex'), PlyElement.describe(indices, 'face') ]).write(dest_path)