def add_textures(output, textures, elname): """Add textures to a pyvista data object""" if not pyvista.is_pyvista_obj(output): output = pyvista.wrap(output) for i, tex in enumerate(textures): # Now map the coordinates for the texture m = vtk.vtkTextureMapToPlane() m.SetInputDataObject(output) m.SetOrigin(tex.origin) m.SetPoint1(tex.origin + tex.axis_u) m.SetPoint2(tex.origin + tex.axis_v) m.Update() # Grab the texture coordinates tmp = m.GetOutputDataObject(0) tcoord = tmp.GetPointData().GetTCoords() name = tex.name if name is None or name == '': name = '{}-texture-{}'.format(elname, i) tcoord.SetName(name) # Add these coordinates to the PointData of the output # NOTE: Let pyvista handle setting the TCoords because of how VTK cleans # up old TCoords output.GetPointData().AddArray(tcoord) # Add the vtkTexture to the output img = np.array(Image.open(tex.image)) tex.image.seek(0) # Reset the image bytes in case it is accessed again if img.shape[2] > 3: img = img[:, :, 0:3] vtexture = pyvista.numpy_to_texture(img) output.textures[name] = vtexture output._activate_texture(name) return output
def test_read_texture_from_numpy(): """"Test adding a texture to a plot""" globe = examples.load_globe() texture = pyvista.numpy_to_texture(imageio.imread(examples.mapfile)) plotter = pyvista.Plotter(off_screen=OFF_SCREEN) plotter.add_mesh(globe, texture=texture) plotter.show()
def test_read_texture_from_numpy(): """"Test adding a texture to a plot""" globe = examples.load_globe() texture = pyvista.numpy_to_texture(imageio.imread(examples.mapfile)) plotter = pyvista.Plotter() plotter.add_mesh(globe, texture=texture) plotter.show(before_close_callback=verify_cache_image)
def get_many_noisy_photos(mesh, movement, resolution, cmap, plotter, camera, title=None, title_location="upper_edge", background_photos=None, background_scale=1, title_color="black", cam_noise_lambda=None, texture_params=(255/2, 155, (1000, 1000, 3))): """ Take a photo of the mesh in a cerain position WITH GAUSSIAN TEXTURE all args in case for more then one mesh should be in list Args: mesh: the mesh to use movement: V side vector texture: the texture to use cmap: the colormap to use, used only if texture is not supplied plotter: the pyvista plotter, clear the mesh "get_photo" in the plotter camera: list of [camera position , focal point, view up] each (x,y,z) tuple resolution: the image resolution [w,h] background_photos: list of background photos to use in random texture_params: (mean, variance, shape) of the noisy texture Returns: An image shot from camera of the mesh """ to_return = np.zeros(shape=(len(camera), resolution[1], resolution[0], 4)) num_of_mesh = len(mesh) if background_photos: plotter.add_background_image(random.choice(background_photos), scale=background_scale) if cam_noise_lambda: cam_noise = np.zeros((len(camera), 3, 3)) cam_noise[:,0] += np.random.normal(0, cam_noise_lambda[0], (len(camera), 3)) cam_noise[:,1] += np.random.normal(0, cam_noise_lambda[1], (len(camera), 3)) cam_noise[:,2] += np.random.normal(0, cam_noise_lambda[2], (len(camera), 3)) camera = np.array(camera) + cam_noise if num_of_mesh == 1: mesh = [mesh] for i in range(num_of_mesh): tex = np.random.normal(texture_params[0], texture_params[1], texture_params[2]).astype(np.uint8) tex[np.where(tex > 255)] = 255 tex[np.where(tex < 0)] = 0 tex = pv.numpy_to_texture(tex) mesh[i].pv_mesh.texture_map_to_plane(inplace=True) plotter.add_mesh(mesh[i].pv_mesh, texture=tex, name='get_photo_mesh_' + str(i)) plotter.update_coordinates(movement[i], mesh=mesh[i].pv_mesh) if title: plotter.add_text(title, position=title_location, font_size=10, color=title_color, name="title", shadow=True) plotter.set_background(color="white") plotter.show(auto_close=False, window_size=resolution) for idx, cam in enumerate(camera): plotter.set_position(cam[0]) plotter.set_focus(cam[1]) plotter.set_viewup(cam[2]) depth = plotter.get_image_depth(fill_value=None) depth = np.abs(depth) screen = plotter.screenshot(window_size=resolution) screen = screen / 255 to_return[idx] = np.append(screen, depth.reshape(resolution[1], resolution[0], 1), axis=-1) if background_photos: plotter.remove_background_image() return np.asarray(to_return, np.float32)
def read_texture(filename, attrs=None): """Load a ``vtkTexture`` from an image file.""" filename = os.path.abspath(os.path.expanduser(filename)) try: # initialize the reader using the extension to find it reader = get_reader(filename) image = standard_reader_routine(reader, filename, attrs=attrs) return pyvista.image_to_texture(image) except KeyError: # Otherwise, use the imageio reader pass return pyvista.numpy_to_texture(imageio.imread(filename))
def draw_model(self, with_texture=False): if self.mode == RenderMode.image: self.mesh.points = self.model.vertices self.plotter.add_mesh(self.mesh, color=self.model_color) return self.plotter.image model_mesh = pv.PolyData(self.model.vertices, self.faces) if with_texture: model_mesh.t_coords = self.model.vertex_texture_coords texture = pv.numpy_to_texture(self.model.texture) model_mesh.textures[0] = texture return self._plot(model_mesh)
def animate(self, movement, f=None, index_col=0, index_row=0, texture=None, cmap='jet', plotter=None, title='', font_size=10, font_color='black', gif_path=None, camera=None): """ animate the mash using movement as movement metrix press "q" after adjusting the frame to start the animation Args: movement: tuple of V side vector as elements, (hull_movement,tip_movement) f: map between (x,y,z) of vertex to scalar for the color map index_row: chosen subplot row index_col: chosen subplot column texture: the texture to use cmap: the colormap to use plotter: the pyvista plotter title: the title of the figure font_size: the font size of the title font_color: the color of the font for the title gif_path: gif path to create, None if no gif is needed camera: the [camera position , focal point, view up] each (x,y,z) tuple Returns: None """ if not plotter: plotter = pv.Plotter() plotter.subplot(index_column=index_col, index_row=index_row) plotter.add_text(title, position="upper_edge", font_size=font_size, color=font_color) if camera is not None: # it gives .any() crushes without.. plotter.set_position(camera[0]) plotter.set_focus(camera[1]) plotter.set_viewup(camera[2]) if not texture: plotter.add_mesh(self.pv_mesh, scalars=f, cmap=cmap, texture=texture) else: if isinstance(texture, np.ndarray): tex = pv.numpy_to_texture(texture) else: tex = pv.read_texture(texture) self.pv_mesh.texture_map_to_plane(inplace=True) plotter.add_mesh(self.pv_mesh, texture=tex) plotter.show(auto_close=False) if gif_path: plotter.open_gif(gif_path) for item in movement: plotter.update_coordinates(item, mesh=self.pv_mesh) if gif_path: plotter.write_frame() plotter.close()
def read_texture(filename, attrs=None): """Load a ``vtkTexture`` from an image file.""" filename = os.path.abspath(os.path.expanduser(filename)) try: # initialize the reader using the extension to find it reader = get_reader(filename) image = standard_reader_routine(reader, filename, attrs=attrs) if image.n_points < 2: raise RuntimeError("Problem reading the image with VTK.") return pyvista.image_to_texture(image) except (KeyError, RuntimeError): # Otherwise, use the imageio reader pass import imageio return pyvista.numpy_to_texture(imageio.imread(filename))
def plot_faces(self, f=None, index_row=0, index_col=0, show=True, plotter=None, cmap='jet', title=None, title_location="upper_edge", font_size=10, font_color='black', texture=None, camera=None): """ plots the faces of the Mesh Args: f: map between (x,y,z) of vertex to scalar for the color map index_row: chosen subplot row index_col: chosen subplot column show: should the function call imshow() plotter: the pyvista plotter cmap: the color map to use title: the title of the figure title_location: title location font_size: the font size of the title font_color: the color of the font for the title texture: the filename for the texture of the figure or np array camera: the [camera position , focal point, view up] each (x,y,z) tuple Returns: the pyvista plotter """ if not plotter: plotter = pv.Plotter() plotter.subplot(index_column=index_col, index_row=index_row) if title: plotter.add_text(title, position=title_location, font_size=font_size, color=font_color) if camera is not None: plotter.set_position(camera[0]) plotter.set_focus(camera[1]) plotter.set_viewup(camera[2]) if self.texture: plotter.add_mesh(self.pv_mesh, texture=self.texture) elif texture is None: plotter.add_mesh(self.pv_mesh, scalars=f, cmap=cmap, texture=texture, show_scalar_bar=False) else: if isinstance(texture, np.ndarray): tex = pv.numpy_to_texture(texture) else: tex = pv.read_texture(texture) self.pv_mesh.texture_map_to_plane(inplace=True) plotter.add_mesh(self.pv_mesh, texture=tex) if show: plotter.show() return plotter
def plot_projection(self, normal=(1, 1, 1), index_row=0, index_col=0, show=True, texture=None, cmap="jet", f=None, plotter=None, title='', font_size=10, font_color='black'): """ plots the projection of the Mesh Args: normal: the normal of the projected image index_row: chosen subplot row index_col: chosen subplot column show: should the function call imshow() texture: the texture to use cmap: the color map to use f: the color for each vertex or face. plotter: the pyvista plotter title: the title of the figure font_size: the font size of the title font_color: the color of the font for the title Returns: the pyvista plotter """ if not plotter: plotter = pv.Plotter() plotter.subplot(index_column=index_col, index_row=index_row) plotter.add_text(title, position="upper_edge", font_size=font_size, color=font_color) tex = None if texture: if isinstance(texture, np.ndarray): tex = pv.numpy_to_texture(texture) else: tex = pv.read_texture(texture) self.pv_mesh.texture_map_to_plane(inplace=True) # plotter.add_mesh(pv_mesh, texture=tex) og = self.pv_mesh.center projected = self.pv_mesh.project_points_to_plane(origin=og, normal=normal) projected.texture_map_to_plane() plotter.add_mesh(projected, texture=tex) if show: plotter.show() return plotter
def DEM_to_vtk_withtexture(input_dem, input_sat=None, im_output='satellite.png', vtk_output='output.vtk', height_scale=1): # Import the DEM file as a 3D mesh data = xr.open_rasterio(input_dem) values = np.asarray(data) nans = values == data.nodatavals if np.any(nans): values[nans] = np.nan # Make a mesh xx, yy = np.meshgrid(data['x'], data['y']) zz = values.reshape(xx.shape) # will make z-comp the values in the file mesh = pv.StructuredGrid(xx, yy, height_scale*zz) mesh['Elevation'] = values.ravel(order='F') mesh = mesh.warp_by_scalar() # If there is a satellite image file then add texture coordinates to the mesh and save the image in the correct format if input_sat != None: ds = xr.open_rasterio(input_sat) # Fetch the texture as an image: moves the first axis to the end, e.g. (10,15,4) -> (4,10,15) image = np.moveaxis(ds.values, 0, -1) # Create the ground control points (GCPs) for texture mapping ***super important o = ds.x.min(), ds.y.min(), 0.0 # Bottom Left u = ds.x.max(), ds.y.min(), 0.0 # Bottom Right v = ds.x.min(), ds.y.max(), 0.0 # Top left # Note: Z-coordinate doesn't matter # Use the GCPs to map the tex coords mesh.texture_map_to_plane(o, u, v, inplace=True) mesh.textures["aerial"] = pv.numpy_to_texture(image) # save the texture as a png to use as texture in Paraview from PIL import Image im = Image.fromarray(image) im.save(im_output) mesh.save(vtk_output) # save as a vtk file return mesh
def __init__(self, parent, image, scale=1, view_port=None): """Initialize BackgroundRenderer with an image.""" # read the image first as we don't need to create a render if # the image path is invalid image_data = pyvista.numpy_to_texture(image).to_image() super().__init__(parent, border=False) self.SetLayer(0) self.InteractiveOff() self.SetBackground(self.parent.renderer.GetBackground()) self._scale = scale self._modified_observer = None self._prior_window_size = None if view_port is not None: self.SetViewport(view_port) # create image actor image_actor = vtk.vtkImageActor() image_actor.SetInputData(image_data) self.add_actor(image_actor, name='background') self.camera.ParallelProjectionOn() self.resize()
def animate_few_meshes(mesh, movement, f=None, subplot=(0, 0), texture=None, cmap='jet', plotter=None, title='', font_size=10, font_color='black', gif_path=None, camera=None, depth=False): """ animate few mashes using f as movment metrix. press "q" after adjusting the frame to start the animation Args: mesh: list of the meshes to plot movement: list of iterable with Vn side vector as elements for the num of vercies of the n-th mesh f: list of function that map between id of vertex to scalar for the color map subplot: list of subplots to use, each is a tuple in the form of: (row,col) texture: list of the textures to use cmap: list of the colormap to use plotter: the pyvista plotter title: the title of the figure font_size: the font size of the title font_color: the color of the font for the title gif_path: gif path to create, None if no gif is needed camera: list of the [camera position , focal point, view up] each (x,y,z) tuple Returns: None """ num_of_plots = len(mesh) if num_of_plots == 1: return mesh.animate(movement=movement, f=f, index_col=subplot[1], index_row=subplot[0], texture=texture, cmap=cmap, plotter=plotter, title=title, font_color=font_color, font_size=font_size, gif_path=gif_path, camera=camera) if not plotter: plotter = pv.Plotter() pv_mesh = [] # adding mushes with textures for idx in range(num_of_plots): plotter.subplot(subplot[idx][0], subplot[idx][1]) if depth: plotter.enable_depth_peeling(0) plotter.add_text(title[idx], position="upper_edge", font_size=font_size[idx], color=font_color[idx]) if camera[idx] is not None: plotter.set_position(camera[idx][0]) plotter.set_focus(camera[idx][1]) plotter.set_viewup(camera[idx][2]) pv_mesh.append(mesh[idx].pv_mesh) if not texture[idx]: plotter.add_mesh(pv_mesh[idx], scalars=f[idx], cmap=cmap[idx], texture=texture[idx]) else: if isinstance(texture[idx], np.ndarray): tex = pv.numpy_to_texture(texture[idx]) else: tex = pv.read_texture(texture[idx]) pv_mesh[idx].texture_map_to_plane(inplace=True) plotter.add_mesh(pv_mesh[idx], texture=tex) # starting the animation plotter.show(auto_close=False) if gif_path: plotter.open_gif(gif_path) for frame, item in enumerate(movement[0]): for plt_id in range(num_of_plots): plotter.update_coordinates(movement[plt_id][frame], mesh=pv_mesh[plt_id]) if gif_path: plotter.write_frame() plotter.close()
# :func:`pyvista.numpy_to_texture`. # create an image using numpy, xx, yy = np.meshgrid(np.linspace(-200, 200, 20), np.linspace(-200, 200, 20)) A, b = 500, 100 zz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0)) # Creating a custom RGB image cmap = get_cmap("nipy_spectral") norm = lambda x: (x - np.nanmin(x)) / (np.nanmax(x) - np.nanmin(x)) hue = norm(zz.ravel()) colors = (cmap(hue)[:, 0:3] * 255.0).astype(np.uint8) image = colors.reshape((xx.shape[0], xx.shape[1], 3), order="F") # Convert 3D numpy array to texture tex = pv.numpy_to_texture(image) # Render it! curvsurf.plot(texture=tex) ############################################################################### # Textures with Transparency # ++++++++++++++++++++++++++ # # Textures can also specify per-pixel opacity values. The image must # contain a 4th channel specifying the opacity value from 0 [transparent] to # 255 [fully visible]. To enable this feature just pass the opacity array as the # 4th channel of the image as a 3 dimensional matrix with shape [nrows, ncols, 4] # :func:`pyvista.numpy_to_texture`. # # Here we can download an image that has an alpha channel:
# Open the GeoTIFF url = "https://dl.dropbox.com/s/pqgme8qsl95u9un/Sio020320_transparent_mosaic_group1.tif?dl=0" path, _ = examples.downloads._retrieve_file( url, "Sio020320_transparent_mosaic_group1.tif.csv") ds = xr.open_rasterio(path) # Fetch the texture as an image image = np.moveaxis(ds.values, 0, -1) # Create the ground control points for texture mapping o = ds.x.min(), ds.y.min(), 0.0 # Bottom Left u = ds.x.max(), ds.y.min(), 0.0 # Bottom Right v = ds.x.min(), ds.y.max(), 0.0 # Lop left # Note: Z-coordinate doesn't matter ############################################################################### # Use the GCPs to map the tex coords mapped_surf = surf.texture_map_to_plane(o, u, v) # Associate the texture with the mapped mesh mapped_surf.textures["aerial"] = pv.numpy_to_texture(image) ############################################################################### # Plot it up in 3D and enjoy! cpos = [ (469735.37431312964, 1321523.2987377762, 5242.9129552423465), (469928.4268006842, 1321916.1316302174, 5171.6505267522025), (0.08372003361058433, 0.13788753708579846, 0.986903228836878), ] mapped_surf.plot(texture="aerial", cpos=cpos)