| import matplotlib.pyplot as plt |
|
|
| from ipywidgets import interact |
| import numpy as np |
| import SimpleITK as sitk |
| import cv2 |
|
|
| def explore_3D_array(arr: np.ndarray, cmap: str = 'gray'): |
| """ |
| Given a 3D array with shape (Z,X,Y) This function will create an interactive |
| widget to check out all the 2D arrays with shape (X,Y) inside the 3D array. |
| The purpose of this function to visual inspect the 2D arrays in the image. |
| |
| Args: |
| arr : 3D array with shape (Z,X,Y) that represents the volume of a MRI image |
| cmap : Which color map use to plot the slices in matplotlib.pyplot |
| """ |
|
|
| def fn(SLICE): |
| plt.figure(figsize=(7,7)) |
| plt.imshow(arr[SLICE, :, :], cmap=cmap) |
|
|
| interact(fn, SLICE=(0, arr.shape[0]-1)) |
|
|
|
|
| def explore_3D_array_comparison(arr_before: np.ndarray, arr_after: np.ndarray, cmap: str = 'gray'): |
| """ |
| Given two 3D arrays with shape (Z,X,Y) This function will create an interactive |
| widget to check out all the 2D arrays with shape (X,Y) inside the 3D arrays. |
| The purpose of this function to visual compare the 2D arrays after some transformation. |
| |
| Args: |
| arr_before : 3D array with shape (Z,X,Y) that represents the volume of a MRI image, before any transform |
| arr_after : 3D array with shape (Z,X,Y) that represents the volume of a MRI image, after some transform |
| cmap : Which color map use to plot the slices in matplotlib.pyplot |
| """ |
|
|
| assert arr_after.shape == arr_before.shape |
|
|
| def fn(SLICE): |
| fig, (ax1, ax2) = plt.subplots(1, 2, sharex='col', sharey='row', figsize=(10,10)) |
|
|
| ax1.set_title('Before', fontsize=15) |
| ax1.imshow(arr_before[SLICE, :, :], cmap=cmap) |
|
|
| ax2.set_title('After', fontsize=15) |
| ax2.imshow(arr_after[SLICE, :, :], cmap=cmap) |
|
|
| plt.tight_layout() |
| |
| interact(fn, SLICE=(0, arr_before.shape[0]-1)) |
|
|
|
|
| def show_sitk_img_info(img: sitk.Image): |
| """ |
| Given a sitk.Image instance prints the information about the MRI image contained. |
| |
| Args: |
| img : instance of the sitk.Image to check out |
| """ |
| pixel_type = img.GetPixelIDTypeAsString() |
| origin = img.GetOrigin() |
| dimensions = img.GetSize() |
| spacing = img.GetSpacing() |
| direction = img.GetDirection() |
|
|
| info = {'Pixel Type' : pixel_type, 'Dimensions': dimensions, 'Spacing': spacing, 'Origin': origin, 'Direction' : direction} |
| for k,v in info.items(): |
| print(f' {k} : {v}') |
|
|
|
|
| def add_suffix_to_filename(filename: str, suffix:str) -> str: |
| """ |
| Takes a NIfTI filename and appends a suffix. |
| |
| Args: |
| filename : NIfTI filename |
| suffix : suffix to append |
| |
| Returns: |
| str : filename after append the suffix |
| """ |
| if filename.endswith('.nii'): |
| result = filename.replace('.nii', f'_{suffix}.nii') |
| return result |
| elif filename.endswith('.nii.gz'): |
| result = filename.replace('.nii.gz', f'_{suffix}.nii.gz') |
| return result |
| else: |
| raise RuntimeError('filename with unknown extension') |
|
|
|
|
| def rescale_linear(array: np.ndarray, new_min: int, new_max: int): |
| """Rescale an array linearly.""" |
| minimum, maximum = np.min(array), np.max(array) |
| m = (new_max - new_min) / (maximum - minimum) |
| b = new_min - m * minimum |
| return m * array + b |
|
|
|
|
| def explore_3D_array_with_mask_contour(arr: np.ndarray, mask: np.ndarray, thickness: int = 1): |
| """ |
| Given a 3D array with shape (Z,X,Y) This function will create an interactive |
| widget to check out all the 2D arrays with shape (X,Y) inside the 3D array. The binary |
| mask provided will be used to overlay contours of the region of interest over the |
| array. The purpose of this function is to visual inspect the region delimited by the mask. |
| |
| Args: |
| arr : 3D array with shape (Z,X,Y) that represents the volume of a MRI image |
| mask : binary mask to obtain the region of interest |
| """ |
| assert arr.shape == mask.shape |
| |
| _arr = rescale_linear(arr,0,1) |
| _mask = rescale_linear(mask,0,1) |
| _mask = _mask.astype(np.uint8) |
|
|
| def fn(SLICE): |
| arr_rgb = cv2.cvtColor(_arr[SLICE, :, :], cv2.COLOR_GRAY2RGB) |
| contours, _ = cv2.findContours(_mask[SLICE, :, :], cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
| |
| arr_with_contours = cv2.drawContours(arr_rgb, contours, -1, (0,1,0), thickness) |
|
|
| plt.figure(figsize=(7,7)) |
| plt.imshow(arr_with_contours) |
|
|
| interact(fn, SLICE=(0, arr.shape[0]-1)) |