def test_label_clusters_example(self): image = ants.image_read(ants.get_ants_data('r16')) timageFully = ants.label_clusters(image, 10, 128, 150, True) timageFace = ants.label_clusters(image, 10, 128, 150, False)
def test_get_centroids_example(self): image = ants.image_read(ants.get_ants_data("r16")) image = ants.threshold_image(image, 90, 120) image = ants.label_clusters(image, 10) cents = ants.get_centroids(image)
# Create initial segmentation image print(" Initial step 6: prediction.") start_time = time.time() data_initial_stage = image_resampled.numpy() data_initial_stage = np.expand_dims(data_initial_stage, 0) data_initial_stage = np.expand_dims(data_initial_stage, -1) prediction_initial_stage = np.squeeze( model_initial_stage.predict(data_initial_stage)) prediction_initial_stage[np.where(prediction_initial_stage >= 0.5)] = 1 prediction_initial_stage[np.where(prediction_initial_stage < 0.5)] = 0 mask_initial_stage = ants.from_numpy(prediction_initial_stage, origin=image_resampled.origin, spacing=image_resampled.spacing, direction=image_resampled.direction) mask_initial_stage = ants.label_clusters(mask_initial_stage, min_cluster_size=10) mask_initial_stage = ants.threshold_image(mask_initial_stage, 1, 2, 1, 0) mask_initial_stage_original_space = ants.resample_image( mask_initial_stage, image_n4.shape, True, 1) end_time = time.time() elapsed_time = end_time - start_time print(" (elapsed time: ", elapsed_time, " seconds)") ######################################### # # Perform initial (stage 2) segmentation # print("") print("") print("************* Refine stage segmentation ***************")
image_n4 = ants.image_math(image_n4, 'Normalize') * 255.0 print("Preprocessing: thresholding") image_n4_array = ((image_n4.numpy()).flatten()) image_n4_nonzero = image_n4_array[(image_n4_array > 0).nonzero()] image_robust_range = np.quantile(image_n4_nonzero, (0.02, 0.98)) threshold_value = 0.10 * (image_robust_range[1] - image_robust_range[0]) + image_robust_range[0] thresholded_mask = ants.threshold_image(image_n4, -10000, threshold_value, 0, 1) thresholded_image = image_n4 * thresholded_mask print("Preprocessing: resampling") image_resampled = ants.resample_image(thresholded_image, (256, 256, 256), True) batchX = np.expand_dims(image_resampled.numpy(), axis=0) batchX = np.expand_dims(batchX, axis=-1) print("Prediction and write to disk.") brain_mask_array = model.predict(batchX, verbose=0) brain_mask_resampled = ants.from_numpy(np.squeeze(brain_mask_array[0, :, :, :, 0]), origin=image_resampled.origin, spacing=image_resampled.spacing, direction=image_resampled.direction) brain_mask_image = ants.resample_image(brain_mask_resampled, image.shape, True, 1) minimum_brain_volume = round(649933.7) brain_mask_labeled = ants.label_clusters(brain_mask_image, minimum_brain_volume) ants.image_write(brain_mask_labeled, "brain_mask.nii.gz")
def hippmapp3r_segmentation(t1, do_preprocessing=True, antsxnet_cache_directory=None, verbose=False): """ Perform HippMapp3r (hippocampal) segmentation described in https://www.ncbi.nlm.nih.gov/pubmed/31609046 with models and architecture ported from https://github.com/mgoubran/HippMapp3r Additional documentation and attribution resources found at https://hippmapp3r.readthedocs.io/en/latest/ Preprocessing consists of: * n4 bias correction and * brain extraction The input T1 should undergo the same steps. If the input T1 is the raw T1, these steps can be performed by the internal preprocessing, i.e. set do_preprocessing = True Arguments --------- t1 : ANTsImage input image do_preprocessing : boolean See description above. antsxnet_cache_directory : string Destination directory for storing the downloaded template and model weights. Since these can be resused, if is None, these data will be downloaded to a ~/.keras/ANTsXNet/. verbose : boolean Print progress to the screen. Returns ------- ANTs labeled hippocampal image. Example ------- >>> mask = hippmapp3r_segmentation(t1) """ from ..architectures import create_hippmapp3r_unet_model_3d from ..utilities import preprocess_brain_image from ..utilities import get_pretrained_network from ..utilities import get_antsxnet_data if t1.dimension != 3: raise ValueError("Image dimension must be 3.") if antsxnet_cache_directory == None: antsxnet_cache_directory = "ANTsXNet" if verbose == True: print("************* Preprocessing ***************") print("") t1_preprocessed = t1 if do_preprocessing == True: t1_preprocessing = preprocess_brain_image( t1, truncate_intensity=None, brain_extraction_modality="t1", template=None, do_bias_correction=True, do_denoising=False, antsxnet_cache_directory=antsxnet_cache_directory, verbose=verbose) t1_preprocessed = t1_preprocessing[ "preprocessed_image"] * t1_preprocessing['brain_mask'] if verbose == True: print("************* Initial stage segmentation ***************") print("") # Normalize to mprage_hippmapp3r space if verbose == True: print(" HippMapp3r: template normalization.") template_file_name_path = get_antsxnet_data( "mprage_hippmapp3r", antsxnet_cache_directory=antsxnet_cache_directory) template_image = ants.image_read(template_file_name_path) registration = ants.registration( fixed=template_image, moving=t1_preprocessed, type_of_transform="antsRegistrationSyNQuickRepro[t]", verbose=verbose) image = registration['warpedmovout'] transforms = dict(fwdtransforms=registration['fwdtransforms'], invtransforms=registration['invtransforms']) # Threshold at 10th percentile of non-zero voxels in "robust range (fslmaths)" if verbose == True: print(" HippMapp3r: threshold.") image_array = image.numpy() image_robust_range = np.quantile(image_array[np.where(image_array != 0)], (0.02, 0.98)) threshold_value = 0.10 * (image_robust_range[1] - image_robust_range[0]) + image_robust_range[0] thresholded_mask = ants.threshold_image(image, -10000, threshold_value, 0, 1) thresholded_image = image * thresholded_mask # Standardize image if verbose == True: print(" HippMapp3r: standardize.") mean_image = np.mean(thresholded_image[thresholded_mask == 1]) sd_image = np.std(thresholded_image[thresholded_mask == 1]) image_normalized = (image - mean_image) / sd_image image_normalized = image_normalized * thresholded_mask # Trim and resample image if verbose == True: print(" HippMapp3r: trim and resample to (160, 160, 128).") image_cropped = ants.crop_image(image_normalized, thresholded_mask, 1) shape_initial_stage = (160, 160, 128) image_resampled = ants.resample_image(image_cropped, shape_initial_stage, use_voxels=True, interp_type=1) if verbose == True: print(" HippMapp3r: generate first network and download weights.") model_initial_stage = create_hippmapp3r_unet_model_3d( (*shape_initial_stage, 1), do_first_network=True) initial_stage_weights_file_name = get_pretrained_network( "hippMapp3rInitial", antsxnet_cache_directory=antsxnet_cache_directory) model_initial_stage.load_weights(initial_stage_weights_file_name) if verbose == True: print(" HippMapp3r: prediction.") data_initial_stage = np.expand_dims(image_resampled.numpy(), axis=0) data_initial_stage = np.expand_dims(data_initial_stage, axis=-1) mask_array = model_initial_stage.predict(data_initial_stage, verbose=verbose) mask_image_resampled = ants.copy_image_info( image_resampled, ants.from_numpy(np.squeeze(mask_array))) mask_image = ants.resample_image(mask_image_resampled, image.shape, use_voxels=True, interp_type=0) mask_image[mask_image >= 0.5] = 1 mask_image[mask_image < 0.5] = 0 ######################################### # # Perform refined (stage 2) segmentation # if verbose == True: print("") print("") print("************* Refine stage segmentation ***************") print("") mask_array = np.squeeze(mask_array) centroid_indices = np.where(mask_array == 1) centroid = np.zeros((3, )) centroid[0] = centroid_indices[0].mean() centroid[1] = centroid_indices[1].mean() centroid[2] = centroid_indices[2].mean() shape_refine_stage = (112, 112, 64) lower = (np.floor(centroid - 0.5 * np.array(shape_refine_stage)) - 1).astype(int) upper = (lower + np.array(shape_refine_stage)).astype(int) image_trimmed = ants.crop_indices(image_resampled, lower.astype(int), upper.astype(int)) if verbose == True: print(" HippMapp3r: generate second network and download weights.") model_refine_stage = create_hippmapp3r_unet_model_3d( (*shape_refine_stage, 1), do_first_network=False) refine_stage_weights_file_name = get_pretrained_network( "hippMapp3rRefine", antsxnet_cache_directory=antsxnet_cache_directory) model_refine_stage.load_weights(refine_stage_weights_file_name) data_refine_stage = np.expand_dims(image_trimmed.numpy(), axis=0) data_refine_stage = np.expand_dims(data_refine_stage, axis=-1) if verbose == True: print(" HippMapp3r: Monte Carlo iterations (SpatialDropout).") number_of_mci_iterations = 30 prediction_refine_stage = np.zeros(shape_refine_stage) for i in range(number_of_mci_iterations): tf.random.set_seed(i) if verbose == True: print(" Monte Carlo iteration", i + 1, "out of", number_of_mci_iterations) prediction_refine_stage = \ (np.squeeze(model_refine_stage.predict(data_refine_stage, verbose=verbose)) + \ i * prediction_refine_stage ) / (i + 1) prediction_refine_stage_array = np.zeros(image_resampled.shape) prediction_refine_stage_array[lower[0]:upper[0], lower[1]:upper[1], lower[2]:upper[2]] = prediction_refine_stage probability_mask_refine_stage_resampled = ants.copy_image_info( image_resampled, ants.from_numpy(prediction_refine_stage_array)) segmentation_image_resampled = ants.label_clusters(ants.threshold_image( probability_mask_refine_stage_resampled, 0.0, 0.5, 0, 1), min_cluster_size=10) segmentation_image_resampled[segmentation_image_resampled > 2] = 0 geom = ants.label_geometry_measures(segmentation_image_resampled) if len(geom['VolumeInMillimeters']) < 2: raise ValueError("Error: left and right hippocampus not found.") if geom['Centroid_x'][0] < geom['Centroid_x'][1]: segmentation_image_resampled[segmentation_image_resampled == 1] = 3 segmentation_image_resampled[segmentation_image_resampled == 2] = 1 segmentation_image_resampled[segmentation_image_resampled == 3] = 2 segmentation_image = ants.apply_transforms( fixed=t1, moving=segmentation_image_resampled, transformlist=transforms['invtransforms'], whichtoinvert=[True], interpolator="genericLabel", verbose=verbose) return (segmentation_image)
def brain_extraction(image, modality="t1", antsxnet_cache_directory=None, verbose=False): """ Perform brain extraction using U-net and ANTs-based training data. "NoBrainer" is also possible where brain extraction uses U-net and FreeSurfer training data ported from the https://github.com/neuronets/nobrainer-models Arguments --------- image : ANTsImage input image (or list of images for multi-modal scenarios). modality : string Modality image type. Options include: * "t1": T1-weighted MRI---ANTs-trained. Update from "t1v0". * "t1v0": T1-weighted MRI---ANTs-trained. * "t1nobrainer": T1-weighted MRI---FreeSurfer-trained: h/t Satra Ghosh and Jakub Kaczmarzyk. * "t1combined": Brian's combination of "t1" and "t1nobrainer". One can also specify "t1combined[X]" where X is the morphological radius. X = 12 by default. * "flair": FLAIR MRI. * "t2": T2 MRI. * "bold": 3-D BOLD MRI. * "fa": Fractional anisotropy. * "t1t2infant": Combined T1-w/T2-w infant MRI h/t Martin Styner. * "t1infant": T1-w infant MRI h/t Martin Styner. * "t2infant": T2-w infant MRI h/t Martin Styner. antsxnet_cache_directory : string Destination directory for storing the downloaded template and model weights. Since these can be resused, if is None, these data will be downloaded to a ~/.keras/ANTsXNet/. verbose : boolean Print progress to the screen. Returns ------- ANTs probability brain mask image. Example ------- >>> probability_brain_mask = brain_extraction(brain_image, modality="t1") """ from ..architectures import create_unet_model_3d from ..utilities import get_pretrained_network from ..utilities import get_antsxnet_data from ..architectures import create_nobrainer_unet_model_3d classes = ("background", "brain") number_of_classification_labels = len(classes) channel_size = 1 if isinstance(image, list): channel_size = len(image) if antsxnet_cache_directory == None: antsxnet_cache_directory = "ANTsXNet" input_images = list() if channel_size == 1: input_images.append(image) else: input_images = image if input_images[0].dimension != 3: raise ValueError("Image dimension must be 3.") if "t1combined" in modality: brain_extraction_t1 = brain_extraction( image, modality="t1", antsxnet_cache_directory=antsxnet_cache_directory, verbose=verbose) brain_mask = ants.iMath_get_largest_component( ants.threshold_image(brain_extraction_t1, 0.5, 10000)) # Need to change with voxel resolution morphological_radius = 12 if '[' in modality and ']' in modality: morphological_radius = int(modality.split("[")[1].split("]")[0]) brain_extraction_t1nobrainer = brain_extraction( image * ants.iMath_MD(brain_mask, radius=morphological_radius), modality="t1nobrainer", antsxnet_cache_directory=antsxnet_cache_directory, verbose=verbose) brain_extraction_combined = ants.iMath_fill_holes( ants.iMath_get_largest_component(brain_extraction_t1nobrainer * brain_mask)) brain_extraction_combined = brain_extraction_combined + ants.iMath_ME( brain_mask, morphological_radius) + brain_mask return (brain_extraction_combined) if modality != "t1nobrainer": ##################### # # ANTs-based # ##################### weights_file_name_prefix = None if modality == "t1v0": weights_file_name_prefix = "brainExtraction" elif modality == "t1": weights_file_name_prefix = "brainExtractionT1" elif modality == "t2": weights_file_name_prefix = "brainExtractionT2" elif modality == "flair": weights_file_name_prefix = "brainExtractionFLAIR" elif modality == "bold": weights_file_name_prefix = "brainExtractionBOLD" elif modality == "fa": weights_file_name_prefix = "brainExtractionFA" elif modality == "t1t2infant": weights_file_name_prefix = "brainExtractionInfantT1T2" elif modality == "t1infant": weights_file_name_prefix = "brainExtractionInfantT1" elif modality == "t2infant": weights_file_name_prefix = "brainExtractionInfantT2" else: raise ValueError("Unknown modality type.") weights_file_name = get_pretrained_network( weights_file_name_prefix, antsxnet_cache_directory=antsxnet_cache_directory) if verbose == True: print("Brain extraction: retrieving template.") reorient_template_file_name_path = get_antsxnet_data( "S_template3", antsxnet_cache_directory=antsxnet_cache_directory) reorient_template = ants.image_read(reorient_template_file_name_path) resampled_image_size = reorient_template.shape if modality == "t1": classes = ("background", "head", "brain") number_of_classification_labels = len(classes) unet_model = create_unet_model_3d( (*resampled_image_size, channel_size), number_of_outputs=number_of_classification_labels, number_of_layers=4, number_of_filters_at_base_layer=8, dropout_rate=0.0, convolution_kernel_size=(3, 3, 3), deconvolution_kernel_size=(2, 2, 2), weight_decay=1e-5) unet_model.load_weights(weights_file_name) if verbose == True: print("Brain extraction: normalizing image to the template.") center_of_mass_template = ants.get_center_of_mass(reorient_template) center_of_mass_image = ants.get_center_of_mass(input_images[0]) translation = np.asarray(center_of_mass_image) - np.asarray( center_of_mass_template) xfrm = ants.create_ants_transform( transform_type="Euler3DTransform", center=np.asarray(center_of_mass_template), translation=translation) batchX = np.zeros((1, *resampled_image_size, channel_size)) for i in range(len(input_images)): warped_image = ants.apply_ants_transform_to_image( xfrm, input_images[i], reorient_template) warped_array = warped_image.numpy() batchX[0, :, :, :, i] = (warped_array - warped_array.mean()) / warped_array.std() if verbose == True: print("Brain extraction: prediction and decoding.") predicted_data = unet_model.predict(batchX, verbose=verbose) origin = reorient_template.origin spacing = reorient_template.spacing direction = reorient_template.direction probability_images_array = list() probability_images_array.append( ants.from_numpy(np.squeeze(predicted_data[0, :, :, :, 0]), origin=origin, spacing=spacing, direction=direction)) probability_images_array.append( ants.from_numpy(np.squeeze(predicted_data[0, :, :, :, 1]), origin=origin, spacing=spacing, direction=direction)) if modality == "t1": probability_images_array.append( ants.from_numpy(np.squeeze(predicted_data[0, :, :, :, 2]), origin=origin, spacing=spacing, direction=direction)) if verbose == True: print( "Brain extraction: renormalize probability mask to native space." ) probability_image = ants.apply_ants_transform_to_image( ants.invert_ants_transform(xfrm), probability_images_array[number_of_classification_labels - 1], input_images[0]) return (probability_image) else: ##################### # # NoBrainer # ##################### if verbose == True: print("NoBrainer: generating network.") model = create_nobrainer_unet_model_3d((None, None, None, 1)) weights_file_name = get_pretrained_network( "brainExtractionNoBrainer", antsxnet_cache_directory=antsxnet_cache_directory) model.load_weights(weights_file_name) if verbose == True: print( "NoBrainer: preprocessing (intensity truncation and resampling)." ) image_array = image.numpy() image_robust_range = np.quantile( image_array[np.where(image_array != 0)], (0.02, 0.98)) threshold_value = 0.10 * (image_robust_range[1] - image_robust_range[0] ) + image_robust_range[0] thresholded_mask = ants.threshold_image(image, -10000, threshold_value, 0, 1) thresholded_image = image * thresholded_mask image_resampled = ants.resample_image(thresholded_image, (256, 256, 256), use_voxels=True) image_array = np.expand_dims(image_resampled.numpy(), axis=0) image_array = np.expand_dims(image_array, axis=-1) if verbose == True: print("NoBrainer: predicting mask.") brain_mask_array = np.squeeze( model.predict(image_array, verbose=verbose)) brain_mask_resampled = ants.copy_image_info( image_resampled, ants.from_numpy(brain_mask_array)) brain_mask_image = ants.resample_image(brain_mask_resampled, image.shape, use_voxels=True, interp_type=1) spacing = ants.get_spacing(image) spacing_product = spacing[0] * spacing[1] * spacing[2] minimum_brain_volume = round(649933.7 / spacing_product) brain_mask_labeled = ants.label_clusters(brain_mask_image, minimum_brain_volume) return (brain_mask_labeled)