def test_both_algs_same_result_donut(): # Performing this test on data that does not have ambiguities n = 48 a, b = 2.5/n, -1.25 vol = np.empty((n, n, n), 'float32') for iz in range(vol.shape[0]): for iy in range(vol.shape[1]): for ix in range(vol.shape[2]): # Double-torii formula by Thomas Lewiner z, y, x = float(iz)*a+b, float(iy)*a+b, float(ix)*a+b vol[iz,iy,ix] = ( ( (8*x)**2 + (8*y-2)**2 + (8*z)**2 + 16 - 1.85*1.85 ) * ( (8*x)**2 + (8*y-2)**2 + (8*z)**2 + 16 - 1.85*1.85 ) - 64 * ( (8*x)**2 + (8*y-2)**2 ) ) * ( ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 ) * ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 ) - 64 * ( ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 ) ) + 1025 vertices1, faces1 = marching_cubes_classic(vol, 0)[:2] vertices2, faces2 = marching_cubes_lewiner(vol, 0)[:2] vertices3, faces3 = marching_cubes_lewiner(vol, 0, use_classic=True)[:2] # Old and new alg are different assert not _same_mesh(vertices1, faces1, vertices2, faces2) # New classic and new Lewiner are different assert not _same_mesh(vertices2, faces2, vertices3, faces3)
def main(select=3, **kwargs): """Script main function. select: int 1: Medical data 2: Blocky data, different every time 3: Two donuts 4: Ellipsoid """ import visvis as vv # noqa: delay import visvis and GUI libraries # Create test volume if select == 1: vol = vv.volread('stent') isovalue = kwargs.pop('level', 800) elif select == 2: vol = vv.aVolume(20, 128) isovalue = kwargs.pop('level', 0.2) elif select == 3: with timer('computing donuts'): vol = donuts() isovalue = kwargs.pop('level', 0.0) # Uncommenting the line below will yield different results for # classic MC # vol *= -1 elif select == 4: vol = ellipsoid(4, 3, 2, levelset=True) isovalue = kwargs.pop('level', 0.0) else: raise ValueError('invalid selection') # Get surface meshes with timer('finding surface lewiner'): vertices1, faces1 = marching_cubes_lewiner(vol, isovalue, **kwargs)[:2] with timer('finding surface classic'): vertices2, faces2 = marching_cubes_classic(vol, isovalue, **kwargs) # Show vv.figure(1) vv.clf() a1 = vv.subplot(121) vv.title('Lewiner') m1 = vv.mesh(np.fliplr(vertices1), faces1) a2 = vv.subplot(122) vv.title('Classic') m2 = vv.mesh(np.fliplr(vertices2), faces2) a1.camera = a2.camera # visvis uses right-hand rule, gradient_direction param uses left-hand rule m1.cullFaces = m2.cullFaces = 'front' # None, front or back vv.use().Run()
def test_both_algs_same_result_ellipse(): # Performing this test on data that does not have ambiguities sphere_small = ellipsoid(1, 1, 1, levelset=True) vertices1, faces1 = marching_cubes_classic(sphere_small, 0)[:2] vertices2, faces2 = marching_cubes_lewiner(sphere_small, 0, allow_degenerate=False)[:2] vertices3, faces3 = marching_cubes_lewiner(sphere_small, 0, allow_degenerate=False, use_classic=True)[:2] # Order is different, best we can do is test equal shape and same vertices present assert _same_mesh(vertices1, faces1, vertices2, faces2) assert _same_mesh(vertices1, faces1, vertices3, faces3)
def test_marching_cubes_isotropic(): ellipsoid_isotropic = ellipsoid(6, 10, 16, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) # Classic verts, faces = marching_cubes_classic(ellipsoid_isotropic, 0.) surf_calc = mesh_surface_area(verts, faces) # Test within 1% tolerance for isotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.99 # Lewiner verts, faces = marching_cubes_lewiner(ellipsoid_isotropic, 0.)[:2] surf_calc = mesh_surface_area(verts, faces) # Test within 1% tolerance for isotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.99
def visualize_voxel_spectral(points, vis_size=128): """Function to visualize voxel (spectral).""" points = np.rint(points) points = np.swapaxes(points, 0, 2) fig = p.figure(figsize=(1, 1), dpi=vis_size) verts, faces = measure.marching_cubes_classic(points, 0, spacing=(0.1, 0.1, 0.1)) ax = fig.add_subplot(111, projection='3d') ax.plot_trisurf( verts[:, 0], verts[:, 1], faces, verts[:, 2], cmap='Spectral_r', lw=0.1) ax.set_axis_off() fig.tight_layout(pad=0) fig.canvas.draw() data = np.fromstring( fig.canvas.tostring_rgb(), dtype=np.uint8, sep='').reshape( vis_size, vis_size, 3) p.close('all') return data
def test_marching_cubes_anisotropic(): spacing = (1., 10 / 6., 16 / 6.) ellipsoid_anisotropic = ellipsoid(6, 10, 16, spacing=spacing, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) # Classic verts, faces = marching_cubes_classic(ellipsoid_anisotropic, 0., spacing=spacing) surf_calc = mesh_surface_area(verts, faces) # Test within 1.5% tolerance for anisotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.985 # Lewiner verts, faces = marching_cubes_lewiner(ellipsoid_anisotropic, 0., spacing=spacing)[:2] surf_calc = mesh_surface_area(verts, faces) # Test within 1.5% tolerance for anisotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.985
def test_invalid_input(): # Classic with testing.raises(ValueError): marching_cubes_classic(np.zeros((2, 2, 1)), 0) with testing.raises(ValueError): marching_cubes_classic(np.zeros((2, 2, 1)), 1) with testing.raises(ValueError): marching_cubes_classic(np.ones((3, 3, 3)), 1, spacing=(1, 2)) with testing.raises(ValueError): marching_cubes_classic(np.zeros((20, 20)), 0) # Lewiner with testing.raises(ValueError): marching_cubes_lewiner(np.zeros((2, 2, 1)), 0) with testing.raises(ValueError): marching_cubes_lewiner(np.zeros((2, 2, 1)), 1) with testing.raises(ValueError): marching_cubes_lewiner(np.ones((3, 3, 3)), 1, spacing=(1, 2)) with testing.raises(ValueError): marching_cubes_lewiner(np.zeros((20, 20)), 0)
def plot_3d_lung(lung_array, title=''): print(title, lung_array.shape) start = time.time() imgs = lung_array.transpose(2, 1, 0) # z,y,x -> x,y,z verts, faces = measure.marching_cubes_classic(imgs, 130) fig = plt.figure(figsize=(20, 20)) ax = fig.add_subplot(111, projection='3d') mesh = Poly3DCollection(verts[faces], alpha=0.3) mesh.set_facecolor([1, 1, 1]) ax.add_collection3d(mesh) ax.set_xlim(0, lung_array.shape[0]) ax.set_ylim(0, lung_array.shape[1]) ax.set_zlim(0, lung_array.shape[2]) #ax.view_init(10,270) #旋转角度 plt.rcParams['axes.facecolor'] = 'black' #背景颜色 plt.axis('off') plt.show() print('time cost:', time.time() - start)
def plot_3d(image, threshold=-300, id="1"): # Position the scan upright, # so the head of the patient would be at the top facing the camera p = image.transpose(2, 1, 0) #p = p[:,::-1,:] verts, faces = measure.marching_cubes_classic(p, threshold) fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces], alpha=0.70) face_color = [0.45, 0.45, 0.75] mesh.set_facecolor(face_color) ax.add_collection3d(mesh) ax.set_xlim(0, p.shape[0]) ax.set_ylim(0, p.shape[1]) ax.set_zlim(0, p.shape[2]) fig = plt.gcf() plt.show() fig.savefig('./output/%s.png' % (id), dpi=100)
def f(X, c, q): vert_list = [] for j in range(N): print 'step {%d}' % j X = f_(X, c, q) R = np.sqrt(np.square(X[:,:,:,0]) + \ np.square(X[:,:,:,1]) + \ np.square(X[:,:,:,2])) B = 1.0 * (R < 2.0) verts, faces = measure.marching_cubes_classic(B, 0) for k in range(3): verts[:, k] = (bounds[k][1] - bounds[k][0]) * ( 1.0 * verts[:, k]) / K + bounds[k][0] faces = measure.correct_mesh_orientation(B, verts, faces) vert_list.append(verts) return vert_list
def test_marching_cubes_anisotropic(): # test spacing as numpy array (and not just tuple) spacing = np.array([1., 10 / 6., 16 / 6.]) ellipsoid_anisotropic = ellipsoid(6, 10, 16, spacing=spacing, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) # Classic verts, faces = marching_cubes_classic(ellipsoid_anisotropic, 0., spacing=spacing) surf_calc = mesh_surface_area(verts, faces) # Test within 1.5% tolerance for anisotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.985 # Lewiner verts, faces = marching_cubes_lewiner( ellipsoid_anisotropic, 0., spacing=spacing)[:2] surf_calc = mesh_surface_area(verts, faces) # Test within 1.5% tolerance for anisotropic. Will always underestimate. assert surf > surf_calc and surf_calc > surf * 0.985 # Test spacing together with allow_degenerate=False marching_cubes_lewiner(ellipsoid_anisotropic, 0, spacing=spacing, allow_degenerate=False)
def test_both_algs_same_result_donut(): # Performing this test on data that does not have ambiguities n = 48 a, b = 2.5 / n, -1.25 isovalue = 0.0 vol = np.empty((n, n, n), 'float32') for iz in range(vol.shape[0]): for iy in range(vol.shape[1]): for ix in range(vol.shape[2]): # Double-torii formula by Thomas Lewiner z, y, x = float(iz) * a + b, float(iy) * a + b, float( ix) * a + b vol[iz, iy, ix] = (((8 * x)**2 + (8 * y - 2)**2 + (8 * z)**2 + 16 - 1.85 * 1.85) * ((8 * x)**2 + (8 * y - 2)**2 + (8 * z)**2 + 16 - 1.85 * 1.85) - 64 * ((8 * x)**2 + (8 * y - 2)**2)) * ( ((8 * x)**2 + ((8 * y - 2) + 4) * ((8 * y - 2) + 4) + (8 * z)**2 + 16 - 1.85 * 1.85) * ((8 * x)**2 + ((8 * y - 2) + 4) * ((8 * y - 2) + 4) + (8 * z)**2 + 16 - 1.85 * 1.85) - 64 * (((8 * y - 2) + 4) * ((8 * y - 2) + 4) + (8 * z)**2)) + 1025 vertices1, faces1 = marching_cubes_classic(vol, 0)[:2] vertices2, faces2 = marching_cubes_lewiner(vol, 0)[:2] vertices3, faces3 = marching_cubes_lewiner(vol, 0, use_classic=True)[:2] # Old and new alg are different assert not _same_mesh(vertices1, faces1, vertices2, faces2) # New classic and new Lewiner are different assert not _same_mesh(vertices2, faces2, vertices3, faces3)
def build_surface(grain): verts, faces = measure.marching_cubes_classic(grain, 0, spacing=(1, 1, 1)) return verts, faces
def getVFByMarchingCubes(voxels, threshold=0.5): """Voxel 로 부터 Vertices, faces 리턴 하는 함수""" v, f = sk.marching_cubes_classic(voxels, level=threshold) return v, f
def getVFByMarchingCubes(voxels, threshold=0.5): # v, f = sk.marching_cubes(voxels, level=threshold) # v, f,_,_ = sk.marching_cubes_lewiner(voxels,threshold) v, f = sk.marching_cubes_classic(voxels, threshold) return v, f
def measure(self, p, threshold, q1, q2): verts, faces = measure.marching_cubes_classic(p, threshold) q1.put(verts) q2.put(faces)
) * ( ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 ) * ( (8*x)**2 + ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 + 16 - 1.85*1.85 ) - 64 * ( ((8*y-2)+4)*((8*y-2)+4) + (8*z)**2 ) ) + 1025 # Uncommenting the line below will yield different results for classic MC #vol = -vol elif SELECT == 4: vol = ellipsoid(4, 3, 2, levelset=True) isovalue = 0 # Get surface meshes t0 = time.time() vertices1, faces1, _ = marching_cubes_lewiner(vol, isovalue, gradient_direction=gradient_dir, use_classic=False) print('finding surface lewiner took %1.0f ms' % (1000*(time.time()-t0)) ) t0 = time.time() vertices2, faces2, _ = marching_cubes_classic(vol, isovalue, gradient_direction=gradient_dir) print('finding surface classic took %1.0f ms' % (1000*(time.time()-t0)) ) # Show vv.figure(1); vv.clf() a1 = vv.subplot(121); m1 = vv.mesh(np.fliplr(vertices1), faces1) a2 = vv.subplot(122); m2 = vv.mesh(np.fliplr(vertices2), faces2) a1.camera = a2.camera # visvis uses right-hand rule, gradient_direction param uses left-hand rule m1.cullFaces = m2.cullFaces = 'front' # None, front or back vv.use().Run()
def mandelbulb(K=200, p=8.0, N=10, extreme=1.5, optimize=False): M = T.ftensor4() C = T.ftensor4() n = T.fscalar() def step(X): r = T.sqrt( T.square(X[:, :, :, 0]) + T.square(X[:, :, :, 1]) + T.square(X[:, :, :, 2])) phi = T.arctan2(X[:, :, :, 1], X[:, :, :, 0]) theta = T.arctan2( T.sqrt(T.square(X[:, :, :, 0]) + T.square(X[:, :, :, 1])), X[:, :, :, 2]) X_ = T.stack((T.pow(r, n) * T.sin(n * theta) * T.cos(n * phi), T.pow(r, n) * T.sin(n * theta) * T.sin(n * theta), T.pow(r, n) * T.cos(n * theta)), axis=-1) return X_ + C if optimize: result, _ = theano.scan(fn=step, outputs_info=M, n_steps=N) f = theano.function([M, C, n], result, allow_input_downcast=True) else: f_ = theano.function([M, C, n], step(M), allow_input_downcast=True) def f(X, c, q): for j in range(N): print 'step {%d}' % j X = f_(X, c, q) return np.array(X) x, y, z = np.meshgrid(np.linspace(-extreme, extreme, K), np.linspace(-extreme, extreme, K), np.linspace(-extreme, extreme, K)) X = np.stack((x, y, z), axis=-1) if optimize: x_n = f(np.zeros((K, K, K, 3)), X, p)[-1] else: x_n = f(np.zeros((K, K, K, 3)), X, p) r_n = np.sqrt(np.square(x_n[:,:,:,0]) + \ np.square(x_n[:,:,:,1]) + \ np.square(x_n[:,:,:,2])) b_ = 1.0 * (r_n < 2.0) import open3d from scipy.misc import imresize from skimage import measure verts, faces = measure.marching_cubes_classic(b_, 0) faces = measure.correct_mesh_orientation(b_, verts, faces) verts = 2.0 * extreme * (np.array(verts, dtype=np.float32) / K) - extreme pcd = open3d.PointCloud() pcd.points = open3d.Vector3dVector(verts) open3d.estimate_normals(pcd, search_param=open3d.KDTreeSearchParamHybrid( radius=0.1, max_nn=30)) global i, images i = 0 images = [] def custom_draw_geometry_with_rotation(pcd): def rotate_view(vis): ctr = vis.get_view_control() ctr.rotate(10.0, 0.0) global i, images i += 1 print i % 210, i // 210 image = np.asarray(vis.capture_screen_float_buffer()) image = np.array(255 * image, dtype=np.uint8) image = imresize(image, 0.25) if (i // 210 == 0): images.append(image) return False open3d.draw_geometries_with_animation_callback([pcd], rotate_view) custom_draw_geometry_with_rotation(pcd) gif_name = 'Mandelbulb_%d_%d.gif' % (int(p), int(N)) output_file = os.path.join(__file__.split('.')[0], gif_name) imageio.mimsave(output_file, images, duration=0.05)
# plotting in plotly if set true if to_plotly: verts, simplices = measure.marching_cubes_classic(vspace, np.amax(vspace)*q_threshold) x,y,z = zip(*verts) #colormap=['rgb(255,105,180)','rgb(255,255,51)','rgb(0,191,255)'] fig = plotly.figure_factory.create_trisurf(x=x, y=y, z=z, plot_edges=False, #colormap=colormap, simplices=simplices, title="Vortex field") py.iplot(fig) # plotting in matplotlib if set true if to_matplot: stop1 = time.clock() verts, faces = measure.marching_cubes_classic(vspace, np.amax(vspace)*q_threshold) stop2 = time.clock() print ('\n',int((stop2-stop1)*10000)/10000.,'sec marching cubes') fig = plt.figure()
def plot_3d(image=None, body=None, roi=None, gt=None, pred=None, threshold_i=1500, threshold_b=0, threshold_r=0): # Position the scan upright, # so the head of the patient would be at the top facing the camera fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') g, y = [], [] if image is not None: g = np.zeros(image.shape, dtype=np.uint8) y = np.zeros(image.shape, dtype=np.uint8) p = image p = p[:, :, ::-1] verts_p, faces_p = measure.marching_cubes_classic(p, threshold_i) # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh_p = Poly3DCollection(verts_p[faces_p], alpha=0.1) mesh_p.set_facecolor([0.0, 0.0, 0.0]) ax.add_collection3d(mesh_p) ax.set_xlim(0, p.shape[0]) ax.set_ylim(0, p.shape[1]) ax.set_zlim(0, p.shape[2]) if body is not None: g = np.zeros(body.shape, dtype=np.uint8) y = np.zeros(body.shape, dtype=np.uint8) b = body b = b[:, :, ::-1] verts_b, faces_b = measure.marching_cubes_classic(b, threshold_b) # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh_b = Poly3DCollection(verts_b[faces_b], alpha=0.1) mesh_b.set_facecolor([0.5, 0.5, 1]) ax.add_collection3d(mesh_b) ax.set_xlim(0, b.shape[0]) ax.set_ylim(0, b.shape[1]) ax.set_zlim(0, b.shape[2]) if roi is not None: g = np.zeros(roi.shape, dtype=np.uint8) y = np.zeros(roi.shape, dtype=np.uint8) r = roi r = r[:, :, ::-1] verts_r, faces_r = measure.marching_cubes_classic(r, threshold_r) # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh_r = Poly3DCollection(verts_r[faces_r], alpha=0.1) mesh_r.set_facecolor([0.5, 0.5, 0]) ax.add_collection3d(mesh_r) ax.set_xlim(0, r.shape[0]) ax.set_ylim(0, r.shape[1]) ax.set_zlim(0, r.shape[2]) if gt is not None: gt = np.round(gt).astype(np.int16) gt[2] = g.shape[2] - gt[2] g[gt[0], gt[1], gt[2]] = 1 verts_g, faces_g = measure.marching_cubes_classic(g, 0) # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh_g = Poly3DCollection(verts_g[faces_g], alpha=0.1) mesh_g.set_facecolor([0, 1, 0]) ax.add_collection3d(mesh_g) ax.set_xlim(0, g.shape[0]) ax.set_ylim(0, g.shape[1]) ax.set_zlim(0, g.shape[2]) if pred is not None: pred = np.round(pred).astype(np.int16) pred[2] = y.shape[2] - pred[2] y[pred[0], pred[1], pred[2]] = 1 verts_y, faces_y = measure.marching_cubes_classic(y, 0) # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh_y = Poly3DCollection(verts_y[faces_y], alpha=0.1) mesh_y.set_facecolor([1, 0, 0]) ax.add_collection3d(mesh_y) ax.set_xlim(0, y.shape[0]) ax.set_ylim(0, y.shape[1]) ax.set_zlim(0, y.shape[2]) plt.show()
def get_surface(mask, spacing): vertices, faces = marching_cubes_classic(mask, level=0, spacing=spacing) faces = correct_mesh_orientation(mask, vertices, faces, spacing) return vertices, faces
def plot(self): """ Plot the contours. """ import bpy import numpy as np from skimage import measure from blendaviz import colors # Check if there is any time array. if not self.time is None: if not isinstance(self.time, np.ndarray): print("Error: time is not a valid array.") return -1 elif self.time.ndim != 1: print("Error: time array must be 1d.") return -1 # Determine the time index. self.time_index = np.argmin( abs(bpy.context.scene.frame_float - self.time)) else: self.time = np.array([0]) self.time_index = 0 # Check the validity of the input arrays. if not isinstance(self.x, np.ndarray) or not isinstance(self.y, np.ndarray) \ or not isinstance(self.z, np.ndarray): print("Error: x OR y OR z array invalid.") return -1 if not ((self.x.shape[0], self.y.shape[0], self.z.shape[0]) == self.phi.shape[:3]): print("Error: input array shapes invalid.") return -1 if not self.psi is None: if not isinstance(self.psi, np.ndarray): print("Error: psi is not a numpy array.") return -1 if not self.psi.shape[:3] == self.phi.shape[:3]: print("Error: psi and phi must of of the same shape.") # Point the local variables to the correct arrays. if self.x.ndim == 2: self._x = self.x[:, self.time_index] else: self._x = self.x if self.y.ndim == 2: self._y = self.y[:, self.time_index] else: self._y = self.y if self.z.ndim == 2: self._z = self.z[:, self.time_index] else: self._z = self.z if self.phi.ndim == 4: self._phi = self.phi[:, :, :, self.time_index] else: self._phi = self.phi if not self.psi is None: if self.psi.ndim == 4: self._psi = self.psi[:, :, :, self.time_index] else: self._psi = self.psi else: self._psi = None # Prepare the isosurface levels. if isinstance(self.contours, int): level_list = np.linspace(self._phi.min(), self._phi.max(), self.contours + 2)[1:-1] elif isinstance(self.contours, list): level_list = np.array(self.contours) elif isinstance(self.contours, np.ndarray): level_list = self.contours.ravel() else: print("Error: countours invalid. \ Must be either integer or 1d array/list.") return -1 # Prepare the material colors. color_rgba = colors.make_rgba_array(self.color, level_list.shape[0], self.color_map, self.vmin, self.vmax) # Determine the grid spacing. dx = np.partition(np.array(list(set(list(self._x.ravel())))), 1)[1] - \ self._x.min() dy = np.partition(np.array(list(set(list(self._y.ravel())))), 1)[1] - \ self._y.min() dz = np.partition(np.array(list(set(list(self._z.ravel())))), 1)[1] - \ self._z.min() # Delete existing meshes. if not self.mesh_object is None: bpy.ops.object.select_all(action='DESELECT') for mesh_object in self.mesh_object: mesh_object.select_set(state=True) bpy.ops.object.delete() self.mesh_object = None # Delete existing materials. if not self.mesh_material is None: for mesh_material in self.mesh_material: bpy.data.materials.remove(mesh_material) # Prepare the lists of mashes and materials. self.mesh_data = [] self.mesh_object = [] self.mesh_material = [] for idx, level in enumerate(level_list): # Find the vertices and faces of the isosurfaces. vertices, faces = measure.marching_cubes_classic(self._phi, level, spacing=(dx, dy, dz)) vertices[:, 0] += self._x.min() vertices[:, 1] += self._y.min() vertices[:, 2] += self._z.min() # Create mesh and object. self.mesh_data.append(bpy.data.meshes.new("DataMesh")) self.mesh_object.append( bpy.data.objects.new("ObjMesh", self.mesh_data[-1])) # Create mesh from the given data. self.mesh_data[-1].from_pydata(list(vertices), [], list(faces)) self.mesh_data[-1].update(calc_edges=True) # Set the material/color. if self._psi is None: self.__set_material(idx, color_rgba, len(level_list)) else: self.__color_vertices(idx, vertices) self.mesh_data[-1].materials.append(self.mesh_material[-1]) # Link the mesh object with the scene. bpy.context.scene.collection.objects.link(self.mesh_object[-1]) # Group the meshes together. for mesh in self.mesh_object[::-1]: mesh.select_set(state=True) bpy.context.view_layer.objects.active = mesh bpy.ops.object.join() self.mesh_object = bpy.context.object self.mesh_object.select_set(state=False) # Make the grouped meshes the deletable object. self.deletable_object = self.mesh_object return 0
# Uncommenting the line below will yield different results for classic MC #vol = -vol elif SELECT == 4: vol = ellipsoid(4, 3, 2, levelset=True) isovalue = 0 # Get surface meshes t0 = time.time() vertices1, faces1, _, _ = marching_cubes_lewiner( vol, isovalue, gradient_direction=gradient_dir, use_classic=False) print('finding surface lewiner took %1.0f ms' % (1000 * (time.time() - t0))) t0 = time.time() vertices2, faces2 = marching_cubes_classic(vol, isovalue, gradient_direction=gradient_dir) print('finding surface classic took %1.0f ms' % (1000 * (time.time() - t0))) # Show vv.figure(1) vv.clf() a1 = vv.subplot(121) m1 = vv.mesh(np.fliplr(vertices1), faces1) a2 = vv.subplot(122) m2 = vv.mesh(np.fliplr(vertices2), faces2) a1.camera = a2.camera # visvis uses right-hand rule, gradient_direction param uses left-hand rule m1.cullFaces = m2.cullFaces = 'front' # None, front or back
from matplotlib import pyplot as plt import numpy as np from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure n = 10 x = np.linspace(0, n, n + 1) X, Y, Z = np.meshgrid(x, x, x, indexing='ij') def f(x, y, z): return (x**2 + y**2 + z**2)**0.5 - 3 verts, faces = measure.marching_cubes_classic(f(X, Y, Z), 5) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) m = 00 ax.set_xlim(-m, n + 5) ax.set_ylim(-m, n + 5) ax.set_zlim(-m, n + 5) plt.show()
def draw_3d_labels( in_bone_labels, # type: np.ndarray start_idx=1, # type: int rescale_func=None, vox_size=None, verbose=False, level=0, figsize=(10, 12), force_shape=True, flip=True): # type: (...) -> Tuple[Axes3D, matplotlib.figure.Figure] # somehow add type to rescale_fun Optional[Function(np.ndarray, np.ndarray)] """ :param in_bone_labels: :param start_idx: :param rescale_func: a function to downscale the images (if needed) :return: >>> test_labels = np.stack([np.eye(3),2*np.eye(3)]).astype(int); tvx = np.array([0.1, 3.0, 0.33]) >>> ax, fig = draw_3d_labels(test_labels, verbose = True) Adding meshes 1, sized 3.0 Adding meshes 2, sized 3.0 >>> type(ax) <class 'matplotlib.axes._subplots.Axes3DSubplot'> >>> type(fig) <class 'matplotlib.figure.Figure'> """ # todo I don't think the Function typing is correct # plt.rcParams['savefig.bbox'] = 'tight' fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles cmap = plt.cm.get_cmap('nipy_spectral_r') max_comp = in_bone_labels.max() rescale_func = rescale_func if rescale_func is not None else lambda x: x if flip: ax_flip = lambda x: rescale_func(x)[::-1].swapaxes(0, 2).swapaxes(0, 1) else: ax_flip = lambda x: rescale_func(x) for i in range(start_idx, min(max_comp, MAX_COMP_LIMIT) + 1): if i == 0: v_img = ax_flip((in_bone_labels > 0).astype(np.float32)) else: v_img = ax_flip((in_bone_labels == i).astype(np.float32)) if verbose: print('Adding meshes {}, sized {}'.format(i, np.sum(v_img))) mc_args = {'level': level} if vox_size is not None: mc_args['spacing'] = vox_size verts, faces = marching_cubes_classic(v_img, **mc_args) mesh = Poly3DCollection(verts[faces]) if i > 0: mesh.set_facecolor(cmap(i / max_comp)[:3]) mesh.set_alpha(0.75) else: mesh.set_facecolor([1, 1, 1]) mesh.set_edgecolor([0, 0, 0]) mesh.set_alpha(0.1) # mesh.set_edgecolor(cmap(i/max_comp)[:3]) ax.add_collection3d(mesh) n_shape = ax_flip(in_bone_labels).shape if force_shape: ax.set_xlim(0, n_shape[0]) ax.set_ylim(0, n_shape[1]) ax.set_zlim(0, n_shape[2]) else: pass # ax.set_aspect('equal') ax.view_init(45, 45) ax.axis('off') return ax, fig
def getVFByMarchingCubes(voxels, threshold=0.5): v, f = sk.marching_cubes_classic(voxels, level=threshold) return v, f
r2 = np.exp(-Z * r / n / amu) r3 = (2 * Z * r / n / amu)**l r4 = np.polyval(LaguerreGen(n - l - 1, 2 * l + 1), 2 * Z * r / n / amu) R = r1 * r2 * r3 * r4 Y = compute_Ylm(l, m, theta, phi) psi = R * Y out = np.sqrt(psi * np.conj(psi)) res = np.meshgrid(np.arange(-rx, rx + 1, 1), np.arange(-ry, ry + 1, 1), np.arange(-rz, rz + 1, 1)) x1 = res(0) * rlims / rn y1 = res(1) * rlims / rn z1 = res(2) * rlims / rn vertices, simplices = measure.marching_cubes_classic(out, V) #x,y,z = zip(*vertices) colormap = ['rgb(255,105,180)', 'rgb(255,255,51)', 'rgb(0,191,255)'] fig = plotly.figure_factory.create_trisurf(x=x1, y=y1, z=z1, plot_edges=False, colormap=colormap, simplices=simplices, title="Isosurface") py.iplot(fig)
myoseg_2d_mask, mask_epi_3d, mask_endo_3d, scar3d = registration( 'pkl_data/cine_lv_1143____.pkl', 'pkl_data/LGE_scar_1143____new.pkl') end_time = time.time() print('registration : ', end_time - start_time) text_pos = get_text_position(myoseg_2d_mask) start_time = time.time() # uniform_filter() is equivalent to smooth3() in matlab. mask_diastole = scipy.ndimage.uniform_filter(mask_epi_3d, [4, 4, 20], mode='nearest') # Using marching cubes algorithm to get a polygonal mesh of an isosurface verts, faces = measure.marching_cubes_classic(mask_diastole, level=0.5) end_time = time.time() print('marching_cubes : ', end_time - start_time) [avgX, avgY, avgZ] = map(np.mean, zip(*verts)) [avgX_text, avgY_text] = map(np.mean, zip(*text_pos)) text_pos = list( map(lambda p: (p[0] - avgX_text, p[1] - avgY_text), text_pos)) app = QtWidgets.QApplication(sys.argv) # vis3D_method = 'glmeshitem' # 'glvolumeitem' or 'glmeshitem' vis3D_method = 'glmeshitem' if vis3D_method == 'glvolumeitem':
treePoints = annotatedSegmentationVolume[tumorPointsNameInMat] # Configuration for cutter barDepth = 10 columnHeight = mouldSlabHeight + 25 print( "#######################################\n####### TISSUE CUTTER GENERATOR #######\n#######################################" ) print("### Input file: " + inputFilePath) print("##### Matrix name: " + tumorVolumeNameInMat) print("### Output file prefix: " + outputFilePath + "*") print("# Performing marching cubes algorithm on tumor volume...") verts, faces = measure.marching_cubes_classic(tree, ) tumorMesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): tumorMesh.vectors[i][j] = verts[f[j], :] print("# done.") print("# Save intermediate mesh...") tumorMesh.save(outputFilePath + "tumour_preproc.stl") print("# done.") print("# Process and re-save intermediate mesh...") in_file = outputFilePath + "tumour_preproc.stl" out_file = outputFilePath + "tumour_postproc.stl" filter_script_path = 'filter.mlx' # Add input mesh command = "/Applications/meshlab.app/Contents/MacOS/meshlabserver -i '" + os.getcwd(
def plot_cartesian_isosurface(function_grids, levels, contours=[], cont_kwargs=[{}], tri_kwargs=[{'cmap': 'Spectral', 'lw': 1}], fig_kwargs={'figsize': [12., 15.]}, ax_kwargs={}, font_kwargs={'name': 'serif', 'size': 30}, show_plot=True, fname=None, fig_num=None): # Repeat axis and line formats if only one value is given if len(tri_kwargs) == 1: tri_kwargs = tri_kwargs * len(function_grids) if len(cont_kwargs) == 1: cont_kwargs = cont_kwargs * len(function_grids) if len(levels) == 1: levels = levels * len(function_grids) # Checks that all inputs are now the same length assert len(function_grids) == len(tri_kwargs) == len(cont_kwargs) == len(levels) # Format Figure and Axes fig = plt.figure(fig_num, **fig_kwargs) ax = fig.add_axes([0.025, 0.15, 0.8, 0.85], projection='3d') # Format Axes format_3d_axes(ax, font_kwargs=font_kwargs, **ax_kwargs) for fg, level, tri_kwarg, cont_kwarg in zip(function_grids, levels, tri_kwargs, cont_kwargs): func = fg.data x, y, z = fg.grid.coordinates # Calculate Projected Functions (Normalized to the same max as original Function) yz_func = np.sum(func, axis=0) yz_func *= np.max(func)/np.max(yz_func) xz_func = np.sum(func, axis=1) xz_func *= np.max(func)/np.max(xz_func) xy_func = np.sum(func, axis=2) xy_func *= np.max(func)/np.max(xy_func) # Calculate and Plot Isosurface # Factor of 2 for consistency with bloch sphere convention del_x, del_y, del_z = 2 * (x[1] - x[0]), 2 * (y[1] - y[0]), 2 * (z[1] - z[0]) x_min, y_min, z_min = 2 * np.min(x), 2 * np.min(y), 2 * np.min(z) x_max, y_max, z_max = 2 * np.max(x), 2 * np.max(y), 2 * np.max(z) verts, faces = measure.marching_cubes_classic(volume=func, level=level) verts[:, 0] = verts[:, 0] * del_x + x_min verts[:, 1] = verts[:, 1] * del_y + y_min verts[:, 2] = verts[:, 2] * del_z + z_min tri = ax.plot_trisurf(verts[:, 0], verts[:, 1], faces, verts[:, 2], zorder=100., **tri_kwarg) for contour in contours: lvl = contour * level if np.min(yz_func) < lvl < np.max(yz_func): cont = np.array(measure.find_contours(yz_func, lvl)) cont = cont[0] cont[:, 0] = cont[:, 0] * del_y + y_min cont[:, 1] = cont[:, 1] * del_z + z_min tri = ax.plot(xs=x_min * np.ones_like(cont[:, 0]), ys=cont[:, 0], zs=cont[:, 1], zorder=-1., **cont_kwarg) if np.min(xz_func) < lvl < np.max(xz_func): cont = np.array(measure.find_contours(xz_func, lvl)) cont = cont[0] cont[:, 0] = cont[:, 0] * del_x + x_min cont[:, 1] = cont[:, 1] * del_z + z_min tri = ax.plot(xs=cont[:, 0], ys=y_max * np.ones_like(cont[:, 0]), zs=cont[:, 1], zorder=-1., **cont_kwarg) if np.min(xy_func) < lvl < np.max(xy_func): cont = np.array(measure.find_contours(xy_func, lvl)) cont = cont[0] cont[:, 0] = cont[:, 0] * del_x + x_min cont[:, 1] = cont[:, 1] * del_y + y_min tri = ax.plot(xs=cont[:, 0], ys=cont[:, 1], zs=z_min * np.ones_like(cont[:, 0]), zorder=-1., **cont_kwarg) # Draw and Save Figure if show_plot: plt.show() if fname is not None: fig.savefig(fname) return fig, tri
def plot_contours(clf, xx, yy, zz, ww, X_Circle, X_Triangle, X_MIN, X_MAX, Y_MIN, Y_MAX, Z_MIN, Z_MAX, type=2, eps=0.1, **params): """Plot the decision boundaries for a classifier. Parameters ---------- ax: matplotlib axes object """ plt.close('all') Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel(), zz.ravel(), ww.ravel()]) Z = Z.reshape(xx.shape) # Create a figure with axes for 3D plotting fig = plt.figure() ax = fig.gca(projection='3d') # Plot the different input points using 3D scatter plotting if type == 0: Z = Z[:, 0, :, :] b1 = ax.scatter(X_Circle[:, 1], X_Circle[:, 2], X_Circle[:, 3], c='red') b2 = ax.scatter(X_Triangle[:, 1], X_Triangle[:, 2], X_Triangle[:, 3], c='green') ax.set_xlabel("Y") ax.set_ylabel("Z") ax.set_zlabel("W") elif type == 1: Z = Z[:, :, 0, :] b1 = ax.scatter(X_Circle[:, 0], X_Circle[:, 2], X_Circle[:, 3], c='red') b2 = ax.scatter(X_Triangle[:, 0], X_Triangle[:, 2], X_Triangle[:, 3], c='green') ax.set_xlabel("X") ax.set_ylabel("Z") ax.set_zlabel("W") elif type == 2: Z = Z[:, :, :, 0] b1 = ax.scatter(X_Circle[:, 0], X_Circle[:, 1], X_Circle[:, 3], c='red') b2 = ax.scatter(X_Triangle[:, 0], X_Triangle[:, 1], X_Triangle[:, 3], c='green') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("W") elif type == 3: Z = Z[:, :, :, 0] b1 = ax.scatter(X_Circle[:, 0], X_Circle[:, 1], X_Circle[:, 2], c='red') b2 = ax.scatter(X_Triangle[:, 0], X_Triangle[:, 1], X_Triangle[:, 2], c='green') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") # Plot the separating hyperplane by recreating the isosurface for the distance # == 0 level in the distance grid computed through the decision function of the # SVM. This is done using the marching cubes algorithm implementation from # scikit-image. try: verts, faces = measure.marching_cubes_classic(Z) # Scale and transform to actual size of the interesting volume verts = verts * \ [X_MAX - X_MIN, Y_MAX - Y_MIN, Z_MAX - Z_MIN] / SPACE_SAMPLING_POINTS verts = verts + [X_MIN + 1, Y_MIN + 1, Z_MIN + 1] # and create a mesh to display alpha = 0.5 fc = "orange" mesh = Poly3DCollection(verts[faces], alpha=alpha, linewidths=1) mesh.set_edgecolor('w') mesh.set_facecolor((0, 1, 0, alpha)) ax.add_collection3d(mesh) # Some presentation tweaks #ax.set_xlim((-5, 5)) #ax.set_ylim((-5, 5)) #ax.set_zlim((-5, 5)) filename = "image_eps_poly_n_" + str(eps) + str(type) + ".png" name_Image = os.path.join(FILEROOT, filename) ax.legend([mpatches.Patch(color='orange', alpha=0.3), b1, b2], [ "Projected hyperplane", "class of circles", "class of triangles" ], loc="lower left", prop=mpl.font_manager.FontProperties(size=11)) plt.savefig(name_Image) except BaseException as e: print('Failed to do something: ' + str(e)) plt.clf()
) xTraj = currentPoint.kft[0,0,:] yTraj = currentPoint.kft[1,0,:] zTraj = currentPoint.kft[2,0,:] trajectoryData = go.Scatter3d( x = xTraj, y = yTraj, z = zTraj, mode='lines', line=dict( color='#ff0000', width=10 ) ) bands = band.e_3D_func(kxx, kyy, kzz) vertices, simplices = measure.marching_cubes_classic(bands, 0) x = (vertices[:,0]/(mesh_xy_graph-1)-0.5)*(5/2.)*pi/band.a y = (vertices[:,1]/(mesh_xy_graph-1)-0.5)*(5/2.)*pi/band.b z = (vertices[:,2]/(mesh_z_graph-1)-0.5)*4*pi/band.c def vzFunction(kx,ky,kz): return (band.v_3D_func(kx, ky, kz)[2]+10) colormap=['rgb(255,105,180)','rgb(255,255,51)','rgb(0,191,255)'] fermiSurface = ff.create_trisurf( x = x, y = y, z = z, simplices = simplices, plot_edges = False, color_func = vzFunction ) # could use 'type': 'scatter3d', graph3D = {