def numpy_to_vtk_cells(data, is_coords=True): """Convert numpy array to a vtk cell array. Parameters ---------- data : ndarray points coordinate or connectivity array (e.g triangles). is_coords : ndarray Select the type of array. default: True. Returns ------- vtk_cell : vtkCellArray connectivity + offset information """ data = np.array(data, dtype=object) nb_cells = len(data) # Get lines_array in vtk input format connectivity = data.flatten() if not is_coords else [] offset = [0, ] current_position = 0 cell_array = CellArray() if VTK_9_PLUS: for i in range(nb_cells): current_len = len(data[i]) offset.append(offset[-1] + current_len) if is_coords: end_position = current_position + current_len connectivity += list(range(current_position, end_position)) current_position = end_position connectivity = np.array(connectivity, np.intp) offset = np.array(offset, dtype=connectivity.dtype) vtk_array_type = numpy_support.get_vtk_array_type(connectivity.dtype) cell_array.SetData( numpy_support.numpy_to_vtk(offset, deep=True, array_type=vtk_array_type), numpy_support.numpy_to_vtk(connectivity, deep=True, array_type=vtk_array_type)) else: for i in range(nb_cells): current_len = len(data[i]) end_position = current_position + current_len connectivity += [current_len] connectivity += list(range(current_position, end_position)) current_position = end_position connectivity = np.array(connectivity) cell_array.GetData().DeepCopy(numpy_support.numpy_to_vtk(connectivity)) cell_array.SetNumberOfCells(nb_cells) return cell_array
def _points_to_vtk_cells(points, points_per_line=2): """ Returns the VTK cell array for the peaks given the set of points coordinates. Parameters ---------- points : (N, 3) array or ndarray points coordinates array. points_per_line : int (1 or 2), optional number of points per peak direction. Returns ------- cell_array : vtkCellArray connectivity + offset information. """ num_pnts = len(points) num_cells = num_pnts // points_per_line cell_array = CellArray() """ Connectivity is an array that contains the indices of the points that need to be connected in the visualization. The indices start from 0. """ connectivity = np.asarray(list(range(0, num_pnts)), dtype=int) """ Offset is an array that contains the indices of the first point of each line. The indices start from 0 and given the known geometry of this actor the creation of this array requires a 2 points padding between indices. """ offset = np.asarray(list(range(0, num_pnts + 1, points_per_line)), dtype=int) vtk_array_type = numpy_support.get_vtk_array_type(connectivity.dtype) cell_array.SetData( numpy_support.numpy_to_vtk(offset, deep=True, array_type=vtk_array_type), numpy_support.numpy_to_vtk(connectivity, deep=True, array_type=vtk_array_type)) cell_array.SetNumberOfCells(num_cells) return cell_array
def numpy_to_vtk_image_data(array, spacing=(1.0, 1.0, 1.0), origin=(0.0, 0.0, 0.0), deep=True): """Convert numpy array to a vtk image data. Parameters ---------- array : ndarray pixel coordinate and colors values. spacing : (float, float, float) (optional) sets the size of voxel (unit of space in each direction x,y,z) origin : (float, float, float) (optional) sets the origin at the given point deep : bool (optional) decides the type of copy(ie. deep or shallow) Returns ------- vtk_image : vtkImageData """ if array.ndim not in [2, 3]: raise IOError("only 2D (L, RGB, RGBA) or 3D image available") vtk_image = ImageData() depth = 1 if array.ndim == 2 else array.shape[2] vtk_image.SetDimensions(array.shape[1], array.shape[0], depth) vtk_image.SetExtent(0, array.shape[1] - 1, 0, array.shape[0] - 1, 0, 0) vtk_image.SetSpacing(spacing) vtk_image.SetOrigin(origin) temp_arr = np.flipud(array) temp_arr = temp_arr.reshape(array.shape[1] * array.shape[0], depth) temp_arr = np.ascontiguousarray(temp_arr, dtype=array.dtype) vtk_array_type = numpy_support.get_vtk_array_type(array.dtype) uchar_array = numpy_support.numpy_to_vtk(temp_arr, deep=deep, array_type=vtk_array_type) vtk_image.GetPointData().SetScalars(uchar_array) return vtk_image
def load_image(filename, as_vtktype=False, use_pillow=True): """Load an image. Parameters ---------- filename: str should be png, bmp, jpeg or jpg files as_vtktype: bool, optional if True, return vtk output otherwise an ndarray. Default False. use_pillow: bool, optional Use pillow python library to load the files. Default True Returns ------- image: ndarray or vtk output desired image array """ is_url = filename.lower().startswith('http://') \ or filename.lower().startswith('https://') if is_url: image_name = os.path.basename(filename) if len(image_name.split('.')) < 2: raise IOError(f'{filename} is not a valid image URL') urlretrieve(filename, image_name) filename = image_name if use_pillow: with Image.open(filename) as pil_image: if pil_image.mode in ['RGBA', 'RGB', 'L']: image = np.asarray(pil_image) elif pil_image.mode.startswith('I;16'): raw = pil_image.tobytes('raw', pil_image.mode) dtype = '>u2' if pil_image.mode.endswith('B') else '<u2' image = np.frombuffer(raw, dtype=dtype) image.reshape(pil_image.size[::-1]).astype('=u2') else: try: image = pil_image.convert('RGBA') except ValueError: raise RuntimeError('Unknown image mode {}'.format( pil_image.mode)) image = np.asarray(pil_image) image = np.flipud(image) if as_vtktype: if image.ndim not in [2, 3]: raise IOError("only 2D (L, RGB, RGBA) or 3D image available") vtk_image = ImageData() depth = 1 if image.ndim == 2 else image.shape[2] # width, height vtk_image.SetDimensions(image.shape[1], image.shape[0], depth) vtk_image.SetExtent(0, image.shape[1] - 1, 0, image.shape[0] - 1, 0, 0) vtk_image.SetSpacing(1.0, 1.0, 1.0) vtk_image.SetOrigin(0.0, 0.0, 0.0) image = image.reshape(image.shape[1] * image.shape[0], depth) image = np.ascontiguousarray(image, dtype=image.dtype) vtk_array_type = numpy_support.get_vtk_array_type(image.dtype) uchar_array = numpy_support.numpy_to_vtk(image, deep=True, array_type=vtk_array_type) vtk_image.GetPointData().SetScalars(uchar_array) image = vtk_image if is_url: os.remove(filename) return image d_reader = { ".png": PNGReader, ".bmp": BMPReader, ".jpeg": JPEGReader, ".jpg": JPEGReader, ".tiff": TIFFReader, ".tif": TIFFReader } extension = os.path.splitext(os.path.basename(filename).lower())[1] if extension.lower() not in d_reader.keys(): raise IOError( "Impossible to read the file {0}: Unknown extension {1}".format( filename, extension)) reader = d_reader.get(extension)() reader.SetFileName(filename) reader.Update() reader.GetOutput().GetPointData().GetArray(0).SetName("original") if not as_vtktype: w, h, _ = reader.GetOutput().GetDimensions() vtk_array = reader.GetOutput().GetPointData().GetScalars() components = vtk_array.GetNumberOfComponents() image = numpy_support.vtk_to_numpy(vtk_array).reshape(h, w, components) if is_url: os.remove(filename) return reader.GetOutput() if as_vtktype else image
def save_image(arr, filename, compression_quality=75, compression_type='deflation', use_pillow=True): """Save a 2d or 3d image. Expect an image with the following shape: (H, W) or (H, W, 1) or (H, W, 3) or (H, W, 4). Parameters ---------- arr : ndarray array to save filename : string should be png, bmp, jpeg or jpg files compression_quality : int, optional compression_quality for jpeg data. 0 = Low quality, 100 = High quality compression_type : str, optional compression type for tiff file select between: None, lzw, deflation (default) use_pillow : bool, optional Use imageio python library to save the files. """ if arr.ndim > 3: raise IOError("Image Dimensions should be <=3") d_writer = { ".png": PNGWriter, ".bmp": BMPWriter, ".jpeg": JPEGWriter, ".jpg": JPEGWriter, ".tiff": TIFFWriter, ".tif": TIFFWriter, } extension = os.path.splitext(os.path.basename(filename).lower())[1] if extension.lower() not in d_writer.keys(): raise IOError( "Impossible to save the file {0}: Unknown extension {1}".format( filename, extension)) if use_pillow: arr = np.flipud(arr) im = Image.fromarray(arr) im.save(filename, quality=compression_quality) return if arr.ndim == 2: arr = arr[..., None] shape = arr.shape if extension.lower() in [ '.png', ]: arr = arr.astype(np.uint8) arr = arr.reshape((shape[1] * shape[0], shape[2])) arr = np.ascontiguousarray(arr, dtype=arr.dtype) vtk_array_type = numpy_support.get_vtk_array_type(arr.dtype) vtk_array = numpy_support.numpy_to_vtk(num_array=arr, deep=True, array_type=vtk_array_type) # Todo, look the following link for managing png 16bit # https://stackoverflow.com/questions/15667947/vtkpngwriter-printing-out-black-images vtk_data = ImageData() vtk_data.SetDimensions(shape[1], shape[0], shape[2]) vtk_data.SetExtent(0, shape[1] - 1, 0, shape[0] - 1, 0, 0) vtk_data.SetSpacing(1.0, 1.0, 1.0) vtk_data.SetOrigin(0.0, 0.0, 0.0) vtk_data.GetPointData().SetScalars(vtk_array) writer = d_writer.get(extension)() writer.SetFileName(filename) writer.SetInputData(vtk_data) if extension.lower() in [".jpg", ".jpeg"]: writer.ProgressiveOn() writer.SetQuality(compression_quality) if extension.lower() in [".tif", ".tiff"]: compression_type = compression_type or 'nocompression' l_compression = ['nocompression', 'packbits', 'jpeg', 'deflate', 'lzw'] if compression_type.lower() in l_compression: comp_id = l_compression.index(compression_type.lower()) writer.SetCompression(comp_id) else: writer.SetCompressionToDeflate() writer.Write()
def _points_to_vtk_cells(points, points_per_line=2): """ Returns the VTK cell array for the peaks given the set of points coordinates. Parameters ---------- points : (N, 3) array or ndarray points coordinates array. points_per_line : int (1 or 2), optional number of points per peak direction. Returns ------- cell_array : vtkCellArray connectivity + offset information. """ num_pnts = len(points) num_cells = num_pnts // points_per_line cell_array = CellArray() if VTK_9_PLUS: """ Connectivity is an array that contains the indices of the points that need to be connected in the visualization. The indices start from 0. """ connectivity = np.asarray(list(range(0, num_pnts)), dtype=int) """ Offset is an array that contains the indices of the first point of each line. The indices start from 0 and given the known geometry of this actor the creation of this array requires a 2 points padding between indices. """ offset = np.asarray(list(range(0, num_pnts + 1, points_per_line)), dtype=int) vtk_array_type = numpy_support.get_vtk_array_type(connectivity.dtype) cell_array.SetData( numpy_support.numpy_to_vtk(offset, deep=True, array_type=vtk_array_type), numpy_support.numpy_to_vtk(connectivity, deep=True, array_type=vtk_array_type)) else: connectivity = np.array([], dtype=int) i_pos = 0 while i_pos < num_pnts: e_pos = i_pos + points_per_line """ In old versions of VTK (<9.0) the connectivity array should include the length of each line and immediately after the indices of the points in each line. """ connectivity = np.append(connectivity, [points_per_line, i_pos, e_pos - 1]) i_pos = e_pos cell_array.GetData().DeepCopy(numpy_support.numpy_to_vtk(connectivity)) cell_array.SetNumberOfCells(num_cells) return cell_array