def draw_one(self, title, Lx, Ly, Lz, X, Y, Z, f, iso, elev=None, azim=None): """ Draw a single plot title: title of the plot X, Y, Z: 1D axes data f: 3D data set (C style index?!) """ self.clf() vert, face = measure.marching_cubes(f, iso) self.rescale(vert, X, Y, Z, f.shape) self.ax = self.add_subplot(111, projection='3d') cmap, col = self.getcolor(vert, face) surface = Poly3DCollection(vert[face]) surface.set_color(col) surface.set_edgecolor('') self.ax.add_collection3d(surface) self.ax.set_xlabel(Lx, fontsize=14) self.ax.set_ylabel(Ly, fontsize=14) self.ax.set_zlabel(Lz, fontsize=14) self.ax.set_xlim(X[0], X[-1]) self.ax.set_ylim(Y[0], Y[-1]) self.ax.set_zlim(Z[0], Z[-1]) self.ax.set_title(title) self.ax.view_init(elev, azim) self.colorbar(cmap, shrink=0.8, fraction=0.1, label=r'V $^2$') self.tight_layout() self.canvas.draw()
def plot_surface(voxels, voxel_size = 0.1): fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # First grid the data res = np.amax(voxels[1,:] - voxels[0,:]) ux = np.unique(voxels[:,0]) uy = np.unique(voxels[:,1]) uz = np.unique(voxels[:,2]) # Expand the model by one step in each direction ux = np.hstack((ux[0] - res, ux, ux[-1] + res)) uy = np.hstack((uy[0] - res, uy, uy[-1] + res)) uz = np.hstack((uz[0] - res, uz, uz[-1] + res)) # Convert to a grid X, Y, Z = np.meshgrid(ux, uy, uz) # Create an empty voxel grid, then fill in the elements in voxels V = np.zeros(X.shape) N = voxels.shape[0] for ii in xrange(N): ix = ux == voxels[ii,0] iy = uy == voxels[ii,1] iz = uz == voxels[ii,2] V[iy, ix, iz] = 1 marching_cubes = measure.marching_cubes(V, 0, spacing=(voxel_size, voxel_size, voxel_size)) verts = marching_cubes[0] faces = marching_cubes[1] ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2], lw=0, color='red') axis_equal(ax, verts[:, 0], verts[:,1], verts[:,2]) plt.show()
def tsdf2mesh(voxel_size, origin, tsdf_vol): verts, faces, norms, vals = measure.marching_cubes(tsdf_vol, level=0) verts = verts * voxel_size + origin # voxel grid coordinates to world coordinates mesh = trimesh.Trimesh(vertices=verts, faces=faces, vertex_normals=norms) return mesh
def load_nii_file(fname, threshold=0.5): """Uses the marching cube algorithm to turn a .nii binary mask into a surface weighted point cloud.""" mask = sitk.GetArrayFromImage(sitk.ReadImage(fname)) # mask = skimage.transform.downscale_local_mean(mask, (4,4,4)) verts, faces, normals, values = marching_cubes(mask, threshold) return to_measure(verts, faces)
def plot_3d_image(ax, image, threshold=0.5, *args, **kwargs): vertices, faces = measure.marching_cubes(image, level=threshold)[:2] mesh = Poly3DCollection(vertices[faces], **kwargs) ax.add_collection3d(mesh) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z") set_equal_3d_axis(ax, vertices)
def test_marching_cubes_isotropic(): ellipsoid_isotropic = ellipsoid(6, 10, 16, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) verts, faces = marching_cubes(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
def make_mesh(image, threshold=-300, step_size=1): print "Transposing surface" p = image.transpose(2,1,0) print "Calculating surface" verts, faces, norm, val = measure.marching_cubes(p, threshold, step_size=step_size, allow_degenerate=True) return verts, faces
def march_the_cubes(data, aff): from skimage.measure import marching_cubes import numpy as np from dipy.tracking.utils import move_streamlines verts, faces = marching_cubes(data, level=0.5) verts = np.asarray(list(move_streamlines(verts, aff))) #TODO: apply affine here return verts, faces
def mesh_and_extract_largest_connected_surface(volume, level_set): vertices, faces = marching_cubes(volume, level_set) mesh = Trimesh() mesh.vertices = vertices mesh.faces = faces meshes = mesh.split(only_watertight=False) sorted_meshes = sorted(meshes, key=lambda x: len(x.vertices)) return sorted_meshes[-1]
def march_cube(volume, level): """ help method for the march cube, using the skimage module """ verts, faces = measure.marching_cubes(volume, level, spacing=(1, 1, 1)) return verts, faces
def _extract_surface(pot_field, val, res, spacing): from skimage import measure vertices, simplices, normals, values = measure.marching_cubes(pot_field.reshape(res[0], res[1], res[2]), val # , #0.2424792, # -0.559606 # spacing=spacing, # (10.0, 10.0, 10.0) ) return vertices, simplices, normals, values
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(sphere_small, 0, method='_lorensen')[:2] vertices2, faces2 = marching_cubes(sphere_small, 0, allow_degenerate=False)[:2] vertices3, faces3 = marching_cubes(sphere_small, 0, allow_degenerate=False, method='lorensen')[: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 plot_3D_image(3D_image,threshold=-300): p = 3D_image.transpose(2,1,0) verts, faces,normals, values = measure.marching_cubes(p, threshold, spacing=(0.1, 0.1, 0.1)) fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2],cmap='Spectral', lw=1) plt.show()
def plot_3d_seg(image,name,threshold=1,save=False): # Position the scan upright, # so the head of the patient would be at the top facing the camera check = np.max(np.unique(image))>1 verts, faces = measure.marching_cubes(image,threshold-1) if check: verts2, faces2 = measure.marching_cubes(image,threshold) fig = plt.figure(figsize=(15, 15)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces], alpha=0.3) if check: mesh2 = Poly3DCollection(verts2[faces2], alpha=0.3) face_color = [1, 0.2, 0.2] if check: face_color2 = [0.3, 0.3, 1] mesh.set_facecolor(face_color) if check: mesh2.set_facecolor(face_color2) ax.add_collection3d(mesh) if check: ax.add_collection3d(mesh2) mesh_z = np.mean(image,axis=2) #mesh_y = np.mean(image,axis=1) #mesh_x = np.mean(image,axis=0) X=np.linspace(0,image.shape[0]-1,image.shape[0]) Y=np.linspace(0,image.shape[1]-1,image.shape[1]) Z=np.linspace(0,image.shape[2]-1,image.shape[2]) #a,b=np.meshgrid(Y,Z) c,d=np.meshgrid(X,Y) #e,f=np.meshgrid(X,Z) cest = ax.contourf(c,d, np.transpose(mesh_z), zdir='z', offset=0, cmap="Blues") #cest = ax.contourf(np.transpose(mesh_x),b,a,zdir='x', offset=0, cmap="Greys") #cest = ax.contourf(e,np.transpose(mesh_y),f,zdir="y", offset=image.shape[1], cmap="Greys") ax.tick_params(axis='both', which='major', labelsize=18) ax.set_ylim(0, image.shape[1]) ax.set_xlim(0, image.shape[0]) ax.set_zlim(0, image.shape[2]) ax.set_title(name+": 3D nodules and liver") if save: fig.savefig("/home/nnk/Bachelor/LiTS/Liver_segmentations/"+name+"_3D_nodules_and_liver.png", bbox_inches='tight') plt.close(fig) del mesh, verts, faces, face_color if check: del mesh2, verts2, faces2, face_color2
def test_marching_cubes_anisotropic(): spacing = (1.0, 10 / 6.0, 16 / 6.0) ellipsoid_anisotropic = ellipsoid(6, 10, 16, spacing=spacing, levelset=True) _, surf = ellipsoid_stats(6, 10, 16) verts, faces = marching_cubes(ellipsoid_anisotropic, 0.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
def update_segmentation_slices(selected, annotations): ctx = dash.callback_context # When shape annotations are changed, reset segmentation visualization if (ctx.triggered[0]["prop_id"] == "annotations.data" or annotations is None or annotations.get("x") is None or annotations.get("z") is None): mask = np.zeros_like(med_img) overlay1 = slicer1.create_overlay_data(mask) overlay2 = slicer2.create_overlay_data(mask) return go.Mesh3d(), overlay1, overlay2 elif selected is not None and "range" in selected: if len(selected["points"]) == 0: return dash.no_update v_min, v_max = selected["range"]["x"] t_start = time() # Horizontal mask path = path_to_coords(annotations["z"]["path"]) rr, cc = draw.polygon(path[:, 1] / spacing[1], path[:, 0] / spacing[2]) mask = np.zeros(img.shape[1:]) mask[rr, cc] = 1 mask = ndimage.binary_fill_holes(mask) # top and bottom, the top is a lower number than the bottom because y values # increase moving down the figure top, bottom = sorted( [int(annotations["x"][c] / spacing[0]) for c in ["y0", "y1"]]) img_mask = np.logical_and(med_img > v_min, med_img <= v_max) img_mask[:top] = False img_mask[bottom:] = False img_mask[top:bottom, np.logical_not(mask)] = False img_mask = largest_connected_component(img_mask) # img_mask_color = mask_to_color(img_mask) t_end = time() print("build the mask", t_end - t_start) t_start = time() # Update 3d viz verts, faces, _, _ = measure.marching_cubes(filters.median( img_mask, selem=np.ones((1, 7, 7))), 0.5, step_size=3) t_end = time() print("marching cubes", t_end - t_start) x, y, z = verts.T i, j, k = faces.T trace = go.Mesh3d(x=z, y=y, z=x, color="red", opacity=0.8, i=k, j=j, k=i) overlay1 = slicer1.create_overlay_data(img_mask) overlay2 = slicer2.create_overlay_data(img_mask) # todo: do we need an output to trigger an update? return trace, overlay1, overlay2 else: return (dash.no_update, ) * 3
def measure_surface_dist_real_size(struct1, struct2, pixdim): """ :param struct1: ndarray of 3D image 1 (the result of nib.get_data()) :param struct2: ndarray of 3D image 2 (the result of nib.get_data()) :param pixdim: :return: Averaged Euclidan distance between the structures surface points (in mm) """ voxel_size = [pixdim[2], pixdim[1], pixdim[3]] verts1, faces1, normals1, values1 = measure.marching_cubes(struct1, 0.5) verts2, faces2, normals2, values2 = measure.marching_cubes(struct2, 0.5) min_s_dist_array = np.zeros(verts1.shape[0]) for ind, surface_point in enumerate(verts1): min_s_dist_array[ind] = min( np.linalg.norm(((verts2 - surface_point) * voxel_size), axis=1)) mean_surface_dist = np.mean(min_s_dist_array) return mean_surface_dist
def make_mesh(image, threshold=-500, step_size=1): p = image.transpose(2, 1, 0) verts, faces, norm, val = measure.marching_cubes(p, threshold, step_size=step_size, allow_degenerate=True) return verts, faces
def plot_3d(image_1, image_2, threshold=-300): # Position the scan upright, # so the head of the patient would be at the top facing the camera try: print('Plotting...') global first_pass first_pass = '******' p_1 = image_1.transpose(2, 1, 0) verts1, faces1 = measure.marching_cubes(p_1, threshold) fig = plt.figure(figsize=(10, 10)) ax1 = fig.add_subplot(121, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh1 = Poly3DCollection(verts1[faces1], alpha=0.70) face_color = [0.45, 0.45, 0.75] mesh1.set_facecolor(face_color) #return mesh ax1.add_collection3d(mesh1) ax1.set_xlim(0, p_1.shape[0]) ax1.set_ylim(0, p_1.shape[1]) ax1.set_zlim(0, p_1.shape[2]) p_2 = image_2.transpose(2, 1, 0) verts2, faces2 = measure.marching_cubes(p_2, threshold) ax2 = fig.add_subplot(122, projection='3d') mesh2 = Poly3DCollection(verts2[faces2], alpha=0.70) mesh2.set_facecolor(face_color) ax2.add_collection3d(mesh2) ax2.set_xlim(0, p_2.shape[0]) ax2.set_ylim(0, p_2.shape[1]) ax2.set_zlim(0, p_2.shape[2]) print('Done!') first_pass = '******' except: print('Problem Plotting Graph...\n ABORT') first_pass = '******' return fig
def _compute_shape_size_features(self): """ compute volume under a given mask""" # mask volume vox_size_SRC = 0.1 * np.array(self._IG.samplingSRC) # unit: cm vox_vol = np.prod(vox_size_SRC) # unit: cm^ vol_cm3 = np.sum(self._maskImage_ndarray) * vox_vol # unit: ml or cm^3 self._df_feature_output['ShapeSize_vol_cm3'] = vol_cm3 # mask surface area the_tumor_vol = np.zeros(self._inputImage_ndarray.shape) the_tumor_vol[self._maskImage_ndarray] = self._inputImage_ndarray[ self._maskImage_ndarray] verts, faces = skm.marching_cubes(the_tumor_vol, 0.0, tuple(vox_size_SRC)) surf_area_cm2 = skm.mesh_surface_area(verts, faces) # unit: cm^2 self._df_feature_output['ShapeSize_surf_area_cm2'] = surf_area_cm2 self._df_feature_output['ShapeSize_compactness1'] = vol_cm3 / ( np.sqrt(np.pi) * surf_area_cm2**(2. / 3.)) self._df_feature_output['ShapeSize_compactness2'] = ( 36. * np.pi * vol_cm3**2) / (surf_area_cm2**3) self._df_feature_output['ShapeSize_sphericity'] = (np.pi**( 1. / 3.)) * (6 * vol_cm3)**(2. / 3.) / surf_area_cm2 self._df_feature_output[ 'ShapeSize_surface2volratio'] = surf_area_cm2 / vol_cm3 # maximum 3D euclidean distance (or diameter?) kk, ii, jj = np.where(self._maskImage_ndarray == True) # skip computing max euclidean distance if the mask is too big such as including skin and etc. if len(kk) > 300000 and vol_cm3 > 70.: print '::ImageFeature:: compute_shape_size_feature, tumor mask is TOO big (vol: {} ml)! will not compute euc max distance :/'.format( vol_cm3) else: print '::ImageFeature:: max euc distance # of voxels to go through: {}, vol = {} cm3'.format( len(kk), vol_cm3) eucdis_tmp = np.zeros((len(kk), 1)) for n in range(len(kk) - 1): px1 = np.column_stack((kk[n + 1:], ii[n + 1:], jj[n + 1:])) px2 = np.tile(np.array([kk[n], ii[n], jj[n]]), (px1.shape[0], 1)) vox_size_tile = np.tile(vox_size_SRC, (px1.shape[0], 1)) eucdis = np.sqrt( np.sum(((px1 - px2) * vox_size_tile)**2, axis=1)) eucdis_tmp[n] = np.amax(eucdis) max_euc_dis = np.amax(eucdis_tmp) self._df_feature_output['ShapeSize_max_euc_dis'] = max_euc_dis # R is the radius of the sphere with the same volume as the tumor tumor_sphere_R = (3 * vol_cm3 / (4 * np.pi))**(1. / 3) self._df_feature_output[ 'ShapeSize_spherical_disproportion'] = surf_area_cm2 / ( 4 * np.pi * tumor_sphere_R**2) print '::ImageFeature:: complete compute_shape_size_features!'
def mask2mesh(mask, mesh_processing=None, voxel_size=(1.0, 1.0, 1.0), level=0, step_size=2, preprocessing=None): # apply volume preprocessing mask = mask if preprocessing is None else preprocessing(mask) # create mesh using marching cubes vertx, faces, normals, _ = measure.marching_cubes(mask, level=level, spacing=voxel_size, step_size=step_size) # if no mesh processing is defined returns tuple with marching cubes outputs mesh = (vertx, faces, normals) if mesh_processing is None else mesh_processing(vertx, faces, normals) return mesh
def extract_and_save_object( image, output_file_name, voxel_size, threshold=0, step_size=1 ): verts, faces, normals, values = measure.marching_cubes( image, threshold, step_size=step_size ) verts, faces = convert_obj_to_br(verts, faces, voxel_size) marching_cubes_to_obj( (verts, faces, normals, values), str(output_file_name) )
def make_mesh(self, threshold=400, step_size=1): images = self.resample() result = dict() for key, image in images.items(): p = image.transpose(2, 1, 0) verts, faces, norm, val = measure.marching_cubes(p, threshold, step_size=step_size, allow_degenerate=True) result[key] = (verts, faces) return result
def tsdf2mesh(tsdf_vol, mesh_path): tsdf_vol = np.transpose(tsdf_vol, (1, 0, 2)) # Marching cubes verts, faces, norms, vals = measure.marching_cubes(tsdf_vol, level=0.0) # Get vertex colors colors = np.array([(186 // 2, 176 // 2, 172 // 2) for _ in range(verts.shape[0])], dtype=np.uint8) meshwrite(mesh_path, verts, faces, norms, colors)
def test_masked_marching_cubes(): ellipsoid_scalar = ellipsoid(6, 10, 16, levelset=True) mask = np.ones_like(ellipsoid_scalar, dtype=bool) mask[:10, :, :] = False mask[:, :, 20:] = False ver, faces, _, _ = marching_cubes(ellipsoid_scalar, 0, mask=mask) area = mesh_surface_area(ver, faces) assert_allclose(area, 299.56878662109375, rtol=.01)
def from_volume(self, voxel_grid, level=0): ''' generates a mesh from a volume voxel_grid, using marching cubes voxel_grid should be a voxel grid object. This allows for the coordinates of the found mesh to be in world space. ''' temp_verts, temp_faces = marching_cubes(voxel_grid.V, level) self.vertices = voxel_grid.idx_to_world(temp_verts) self.faces = temp_faces
def make_meshNew(image, threshold=-100, step_size=1): # Generates a mesh from a stack of images (image variable) print "Transposing surface" # p = image.transpose(2,1,0) p = image print "Calculating surface" try: if (threshold == 0.0): verts, faces = measure.marching_cubes(p) else: verts, faces = measure.marching_cubes(p, threshold) except: if (threshold == 0.0): verts, faces = measure.marching_cubes_classic(p) else: verts, faces = measure.marching_cubes_classic(p, threshold) return verts, faces
def make_outer_surface(filled_file, output_surface_file, se_diameter=15): if os.path.isfile(output_surface_file): log.info('Dural surface mesh %s already exists' % os.path.basename(output_surface_file)) return # read MRI volume = nbfs.MGHImage.from_filename(filled_file) volume = volume.get_data() # change elements from {0,1} to {0,255} volume *= 255 # Gaussian filter (sigma=1mm) gaussian_volume = scimage.gaussian_filter( volume, 1, mode='constant') # Is this correct? # Binarize filtered image avg = gaussian_volume.mean() gaussian_volume[gaussian_volume > avg] = 255 gaussian_volume[gaussian_volume < avg] = 0 # Morphological closing: # Construct structuring element xx, yy = np.meshgrid(list(range(-1 * se_diameter + 1, se_diameter)), list(range(-1 * se_diameter + 1, se_diameter))) se = (xx**2 + yy**2) < se_diameter**2 # Take closing closed_volume = np.stack([ scimage.grey_closing( gaussian_volume[..., i], structure=se, mode='constant') for i in range(gaussian_volume.shape[-1]) ], axis=-1) # Binarize closed image thresh = closed_volume.max() / 2 closed_volume[closed_volume <= thresh] = 0 closed_volume[closed_volume > thresh] = 255 # vertices,faces = isosurface(*,100) vertices, faces, _, _ = measure.marching_cubes(closed_volume, 100) # Reorient v2 = np.zeros(vertices.shape) v2[:, 0] = 129 - vertices[:, 0] v2[:, 1] = vertices[:, 2] - 129 v2[:, 2] = 129 - vertices[:, 1] vertices = v2 # Write geometry file nbfs.write_geometry(output_surface_file, vertices, faces)
def __build_mesh(self, image, threshold=300, step_size=1): ''' Helper method to build mesh for given 3D scan ''' print("Transposing surface") p = image.transpose(2, 1, 0) print("Generating mesh") verts, faces, _, _ = measure.marching_cubes(p, threshold, step_size=step_size)#, #allow_degenerate=True) return verts, faces, p
def calculate_burning_area_3d(regression_map, regression_depth, mc_mask, volume_ratio): regression_depth = regression_depth / volume_ratio verts, faces, norm, line = measure.marching_cubes( regression_map, level=regression_depth, mask=mc_mask, spacing=(volume_ratio, volume_ratio, volume_ratio)) # (hide false values) burning_area = measure.mesh_surface_area(verts, faces) return burning_area
def reconstruction(structured_implicit, resolution, b_min, b_max, use_octree=False, num_samples=10000, marching_cube=True): ''' Reconstruct meshes from sdf predicted by the network. :param structured_implicit: a StructuredImplicit object. :param resolution: resolution of the grid cell :param b_min: bounding box corner [x_min, y_min, z_min] :param b_max: bounding box corner [x_max, y_max, z_max] :param use_octree: whether to use octree acceleration :param num_samples: how many points to query each gpu iteration :return: marching cubes results. ''' # First we create a grid by resolution # and transforming matrix for grid coordinates to real world xyz coords, mat = create_grid(resolution, resolution, resolution, b_min, b_max) # Then we define the lambda function for cell evaluation def eval_func(points, structured_implicit): points = np.expand_dims(points, axis=0) samples = torch.from_numpy(points).to(device=structured_implicit.device).float() samples = samples.transpose(-1, -2) samples = samples.expand(structured_implicit.batch_size, -1, -1) pred = structured_implicit.class_at_samples(samples, apply_class_transfer=False)[0][..., 0] return pred.detach().cpu().numpy() # Then we evaluate the grid if use_octree: sdf = [] for s in structured_implicit.unbind(): sdf.append(eval_grid_octree(coords, lambda p:eval_func(p, s), num_samples=num_samples).squeeze()) sdf = np.stack(sdf) else: sdf = eval_grid(coords, lambda p:eval_func(p, structured_implicit), num_samples=num_samples, batch_size=structured_implicit.batch_size) # Finally we do marching cubes if marching_cube: mesh = [] for s in sdf: try: verts, faces, _, _ = measure.marching_cubes(s, -0.07) # transform verts into world coordinate system verts = np.matmul(mat[:3, :3], verts.T) + mat[:3, 3:4] verts = verts.T mesh.append(trimesh.Trimesh(vertices=verts, faces=faces)) except (ValueError, RuntimeError) as e: print('Failed to extract mesh with error %s. Setting to unit sphere.' % repr(e)) mesh.append(trimesh.primitives.Sphere(radius=0.5)) return mesh else: return sdf, mat
def getModel(self): cloudField = self.cloudSet.getCloud() verts, faces, normals, values = (np.array((), dtype=np.float32) for i in range(4)) if np.any(cloudField > 0.1): verts, faces, normals, values = measure.marching_cubes( cloudField, 0.1) # edges = self.cloudSet.getEdgeStrength(verts) # verts, faces, normals, edges = self.decimate(verts, faces, normals, edges, 3) return verts, faces, normals
def seg2mesh(idx, segmentation, step_size=1): mask = segmentation == idx _z, _x, _y = np.nonzero(mask) # returns True only if mask is not flat in any dimension if abs(_z.max() - _z.min()) > 1 and abs(_x.max() - _x.min()) > 1 and abs( _y.max() - _y.min()) > 1: coords, faces, _, _ = marching_cubes(mask, step_size=step_size) return coords, faces else: return None, None
def add_trisurf(ax, arr, x, y, z, iso_val, **kwds): verts, faces, normals, values = measure.marching_cubes(arr, iso_val) verts_p = verts.copy() verts_p[:, 2] = np.interp(verts_p[:, 2], np.arange(len(x)), x) verts_p[:, 1] = np.interp(verts_p[:, 1], np.arange(len(y)), y) verts_p[:, 0] = np.interp(verts_p[:, 0], np.arange(len(z)), z) psurf = ax.plot_trisurf(verts_p[:, 2], verts_p[:, 1], faces, verts_p[:, 0], **kwds) return psurf
def three_d_print(volume_data): b = raw_input('What resolution? (enter an int between 0 and 6, where 0 is highest resolution):\n') name = raw_input('What should the filename be?') + '.stl' verts, faces = measure.marching_cubes(volume_data, 0) solid = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): solid.vectors[i][j] = verts[f[j],:] solid.save(name)
def isosurface(M,v,step,title=""): """ returns the isosurface of value v of M, subsetting M with the steps argument """ sel = np.arange(0,np.shape(M)[0],step) verts, faces = measure.marching_cubes(M[np.ix_(sel,sel,sel)], v, spacing=(1.0, 1.0, 1.0)) fig = plt.figure(figsize = (10,7)) ax = fig.add_subplot(111, projection='3d') ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2], lw=.1, cmap="jet") ax.axis("off") ax.view_init(elev=35, azim=70) plt.title(title) plt.show()
def three_d_print(self): """This will produce a 3d printable stl based on self.volume_data. It is to be used for the final "print" button, and needs to be fed high quality data.""" name = raw_input('What should the filename be?') + '.stl' verts, faces = measure.marching_cubes(self.volume_data, 0) #Marching Cubes algorithm solid = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): solid.vectors[i][j] = verts[f[j],:] solid.save(name)
def marchingcubesobj(data,iso,objfile,scale=(1,1,1),center=(0,0,0),vertexoffset=0,excludeslice=False,debug=True): if iso < data.min() or iso > data.max(): return 0,0 vert,face = measure.marching_cubes(data,iso) vert[:,0]=scale[0]*(vert[:,0]-data.shape[0]/2.)+center[0] vert[:,1]=scale[1]*(vert[:,1]-data.shape[1]/2.)+center[1] vert[:,2]=scale[2]*(vert[:,2]-data.shape[2]/2.)+center[2] if debug: print 'Writing Data:' for i in xrange(vert.shape[0]): outstr = 'v %7.3f %7.3f %7.3f\n'%(vert[i,0],vert[i,1],vert[i,2]) objfile.write(outstr) for i in xrange(face.shape[0]): outstr = 'f %9d %9d %9d\n'%(face[i,0]+1+vertexoffset,face[i,1]+1+vertexoffset,face[i,2]+1+vertexoffset) objfile.write(outstr) # print (vert[:,0].min(),vert[:,1].min(),vert[:,2].min()),(vert[:,0].max(),vert[:,1].max(),vert[:,2].max()) return vert.shape[0], face.shape[0]
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(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_correct_mesh_orientation(): sphere_small = ellipsoid(1, 1, 1, levelset=True) verts, faces = marching_cubes(sphere_small, 0.) # Correct mesh orientation - descent corrected_faces1 = correct_mesh_orientation(sphere_small, verts, faces, gradient_direction='descent') corrected_faces2 = correct_mesh_orientation(sphere_small, verts, faces, gradient_direction='ascent') # Ensure ascent is opposite of descent for all faces np.testing.assert_array_equal(corrected_faces1, corrected_faces2[:, ::-1]) # Ensure correct faces have been reversed: 1, 4, and 5 idx = [1, 4, 5] expected = faces.copy() expected[idx] = expected[idx, ::-1] np.testing.assert_array_equal(expected, corrected_faces1)
def implicit_surface(density_field,size,resolution,iso=0.5): import numpy as np from scipy.cluster.vq import kmeans, vq from openalea.container import array_dict from skimage.measure import marching_cubes surface_points, surface_triangles = marching_cubes(density_field,iso) surface_points = (np.array(surface_points))*(size*resolution/np.array(density_field.shape)) - size*resolution/2. points_ids = np.arange(len(surface_points)) points_to_delete = [] for p,point in enumerate(surface_points): matching_points = np.sort(np.where(vq(surface_points,np.array([point]))[1] == 0)[0]) if len(matching_points) > 1: points_to_fuse = matching_points[1:] for m_p in points_to_fuse: surface_triangles[np.where(surface_triangles==m_p)] = matching_points[0] points_to_delete.append(m_p) points_to_delete = np.unique(points_to_delete) print len(points_to_delete),"points deleted" surface_points = np.delete(surface_points,points_to_delete,0) points_ids = np.delete(points_ids,points_to_delete,0) surface_triangles = array_dict(np.arange(len(surface_points)),points_ids).values(surface_triangles) for p,point in enumerate(surface_points): matching_points = np.where(vq(surface_points,np.array([point]))[1] == 0)[0] if len(matching_points) > 1: print p,point raw_input() triangles_to_delete = [] for t,triangle in enumerate(surface_triangles): if len(np.unique(triangle)) < 3: triangles_to_delete.append(t) # elif triangle.max() >= len(surface_points): # triangles_to_delete.append(t) surface_triangles = np.delete(surface_triangles,triangles_to_delete,0) return surface_points, surface_triangles
def marching_cubes(field,iso=0.5): try: from skimage.measure import marching_cubes surface_points, surface_triangles = marching_cubes(density_field,iso) except ImportError: print "Please try to install SciKit-Image!" from mayavi import mlab from mayavi.mlab import contour3d mlab.clf() surface = mlab.contour3d(field,contours=[iso]) my_actor=surface.actor.actors[0] poly_data_object=my_actor.mapper.input surface_points = (np.array(poly_data_object.points) - np.array([abs(grid_points/2.),abs(grid_points/2.),abs(grid_points/2.)])[np.newaxis,:])*(grid_max/abs(grid_points/2.)) surface_triangles = poly_data_object.polys.data.to_array().reshape([-1,4]) surface_triangles = surface_triangles[:,1:] return surface_points, surface_triangles
def plot_3d(image, threshold=-300): # Position the scan upright, # so the head of the patient would be at the top facing the camera p = image.transpose(2,1,0) verts, faces = measure.marching_cubes(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]) plt.show()
def test_mc_skimage_orig_example(self): import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure from skimage.draw import ellipsoid # Generate a level set about zero of two identical ellipsoids in 3D ellip_base = ellipsoid(6, 10, 16, levelset=True) ellip_double = np.concatenate((ellip_base[:-1, ...], ellip_base[2:, ...]), axis=0) # Use marching cubes to obtain the surface mesh of these ellipsoids # outs = measure.marching_cubes(ellip_double, 0) # verts, faces, normals, values = measure.marching_cubes(ellip_double, 0) verts, faces = measure.marching_cubes(ellip_double, 0) # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi (see skimage.measure.marching_cubes docstring). 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]) mesh.set_edgecolor('k') ax.add_collection3d(mesh) ax.set_xlabel("x-axis: a = 6 per ellipsoid") ax.set_ylabel("y-axis: b = 10") ax.set_zlabel("z-axis: c = 16") ax.set_xlim(0, 24) # a = 6 (times two for 2nd ellipsoid) ax.set_ylim(0, 20) # b = 10 ax.set_zlim(0, 32) # c = 16 plt.tight_layout() plt.show()
def plot_voxels(volume): import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure # Use marching cubes to obtain the surface mesh verts, faces = measure.marching_cubes(volume, 0.5) # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi (see skimage.measure.marching_cubes docstring). fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.set_xlim(0, volume.shape[0]) ax.set_ylim(0, volume.shape[1]) ax.set_zlim(0, volume.shape[2]) ax.set_aspect('equal') plt.show()
def marche_cubes( ids , volume): """ Given a segmentation volume and set of ids, it first computes a boolean volume, where every voxel which correspond to an id present in the ids set is set to true. It then create a mesh in the boundaries between true and false. The generated mesh guarantees coherent orientation as of version 0.12. of scikit-image Args: ids (tuple): segment ids that we want to generate a mesh from. volume (numpy.array): volume to process """ shape = volume.shape volume = np.in1d(volume,ids).reshape(shape) try: vertices, triangles = measure.marching_cubes(volume, 0.4) except Exception, e: return np.array([]), np.array([])
def isoSurface3d(image, level=1, fn='./plots/isosurf3d.html'): ''' wrapper function for plotly's isosurface 3d plots args: @a image: 3d array of numbers @a level: level at which to make an isocontour @a fn: string, filename to save plot as ''' vertices, simplices = measure.marching_cubes(image, level) x,y,z = zip(*vertices) fig = FF.create_trisurf( x=x, y=y, z=z, simplices=simplices ) py.offline.plot(fig, filename=fn)
def reconstruction_from2DtoSTL(path, name, way, size): """ Build a 3D object from a serie of 2D images. Input parameters ---------------- path : str Folder with 2D images. name : str Wanted name for the created STL file. way : 'plot' or 'save' Can plot the 3D object or can save it with the STL extension. size : int or 'all' Can have a 3D object with every face, or can have a divided 3D object. Example : if size = 2, 1 of 2 slices on the x axis is taken, 1 of 2 slices on the y axis is taken, and 1 of 2 slices on the z axis is taken, so the 3D object is 8 times 'lighter'. """ plt.close('all') line = currentframe().f_back.f_lineno if path.__class__ != str: print 'Line', line, '- Error: Directory must be str.' exit() elif name.__class__ != str: print 'Line', line, '- Error: Name must be str.' exit() elif (way != 'plot' and way != 'save'): print 'Line', line, '- Error: Way must be "plot" or "save".' exit() elif (size != 'all' and size.__class__ != int): print 'Line', line, '- Error: Size must be "all" or int.' exit() else: begin_time = time.time() # pixel_file = (glob.glob(path.split(path.split('/')[-2])[0] + 'pixel_spacing.txt'))[0] # with open(pixel_file, 'r') as pixel_readfile: # for line in pixel_readfile: # pixel_width = float(line.split('\t')[1]) # pixel_height = float(line.split('\t')[2]) # voxel_depth = float(line.split('\t')[3])$ pixel_width = 1.0 pixel_height = 1.0 voxel_depth = 1.0 files = glob.glob(path + '*') files.sort() # files.remove(pixel_file) width = (misc.imread(files[0])).shape[0] height = (misc.imread(files[0])).shape[1] # width, height = (misc.imread(files[0])).shape ZD_object = np.array([[0 for i in range(width)] for j in range(height)]) k = 1 for file in files: try: filename = file.split('/')[-1] except: filename = file.split('\\')[-1] print 'Reading image', filename, '(', k, '/', str(len(files)), ')...' image = misc.imread(file) for i in range(width): for j in range(height): if len((image[i][j]).shape) != 0: image[i][j] = image[i][j][0] ZD_object = np.dstack((ZD_object, image)) k = k+1 append_time = time.time() print 'Image reading and appending to 3D object time:', round(append_time - begin_time, 3), 'seconds' print '\nSize of 3D object:', ZD_object.shape[0], 'x', ZD_object.shape[1], 'x', ZD_object.shape[2] print '\nStarting the 3D reconstruction...' if size == 'all': verts, faces = measure.marching_cubes(ZD_object, 0.5, spacing = (pixel_width, pixel_height, voxel_depth)) else: verts, faces = measure.marching_cubes(ZD_object[::size,::size,::size], 0.5, spacing = (pixel_width, pixel_height, voxel_depth)) marchingcubes_time = time.time() print 'Marching cubes time:', round(marchingcubes_time - append_time, 3), 'seconds' if way == 'plot': print '\nPlotting the 3D object...' fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') #ax = Axes3D(fig) isosurface = Poly3DCollection(verts[faces]) ax.add_collection3d(isosurface) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') ax.set_xlim(0, 100) ax.set_ylim(0, 100) ax.set_zlim(0, 100) plt.show() plot_time = time.time() print 'Plotting time:', round(plot_time - marchingcubes_time, 3), 'seconds' elif way == 'save': print '\nSaving the STL file...' final_obj = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i,f in enumerate(faces): for j in range(3): final_obj.vectors[i][j] = verts[f[j],:] try: path_1 = path.split(path.split('/')[-2])[0] except: path_1 = path.split(path.split('\\')[-2])[0] final_obj.save(path_1 + name + '.stl') save_time = time.time() print 'Saving time:', round(save_time - marchingcubes_time, 3), 'seconds' print '\n3D reconstruction done.\n'
dcm.append(os.path.join(filename)) #read first file to start array ds = dicom.read_file(dcm[0]) ds1p = ds.pixel_array dsfull = ds1p for i in range(1,len(dcm)): imgref = dcm[i] ds = dicom.read_file(imgref) pa = ds.pixel_array dsfull = np.dstack((dsfull, pa)) dsfull = dsfull.swapaxes(0,2) verts, faces = measure.marching_cubes(dsfull, 255) fig = plt.figure(figsize=(692, 778)) ax = fig.add_subplot(111, projection='3d') mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.set_xlim(0, 21) ax.set_ylim(0, 692) ax.set_zlim(0, 778) plt.show()
def plot_ellipsoid(self, hkle, dpi=100): r"""Plots the resolution ellipsoid in the $Q_x$, $Q_y$, $W$ zone Parameters ---------- hkle : tup A tuple of intergers or arrays of H, K, L, and W (energy transfer) values at which resolution ellipsoid are desired to be plotted dpi : int, optional Number of points in the plot """ try: from skimage import measure import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D except ImportError: raise # clean arguments [length, H, K, L, W] = _CleanArgs(*hkle) # check if resolution already calculated at given hkle try: if np.all(H == self.H) and np.all(K == self.K) and np.all(L == self.L) and np.all(W == self.W): NP = np.array(self.RMS) R0 = self.R0 else: self.calc_resolution(hkle) NP = np.array(self.RMS) R0 = self.R0 except AttributeError: self.calc_resolution(hkle) NP = np.array(self.RMS) R0 = self.R0 if NP.shape == (4, 4): NP = NP[np.newaxis] R0 = [R0] else: NP = NP.T # Create a canvas with a 3D viewport fig = plt.figure(facecolor='w', edgecolor='k') ax = fig.add_subplot(111, projection='3d') for ind, (r0, rms) in enumerate(zip(R0, NP)): qx0, qy0 = [np.dot([H[ind], K[ind], L[ind]], self.orient1 / np.linalg.norm(self.orient1) ** 2), np.dot([H[ind], K[ind], L[ind]], self.orient2 / np.linalg.norm(self.orient2) ** 2)] qw0 = W[ind] def resolution_ellipsoid(prefac, resmat, x, y, w, x0, y0, w0): r"""Resolution ellipsoid equation for qx, qy, and w dimensions Parameters ---------- prefac : float resmat : ndarray(4,4) x : ndarray y : ndarray w : ndarray x0 : float y0 : float w0 : float Returns ------- res_func : ndarray """ ee = (resmat[0, 0] * (x - x0) ** 2 + resmat[1, 1] * (y - qy0) ** 2 + resmat[3, 3] * (w - w0) ** 2 + 2 * resmat[0, 1] * (x - x0) * (y - y0) + 2 * resmat[0, 2] * (x - x0) * (w - w0) + 2 * resmat[1, 2] * (y - y0) * (w - w0)) return prefac * np.exp(-1 / 2 * ee) # get fwhm to generate grid for plotting w = [] for i in range(3): _rms = np.delete(np.delete(rms, 2, axis=0), 2, axis=1) w.append(fproject(_rms.reshape((3, 3, 1)), i)[0] * 1.01) wx, wy, ww = w # build grid xg, yg, zg = np.mgrid[qx0 - wx:qx0 + wx:(dpi + 1) * 1j, qy0 - wy:qy0 + wy:(dpi + 1) * 1j, qw0 - ww:qw0 + ww:(dpi + 1) * 1j] # resolution function (ellipsoidal gaussian) vol = resolution_ellipsoid(r0, rms, xg, yg, zg, qx0, qy0, qw0) # isosurface of resolution function at half-max vertices, faces, normals, values = measure.marching_cubes(vol, vol.max() / 2.0, spacing=(wx / dpi, wy / dpi, ww / dpi)) # properly center ellipsoid x_verts = vertices[:, 0] + qx0 - wx / 2 y_verts = vertices[:, 1] + qy0 - wy / 2 z_verts = vertices[:, 2] + qw0 - ww / 2 # plot ellipsoid ax.plot_trisurf(x_verts, y_verts, faces, z_verts, lw=0, cmap='Spectral') # figure labels ax.ticklabel_format(style='plain', useOffset=False) ax.set_xlabel(r'$q_x$ (along {0}) (r.l.u.)'.format(self.orient1), fontsize=12) ax.set_ylabel(r'$q_y$ (along {0}) (r.l.u.)'.format(self.orient2), fontsize=12) ax.set_zlabel(r'$\hbar \omega$ (meV)', fontsize=12) plt.show()
""" import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure from skimage.draw import ellipsoid # Generate a level set about zero of two identical ellipsoids in 3D ellip_base = ellipsoid(6, 10, 16, levelset=True) ellip_double = np.concatenate((ellip_base[:-1, ...], ellip_base[2:, ...]), axis=0) # Use marching cubes to obtain the surface mesh of these ellipsoids verts, faces, normals, values = measure.marching_cubes(ellip_double, 0) # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi or visvis (see skimage.measure.marching_cubes docstring). fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.set_xlabel("x-axis: a = 6 per ellipsoid") ax.set_ylabel("y-axis: b = 10") ax.set_zlabel("z-axis: c = 16") ax.set_xlim(0, 24) # a = 6 (times two for 2nd ellipsoid)
print 'losses max -> ',(np.amax( losses )) print 'losses argmax -> ',(np.argmax( losses )) print 'losses x[max] -> ',g_x[(np.argmax( losses ))] print 'v',v print 'sigma',sigma data = pop_data_grid(g_Desc[g_counter], g_Desc[g_counter].beta,g_Desc[g_counter].rho, x0_max,x1_max,x2_max,x0_min,x1_min,x2_min) proc_data(g_Desc[g_counter].beta,g_Desc[g_counter].rho,data) # In[22]: # Use marching cubes to obtain the surface mesh of these ellipsoids verts, faces = measure.marching_cubes(data, 0) for elev in [180,120,60,90]: for azim in [30,90,180,240]: # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi (see skimage.measure.marching_cubes docstring). fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.view_init(elev=elev, azim=azim) ax.set_xlim(0,grid_steps) ax.set_ylim(0,grid_steps)
def getVFByMarchingCubes(voxels, threshold=0.5): v, f = sk.marching_cubes(voxels, level=threshold) return v, f
def reconstruction_fromXYZtoSTL(file, way, size): """ Build a 3D object from a XYZ file. Input parameters ---------------- file : str XYZ file. way : 'plot' or 'save' Can plot the 3D object or can save it with the STL extension. size : int or 'all' Can have a 3D object with every face, or can have a divided 3D object. Example : if size = 2, 1 of 2 slices on the x axis is taken, 1 of 2 slices on the y axis is taken, and 1 of 2 slices on the z axis is taken, so the 3D object is 8 times 'lighter'. """ line = currentframe().f_back.f_lineno if file.__class__ != str: print 'Line', line, '- Error: File must be str.' exit() elif (way != 'plot' and way != 'save'): print 'Line', line, '- Error: Way must be "plot" or "save".' exit() elif (size != 'all' and size.__class__ != int): print 'Line', line, '- Error: Size must be "all" or int.' exit() else: begin_time = time.time() print '\nStarting the conversion from a XYZ file to a STL file...' images = reconstruction_fromXYZto2D(file, 'nosave') XYZto2D_time = time.time() print 'Converting from XYZ file to 2D images:', round(XYZto2D_time - begin_time, 3), 'seconds' width = (images[0]).shape[0] height = (images[0]).shape[1] begin_time = time.time() print "\nStarting the 3D reconstruction..." ZD_object = np.array([[0 for i in range(width)] for j in range(height)]) for image in images: ZD_object = np.dstack((ZD_object, image)) append_time = time.time() print 'Image reading and appending to 3D object time:', round(append_time - XYZto2D_time, 3), 'seconds' print '\nSize of 3D object:', ZD_object.shape[0], 'x', ZD_object.shape[1], 'x', ZD_object.shape[2] if size == 'all': verts, faces = measure.marching_cubes(ZD_object, 0.5) else: verts, faces = measure.marching_cubes(ZD_object[::size,::size,::size], 0.5) marchingcubes_time = time.time() print 'Marching cubes time:', round(marchingcubes_time - begin_time, 3), 'seconds' if way == 'plot': print '\nPlotting the 3D object...' fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') #ax = Axes3D(fig) isosurface = Poly3DCollection(verts[faces]) ax.add_collection3d(isosurface) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') ax.set_xlim(0, 100) ax.set_ylim(0, 100) ax.set_zlim(0, 100) plt.show() plot_time = time.time() print 'Plotting time:', round(plot_time - marchingcubes_time, 3), 'seconds' elif way == 'save': print '\nSaving the STL file...' final_obj = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i,f in enumerate(faces): for j in range(3): final_obj.vectors[i][j] = verts[f[j],:] name = file.split('.xyz')[0] final_obj.save(name + '.stl') save_time = time.time() print 'Saving time:', round(save_time - marchingcubes_time, 3), 'seconds' print '\n3D reconstruction done.\n'
def writeContoursToJson(LFP, x, y, z, n=1, directory='neuron'): dname_base = 'contour_' fname_base = 'frame_' config_name = 'config.js' dirs_config_name = 'contour_dir_list.js' dx = np.abs(x[1] - x[0]) dy = np.abs(y[1] - y[0]) dz = np.abs(z[1] - z[0]) nx = len(x) ny = len(y) nz = len(z) baseline = 0 # Choose n isopotentials between max amplitude and baseline, not # including endpoints. amp_max = LFP.max() values_pos = [] if amp_max > 0: values_pos = np.linspace(baseline, amp_max, n + 2) values_pos = values_pos[1:-1] amp_min = LFP.min() values_neg = [] if amp_min < 0: values_neg = np.linspace(baseline, amp_min, n + 2) values_neg = values_neg[1:-1] contour_directories = [] contour_cnt = 0 for iso_pot_val in values_pos: # Create a seperate folder for each contour animation. dir_name = dname_base + '%04d' % (contour_cnt) contour_directories.append(dir_name) dir_path = directory + '/' + dir_name if not os.path.exists(dir_path): os.makedirs(dir_path) for i in xrange(LFP.shape[1]): U = LFP[:, i].reshape(nx, ny, nz) # The marching cubes algorithm cannot deal with levels # outside the range of U. if U.max() < iso_pot_val or U.min() > iso_pot_val: verts = np.zeros([0, 3]) faces = np.zeros([0, 3]) else: verts, faces = measure.marching_cubes(U, iso_pot_val, spacing=(dx, dy, dz)) verts[:, 0] = verts[:, 0] + x[0] verts[:, 1] = verts[:, 1] + y[0] verts[:, 2] = verts[:, 2] + z[0] filename = fname_base + '%04d.js' % (i) meshToJson(verts, faces, filename, dir_path) # Save a config file listing all the data files. data = {'n_frames': LFP.shape[1]} dataString = json.dumps(data) f = open(dir_path + '/' + config_name, 'w') f.write(dataString) f.close() contour_cnt += 1 for iso_pot_val in values_neg: # Create a seperate folder for each contour animation. dir_name = dname_base + '%04d' % (contour_cnt) contour_directories.append(dir_name) dir_path = directory + '/' + dir_name if not os.path.exists(dir_path): os.makedirs(dir_path) for i in xrange(LFP.shape[1]): U = LFP[:, i].reshape(nx, ny, nz) # The marching cubes algorithm cannot deal with levels # outside the range of U. if U.max() < iso_pot_val or U.min() > iso_pot_val: verts = np.zeros([0, 3]) faces = np.zeros([0, 3]) else: verts, faces = measure.marching_cubes(U, iso_pot_val, spacing=(dx, dy, dz)) verts[:, 0] = verts[:, 0] + x[0] verts[:, 1] = verts[:, 1] + y[0] verts[:, 2] = verts[:, 2] + z[0] filename = fname_base + '%04d.js' % (i) meshToJson(verts, faces, filename, dir_path) # Save a config file listing all the data files. data = {'n_frames': LFP.shape[1]} dataString = json.dumps(data) f = open(dir_path + '/' + config_name, 'w') f.write(dataString) f.close() contour_cnt += 1 # Save a config file listing all the data files. data = {'n_contours': len(contour_directories)} dataString = json.dumps(data) f = open(directory + '/' + dirs_config_name, 'w') f.write(dataString) f.close()
# get the error size n_error_train = y_pred_train[y_pred_train == -1].size # Distance of the samples X, Y, Z to the sperating hyperplane Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel(), zz.ravel()]) Z = Z.reshape(xx.shape) plt.title("Novelty Detection") ax = plt.gca(projection='3d') # draw the points on the 3D graph b1 = ax.scatter(X_train[:, 0], X_train[:, 1], X_train[:, 2], c='white') # Signifies the Learning Curve # IMP it should be better as the data set gets better verts, faces = measure.marching_cubes(Z, 0) verts = verts * \ [X_MAX - X_MIN, Y_MAX - Y_MIN, Z_MAX - Z_MIN] / SPACE_SAMPLING_POINTS verts = verts + [X_MIN, Y_MIN, Z_MIN] mesh = Poly3DCollection(verts[faces], facecolor='orange', edgecolor='gray', alpha=0.3) ax.add_collection3d(mesh) ax.set_xlim((-20, 20)) ax.set_ylim((-20, 20)) ax.set_zlim((-20, 20)) ax.axis('tight') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") # ax.legend([mpatches.Patch(color='orange', alpha=0.3), b1, b2, c],
phi = la.spsolve(K3, source3) phi = phi.reshape((N,N,N)) x = np.linspace(0,L,N,endpoint=False) y = np.linspace(0,L,N,endpoint=False) z = np.linspace(0,L,N,endpoint=False) xv, yv, zv = np.meshgrid(x,y,z) # http://scikit-image.org/docs/dev/auto_examples/plot_marching_cubes.html from skimage import measure verts, faces = measure.marching_cubes(phi, 0.01) #-.1 #print verts verts = verts * L / N # rescale verts from mpl_toolkits.mplot3d.art3d import Poly3DCollection import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) verts, faces = measure.marching_cubes(phi, -0.01) #-.1
""" import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection from skimage import measure from skimage.draw import ellipsoid # Generate a level set about zero of two identical ellipsoids in 3D ellip_base = ellipsoid(6, 10, 16, levelset=True) ellip_double = np.concatenate((ellip_base[:-1, ...], ellip_base[2:, ...]), axis=0) # Use marching cubes to obtain the surface mesh of these ellipsoids verts, faces = measure.marching_cubes(ellip_double, 0) # Display resulting triangular mesh using Matplotlib. This can also be done # with mayavi (see skimage.measure.marching_cubes docstring). fig = plt.figure(figsize=(10, 12)) ax = fig.add_subplot(111, projection='3d') # Fancy indexing: `verts[faces]` to generate a collection of triangles mesh = Poly3DCollection(verts[faces]) ax.add_collection3d(mesh) ax.set_xlabel("x-axis: a = 6 per ellipsoid") ax.set_ylabel("y-axis: b = 10") ax.set_zlabel("z-axis: c = 16") ax.set_xlim(0, 24) # a = 6 (times two for 2nd ellipsoid)