def mesh_to_image(meshes: list, reference_image: itk.Image = None) -> itk.Image: # Allow single mesh as input if type(meshes) != list: meshes = [meshes] mesh_type = type(meshes[0]) pixel_type, dimension = itk.template(mesh_type)[1] image_type = itk.Image[pixel_type, dimension] mesh_to_image_filter_type = itk.TriangleMeshToBinaryImageFilter[mesh_type, image_type] images = list() if not reference_image: # Set bounds to largest region encompassing all meshes # Bounds format: [x_min x_max y_min y_max z_min z_max] bounds = meshes[0].GetBoundingBox().GetBounds() for mesh in meshes[1:]: mesh_bounds = mesh.GetBoundingBox().GetBounds() for dim in range(0, dimension): bounds[dim * 2] = min(bounds[dim * 2], mesh_bounds[dim * 2]) bounds[(dim * 2) + 1] = max(bounds[(dim * 2) + 1], mesh_bounds[(dim * 2) + 1]) # Calculate spacing, origin, and size with 5 pixel buffer around mesh spacing = ((bounds[1] - bounds[0]) / 90, (bounds[3] - bounds[2]) / 90, (bounds[5] - bounds[4]) / 90) origin = (bounds[0] - 5 * spacing[0], bounds[2] - 5 * spacing[1], bounds[4] - 5 * spacing[2]) size = (100, 100, 100) direction = itk.Matrix[itk.D, dimension, dimension].GetIdentity() else: # Use given parameters origin = reference_image.GetOrigin() spacing = reference_image.GetSpacing() size = reference_image.GetLargestPossibleRegion().GetSize() direction = reference_image.GetDirection() # Generate image for each mesh for mesh in meshes: mesh_to_image_filter = mesh_to_image_filter_type.New( Input=mesh, Origin=origin, Spacing=spacing, Size=size, Direction=direction) mesh_to_image_filter.Update() distance = itk.signed_maurer_distance_map_image_filter( mesh_to_image_filter.GetOutput()) images.append(distance) return images[0] if len(images) == 1 else images
def _get_meta_dict(self, img: Image) -> Dict: """ Get all the meta data of the image and convert to dict type. Args: img: a ITK image object loaded from a image file. """ img_meta_dict = img.GetMetaDataDictionary() meta_dict = dict() for key in img_meta_dict.GetKeys(): # ignore deprecated, legacy members that cause issues if key.startswith("ITK_original_"): continue meta_dict[key] = img_meta_dict[key] meta_dict["origin"] = np.asarray(img.GetOrigin()) meta_dict["spacing"] = np.asarray(img.GetSpacing()) meta_dict["direction"] = itk.array_from_matrix(img.GetDirection()) return meta_dict
def _get_affine(self, img: Image) -> np.ndarray: """ Get or construct the affine matrix of the image, it can be used to correct spacing, orientation or execute spatial transforms. Construct Affine matrix based on direction, spacing, origin information. Refer to: https://github.com/RSIP-Vision/medio Args: img: a ITK image object loaded from a image file. """ direction = itk.array_from_matrix(img.GetDirection()) spacing = np.asarray(img.GetSpacing()) origin = np.asarray(img.GetOrigin()) direction = np.asarray(direction) affine = np.eye(direction.shape[0] + 1) affine[(slice(-1), slice(-1))] = direction @ np.diag(spacing) affine[(slice(-1), -1)] = origin return affine