def test_smoothing(volume): ROUNDS = 3 vertices, normals, faces = marching_cubes.march(volume, 0) smoothed_vertices, smoothed_normals, smoothed_faces = marching_cubes.march(volume, ROUNDS) # Compare with our reference implementation of laplacian smoothing. ref_smoothed_vertices = laplacian_smooth(vertices, faces, ROUNDS) np.allclose(smoothed_vertices, ref_smoothed_vertices, rtol=0.001) assert (faces == smoothed_faces).all(), \ "Smoothing should not affect face definitions." assert not (normals == smoothed_normals).all(), \ "Normals should not be the same after smoothing."
def test_c_and_f_order_agnostic(volume): # take a assymetric volume shape_z, shape_y, shape_x = volume.shape vol_c = np.ascontiguousarray(volume[0:shape_z // 2, 0:shape_y // 3, 0:shape_x // 5]) assert len(np.unique(vol_c.shape)) == len(vol_c.shape) assert vol_c.flags['C_CONTIGUOUS'] vol_f = np.copy(vol_c, order="f") assert vol_f.flags['F_CONTIGUOUS'] mesh_data_c = marching_cubes.march(vol_c, 0) mesh_data_h = marching_cubes.march(vol_f, 0) for a, b in zip(mesh_data_c, mesh_data_h): assert (a == b).all()
def calcMesh(stackname, labelStack, simplify): indices = np.where(labelStack>0) box, dimensions = findBBDimensions(indices) window = labelStack[box[0]:box[1], box[2]:box[3], box[4]:box[5]] localIndices = np.where(window > 0) paddedWindowSizeList = list(window.shape) paddedWindowSize = tuple([i+2 for i in paddedWindowSizeList]) blankImg = np.zeros(paddedWindowSize, dtype=bool) blankImg[tuple(([i+1 for i in localIndices[0]], [i+1 for i in localIndices[1]], [i+1 for i in localIndices[2]]))] = 1 print("Building mesh...") vertices, normals, faces = march(blankImg.transpose(), 3) # zero smoothing rounds with open(stackname +".obj", 'w') as f: f.write("# OBJ file\n") for v in vertices: f.write("v %.2f %.2f %.2f \n" % ((box[0] * SCALEX) + (v[2] * SCALEX), (box[2] * SCALEY) + (v[1] * SCALEY), (box[4] * SCALEZ) + v[0] + totalZ)) for n in normals: f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) for face in faces: f.write("f %d %d %d \n" % (face[0]+1, face[1]+1, face[2]+1)) print("Decimating Mesh...") largeZ = box[5] s = 'fq-mesh-simplify' + ' ./' + stackname +".obj ./" + stackname +".smooth.obj " + str(simplify) print(s) #subprocess.call(s, shell=True) return largeZ
def calcMesh(stackname, labelStack, location, simplify_ratio): tags = getTagDictionary(stackname) downsampleFactor = float(tags['downsample_interval_x']) xOffset = float(tags['dvid_offset_x']) yOffset = float(tags['dvid_offset_y']) zOffset = float(tags['dvid_offset_z']) labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") vertices, normals, faces = march(labelStack, 3) # 3 smoothing rounds print('preparing vertices and faces...') vertStrings = ["v %.3f %.3f %.3f \n" % ((xOffset + i[0]) * downsampleFactor, (yOffset + i[1]) * downsampleFactor, (zOffset + i[2]) * downsampleFactor) for i in vertices] faceStrings = ["f %d %d %d \n" % (face[2]+1, face[1]+1, face[0]+1) for face in faces] with open(location + os.path.basename(stackname) +".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings)) print("Decimating Mesh...") input_path = "./" + location + os.path.basename(stackname) +".obj" output_path = "./" + location + os.path.basename(stackname) +".smooth.obj" cmd = f'fq-mesh-simplify "{input_path}" "{output_path}" {simplify_ratio}' print(cmd) subprocess.call(cmd, shell=True)
def marching_cubes(obj, smoothing_iterations=0, resolution=None, use_ilastik=False): """ Compute mesh via marching cubes. Arguments: obj [np.ndarray] - volume containing the object to be meshed smoothing_iterations [int] - number of mesh smoothing iterations (default: 0) resolution[listlike[int]] - resolution of the data (default: None) use_ilastik [bool] - whether to use the ilastk marching cubes implementation. Default is skimage (default: False) """ resolution = (1., 1., 1.) if resolution is None else resolution if len(resolution) != 3: raise ValueError(f"Invalid resolution argument: {resolution}") resolution = tuple(resolution) if use_ilastik: if march is None: raise RuntimeError("Ilastik marching cubes implementation not found") if resolution is not None: raise RuntimeError("Ilastik marching cubes does not support resolution.") verts, normals, faces = march(obj.T, smoothing_iterations) verts = verts[:, ::-1] else: verts, faces, normals, _ = marching_cubes_lewiner(obj, spacing=resolution) if smoothing_iterations > 0: if nifty is None: raise RuntimeError("Need nifty to perform mesh smoothing") verts, normals = smooth_mesh(verts, normals, faces, smoothing_iterations) return verts, faces, normals
def calcMesh(stackname, labelStack, location, simplify, tags): labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") vertices, normals, faces = march(labelStack, 3) # 3 smoothing rounds print('preparing vertices and faces...') newVerts = [[i[0], i[1], i[2]] for i in vertices] vertStrings = [ "v %.3f %.3f %.3f \n" % (i[0], i[1], i[2]) for i in newVerts ] faceStrings = [ "f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1) for face in faces ] with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings)) print("Decimating Mesh...") s = 'fq-mesh-simplify' + ' ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) print(s) subprocess.call(s, shell=True)
def calcMesh(stackname, labelStack, location, simplify): #code.interact(local=locals()) labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") vertices, normals, faces = march(labelStack, 0) # 3 smoothing rounds print('preparing vertices and faces...') #code.interact(local=locals()) vertStrings = [ "v %.3f %.3f %.3f \n" % (i[0] - 1, i[1] - 1, i[2] - 1) for i in vertices ] faceStrings = [ "f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1) for face in faces ] with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings))
def test_regression(volume, mesh_loader, smoothing, reference_mesh_file): vertices, normals, faces = marching_cubes.march(volume, smoothing) ref_vertices, ref_normals, ref_faces = mesh_loader(reference_mesh_file) numpy.testing.assert_array_almost_equal(vertices, ref_vertices) numpy.testing.assert_array_almost_equal(normals, ref_normals) numpy.testing.assert_array_almost_equal(faces, ref_faces)
def test_regression(volume, mesh_loader, smoothing, reference_mesh_file): vertices, normals, faces = marching_cubes.march(volume, smoothing) ref_vertices, ref_normals, ref_faces = mesh_loader(reference_mesh_file) np.testing.assert_array_almost_equal(vertices, ref_vertices) np.testing.assert_array_almost_equal(normals, ref_normals) assert (faces == ref_faces).all()
def labeling_to_mesh(labeling, labels): for label in labels: vertices, normals, faces = march(where(labeling == label, 2, 0).astype(int).T, 4) data = MeshData(vertices, faces) if normals is not None: data._vertexNormals = normals yield label, data
def GenerateStl(self, id): mask = (self.small_ids == id) vertices, normals, faces = march(mask, 2) print('Generated faces size: ', faces.shape) our_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): our_mesh.vectors[i][j] = vertices[f[j], :] return our_mesh
def calcMeshWithCrop(stackname, labelStack, location, simplify, tags): print(str(tags['downsample_interval_x'])) SCALEX = tags['downsample_interval_x'] SCALEY = tags['downsample_interval_x'] SCALEZ = tags['downsample_interval_x'] indices = np.where(labelStack > 0) box, dimensions = findBBDimensions(indices) window = labelStack[box[0]:box[1], box[2]:box[3], box[4]:box[5]] localIndices = np.where(window > 0) paddedWindowSizeList = list(window.shape) paddedWindowSize = tuple([i + 2 for i in paddedWindowSizeList]) blankImg = np.zeros(paddedWindowSize, dtype=bool) blankImg[tuple( ([i + 1 for i in localIndices[0]], [i + 1 for i in localIndices[1]], [i + 1 for i in localIndices[2]]))] = 1 print("Building mesh...") vertices, normals, faces = march(blankImg.transpose(), 3) # zero smoothing rounds with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") for v in vertices: f.write("v %.2f %.2f %.2f \n" % ((box[0] * SCALEX) + ((float(tags['dvid_offset_x']) + v[0]) * SCALEX), (box[2] * SCALEY) + ((float(tags['dvid_offset_x']) + v[1]) * SCALEY), (box[4] * SCALEZ) + (float(tags['dvid_offset_x']) + v[2]) * SCALEZ)) #for n in normals: #f.write("vn -1 -1 -1 \n")# % (n[2], n[1], n[0])) for face in faces: f.write("f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1)) print("Decimating Mesh...") if os.name == 'nt': s = './binWindows/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) else: if platform.system() == "Darwin": s = './binOSX/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) else: s = './binLinux/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) print(s) subprocess.call(s, shell=True)
def calcMeshWithOffsets(stackname, labelStack, location, simplify, tags): print(str(tags['downsample_interval_x'])) downsampleFactor = float(tags['downsample_interval_x']) xOffset = float(tags['dvid_offset_x']) yOffset = float(tags['dvid_offset_y']) zOffset = float(tags['dvid_offset_z']) labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") try: vertices, normals, faces = march(labelStack, 3) # 3 smoothing rounds except: return print('preparing vertices and faces...') newVerts = [[((xOffset + i[0]) * downsampleFactor), ((yOffset + i[1]) * downsampleFactor), ((zOffset + i[2]) * downsampleFactor)] for i in vertices] vertStrings = [ "v %.3f %.3f %.3f \n" % (i[0], i[1], i[2]) for i in newVerts ] faceStrings = [ "f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1) for face in faces ] with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings)) print("Decimating Mesh...") if os.name == 'nt': s = 'binWindows\\simplify.exe ' + location[:-1] + '\\' + os.path.basename( stackname) + ".obj " + location[:-1] + '\\' + os.path.basename( stackname) + ".smooth.obj " + str(simplify) return else: if platform.system() == "Darwin": s = './binOSX/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) else: s = './binLinux/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) print(s) subprocess.call(s, shell=True)
def marching_cubes(obj, smoothing_iterations=0, use_ilastik=False): if use_ilastik: if march is None: raise RuntimeError( "Ilastik marching cubes implementation not found") verts, normals, faces = march(obj.T, smoothing_iterations) verts = verts[:, ::-1] else: verts, faces, normals, _ = marching_cubes_lewiner(obj) if smoothing_iterations > 0: verts, normals = smooth_mesh(verts, normals, faces, smoothing_iterations) return verts, faces, normals
def GenerateStl(self, id): mask = (self.small_ids == id) try: vertices, normals, faces = march(mask, 2) except: print('Mesh was not generated.') return False print('Generated face number: ', faces.shape) our_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): our_mesh.vectors[i][j] = vertices[f[j], :] ### our_mesh.save(os.path.join(stldata_dir, 'i{0}.stl'.format(id))) return True
def calcMesh(stackname, labelStack, simplify): indices = np.where(labelStack>0) box, dimensions = findBBDimensions(indices) window = labelStack[box[0]:box[1], box[2]:box[3], box[4]:box[5]] localIndices = np.where(window > 0) paddedWindowSizeList = list(window.shape) paddedWindowSize = tuple([i+2 for i in paddedWindowSizeList]) blankImg = np.zeros(paddedWindowSize, dtype=bool) blankImg[tuple(([i+1 for i in localIndices[0]], [i+1 for i in localIndices[1]], [i+1 for i in localIndices[2]]))] = 1 print("Building mesh...") vertices, normals, faces = march(blankImg.transpose(), 3) # zero smoothing rounds return (vertices, normals, faces, box)
def calcMeshWithOffsets(stackname, labelStack, location, simplify): tags = getTagDictionary(stackname) downsampleFactor = float(tags['downsample_interval_x']) xOffset = float(tags['dvid_offset_x']) yOffset = float(tags['dvid_offset_y']) zOffset = float(tags['dvid_offset_z']) labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") vertices, normals, faces = march(labelStack, 3) # 3 smoothing rounds print('preparing vertices and faces...') newVerts = [[((xOffset + i[0]) * downsampleFactor), ((yOffset + i[1]) * downsampleFactor), ((zOffset + i[2]) * downsampleFactor)] for i in vertices] vertStrings = [ "v %.3f %.3f %.3f \n" % (i[0] - 1.0, i[1] - 1.0, i[2] - 1.0) for i in newVerts ] faceStrings = [ "f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1) for face in faces ] with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings)) print("Decimating Mesh...") #if os.name == 'nt': # s = 'fq-mesh-simplify' + location[:-1] + '\\' + os.path.basename(stackname) +".obj " + location[:-1] + '\\' + os.path.basename(stackname) +".smooth.obj " + str(simplify) # return assert platform.system() in ("Darwin", "Linux"), "Windows not supported." s = 'fq-mesh-simplify' + ' ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) print(s) subprocess.call(s, shell=True)
def calcMesh(stackname, labelStack, location, simplify, tags): labelStack = np.swapaxes(labelStack, 0, 2) print("Building mesh...") vertices, normals, faces = march(labelStack, 3) # 3 smoothing rounds print('preparing vertices and faces...') newVerts = [[i[0], i[1], i[2]] for i in vertices] vertStrings = [ "v %.3f %.3f %.3f \n" % (i[0], i[1], i[2]) for i in newVerts ] faceStrings = [ "f %d %d %d \n" % (face[2] + 1, face[1] + 1, face[0] + 1) for face in faces ] with open(location + os.path.basename(stackname) + ".obj", 'w') as f: f.write("# OBJ file\n") print("writing vertices...") f.write(''.join(vertStrings)) #for n in normals: # f.write("vn %.2f %.2f %.2f \n" % (n[2], n[1], n[0])) print("writing faces...") f.write(''.join(faceStrings)) print("Decimating Mesh...") if os.name == 'nt': s = 'binWindows\\simplify.exe ' + location[:-1] + '\\' + os.path.basename( stackname) + ".obj " + location[:-1] + '\\' + os.path.basename( stackname) + ".smooth.obj " + str(simplify) return else: if platform.system() == "Darwin": s = './binOSX/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) else: s = './binLinux/simplify ./' + location + os.path.basename( stackname) + ".obj ./" + location + os.path.basename( stackname) + ".smooth.obj " + str(simplify) print(s) subprocess.call(s, shell=True)
from marching_cubes import march from numpy import load import os import time from pyqtgraph.opengl import GLViewWidget, MeshData from pyqtgraph.opengl.items.GLMeshItem import GLMeshItem from PyQt5.QtGui import QApplication volume = load(os.path.join( os.path.split(__file__)[0], 'data/input/sample.npy')) t0 = time.time() vertices, normals, faces = march(volume, 0) # zero smoothing rounds smooth_vertices, smooth_normals, faces = march(volume, 4) # 4 smoothing rounds t1 = time.time() print("took", t1 - t0, "sec") app = QApplication([]) view = GLViewWidget() mesh = MeshData(vertices / 100.0, faces) # scale down - otherwise camera is misplaced # or mesh = MeshData(smooth_vertices / 100, faces) mesh._vertexNormals = normals # or mesh._vertexNormals = smooth_normals item = GLMeshItem(meshdata=mesh, color=[1, 0, 0, 1], shader="normalColor") view.addItem(item)
def Run(self): ### ### print('Export Stl Files.') ## Obtain biggest ID con = sqlite3.connect(self.u_info.segment_info_db_file) cur = con.cursor() cur.execute('select id, max(size) from segmentInfo;') maxid = cur.fetchone()[0] con.commit() con.close() #maxid = 15 print('Obtain id: ', maxid) mask = (self.small_ids == maxid) # print('Mask was made.') # print('Mask Size: ', mask.shape) # print('Mask Type: ', mask.dtype) # print('Mask volume: ', np.sum(mask) ) # plt.imshow(mask[:, :, 50]) # plt.show() ## Generate mesh # volume = np.load( path.join(current_dir, "sample.npy") ) # iw = 1 # volume = volume[::(2 ** iw), ::(2 ** iw), :] # print('Volume was loaded.') # print('Max Volme: ', np.max(volume)) # print('Volme Size: ', volume.shape) # print('Volme Type: ', volume.dtype) # print('Volume volume: ', np.sum(volume)) # plt.imshow(volume[:, :, 50]) # plt.show() vertices, normals, faces = march(mask, 2) print('Faces size: ', faces.shape) # faces = np.array(faces) # vertices = np.array(vertices) # app = QApplication([]) # view = GLViewWidget() # mesh = MeshData(vertices / 100, faces) # mesh._vertexNormals = normals # item = GLMeshItem(meshdata=mesh, color=[1, 0, 0, 1], shader="normalColor") # view.addItem(item) # view.show() # app.exec_() ## ## ## print('Mesh was made.') m.save_hdf5(path.join(pparent_dir, 'vertices.h5'), 'data', vertices) m.save_hdf5(path.join(pparent_dir, 'faces.h5'), 'data', normals) m.save_hdf5(path.join(pparent_dir, 'normals.h5'), 'data', faces) our_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): # for j in range(3): # our_mesh.vectors[i][j] = vertices[f[j], :] our_mesh.vectors[i][2] = vertices[f[0], :] our_mesh.vectors[i][1] = vertices[f[1], :] our_mesh.vectors[i][0] = vertices[f[2], :] #print('F shape: ', f.shape) #print('F shape: ',vertices[0, :]) ## Export mesh volume, cog, inertia = our_mesh.get_mass_properties() our_mesh.x -= cog[0] our_mesh.y -= cog[1] our_mesh.z -= cog[2] our_mesh.save(path.join(pparent_dir, 'maxsize_obj.stl')) print('Stl was saved.')
# # view.addItem(item) # view.show() # app.exec_() if __name__ == "__main__": # vertices, faces, normals, values = np.load("/export/home/amatskev/Bachelor/data/first_try/mesh_data.npy") volume=np.load("/mnt/localdata03/amatskev/neuraldata/test/difficult_volume.npy") print "loading finished" time1=time() vertices, normals, faces = march(volume, 0) time2=time() print time2-time1 np.save("/mnt/localdata03/amatskev/neuraldata/test/marching_cubes1.npy",(vertices, normals, faces)) # plot_mesh(vertices, faces) # # volume = np.load("/export/home/amatskev/Bachelor/data/first_try/first_try_Volume.npy") # testvolume=np.load("/export/home/amatskev/Bachelor/marching_cubes/test/sample.npy") # vertices, faces, normals, values = measure.marching_cubes_lewiner(volume,
def mesh_from_array(volume_zyx, box_zyx, downsample_factor=1, simplify_ratio=None, smoothing_rounds=3, output_format='obj'): """ Given a binary volume, convert it to a mesh in .obj format, optionally simplified. volume_zyx: Binary volume (ZYX order) box: Bounding box of the the volume data in global non-downsampled coordinates [(z0,y0,x0), (z1,y1,x1)] downsample_factor: Factor by which the given volume has been downsampled from its original size simplify_ratio: How much to simplify the generated mesh (or None to skip simplification) smoothing_rounds: Passed to marching_cubes.march() output_format: Either 'drc' or 'obj' """ assert output_format in ('obj', 'drc'), \ f"Unknown output format: {output_format}. Expected one of ('obj', 'drc')" if simplify_ratio == 1.0: simplify_ratio = None volume_xyz = volume_zyx.transpose() box_xyz = np.asarray(box_zyx)[:, ::-1] vertices_xyz, _normals, faces = march(volume_xyz, smoothing_rounds) # Rescale and translate vertices_xyz[:] *= downsample_factor vertices_xyz[:] += box_xyz[0] # I don't understand why we write face vertices in reverse order... # ...does marching_cubes give clockwise order instead of counter-clockwise? # Is it because we passed a fortran-order array? faces = faces[:, ::-1] faces += 1 mesh_stream = generate_obj(vertices_xyz, faces) child_processes = [] try: if simplify_ratio is not None: simplify_input_pipe = TemporaryNamedPipe('input.obj') simplify_input_pipe.start_writing_stream(mesh_stream) simplify_output_pipe = TemporaryNamedPipe('output.obj') cmd = f'fq-mesh-simplify {simplify_input_pipe.path} {simplify_output_pipe.path} {simplify_ratio}' child_processes.append((cmd, subprocess.Popen(cmd, shell=True))) mesh_stream = simplify_output_pipe.open_stream('rb') if output_format == 'drc': # Sadly, draco is incapable of reading from non-seekable inputs. # It requires an actual input file, so we can't use a named pipe to avoid disk I/O. # But at least we can use a pipe for the output... mesh_dir = AutoDeleteDir(tempfile.mkdtemp()) mesh_path = f'{mesh_dir}/mesh.obj' with open(mesh_path, 'wb') as mesh_file: copyfileobj(mesh_stream, mesh_file) draco_output_pipe = TemporaryNamedPipe('output.drc') cmd = f'draco_encoder -cl 5 -i {mesh_path} -o {draco_output_pipe.path}' child_processes.append((cmd, subprocess.Popen(cmd, shell=True))) mesh_stream = draco_output_pipe.open_stream('rb') return mesh_stream.read() finally: # Explicitly wait() for the child processes # (avoids a warning from subprocess.Popen.__del__) for cmd, proc in child_processes: proc.wait(timeout=1.0) if proc.returncode != 0: raise RuntimeError( f"Child process returned an error code: {proc.returncode}.\n" f"Command was: {cmd}")
from marching_cubes import march from numpy import load import os import time from pyqtgraph.opengl import GLViewWidget, MeshData from pyqtgraph.opengl.items.GLMeshItem import GLMeshItem from PyQt5.QtGui import QApplication volume = load(os.path.join(os.path.split(__file__)[0], 'data/input/sample.npy')) t0 = time.time() vertices, normals, faces = march(volume, 0) # zero smoothing rounds smooth_vertices, smooth_normals, faces = march(volume, 4) # 4 smoothing rounds t1 = time.time() print("took", t1 - t0, "sec") app = QApplication([]) view = GLViewWidget() mesh = MeshData(vertices / 100.0, faces) # scale down - otherwise camera is misplaced # or mesh = MeshData(smooth_vertices / 100, faces) mesh._vertexNormals = normals # or mesh._vertexNormals = smooth_normals item = GLMeshItem(meshdata=mesh, color=[1, 0, 0, 1], shader="normalColor") view.addItem(item)