Exemple #1
0
 def test_n4_bias_field_correction(self):
     #def n4_bias_field_correction(image, mask=None, shrink_factor=4,
     #                     convergence={'iters':[50,50,50,50], 'tol':1e-07},
     #                     spline_param=200, verbose=False, weight_mask=None):
     for img in self.imgs:
         image_n4 = ants.n4_bias_field_correction(img)
         mask = img > img.mean()
         image_n4 = ants.n4_bias_field_correction(img, mask=mask)
        def process(filename: str) -> str:
            img = ants.image_read(filename)
            img = ants.n4_bias_field_correction(
                img, shrink_factor=options.shrink_factor, convergence=conv)

            output = path.join(options.outputdir, path.basename(filename))
            img.to_file(output)
            logger.info(output)
            return output
Exemple #3
0
def bias_field_correction(image):
    #image : ants format image
    from time import time
    import ants
    t1 = time()
    jk_corrected = ants.n4_bias_field_correction(image)
    t2 = time()
    print("Time taken for N4 bias field correction: ", t2 - t1)
    return jk_corrected
Exemple #4
0
def n4_correction_ants(im_input):
    image = ants.image_read(im_input, 3)
    image_target = im_input.replace('.nii.gz', '_corrected.nii.gz')

    image_result: ANTsImage = ants.n4_bias_field_correction(image,
                                                            shrink_factor=3,
                                                            convergence={'iters': [50, 50, 30, 20], 'tol': 1e-07},
                                                            spline_param=300,
                                                            verbose=False)

    image_result.to_file(image_target)
    print(f"Saved image: ${image_target}")
Exemple #5
0
    def test_n4_bias_field_correction_example(self):
        image = ants.image_read(ants.get_ants_data('r16'))
        image_n4 = ants.n4_bias_field_correction(image)

        # spline param list
        image_n4 = ants.n4_bias_field_correction(image, spline_param=(10, 10))

        # image not float
        image_ui = image.clone('unsigned int')
        image_n4 = ants.n4_bias_field_correction(image_ui)

        # weight mask
        mask = image > image.mean()
        ants.n4_bias_field_correction(image, weight_mask=mask)

        # len(spline_param) != img.dimension
        with self.assertRaises(Exception):
            ants.n4_bias_field_correction(image, spline_param=(10, 10, 10))

        # weight mask not ANTsImage
        with self.assertRaises(Exception):
            ants.n4_bias_field_correction(image, weight_mask=0.4)
Exemple #6
0
def preprocess_single_subject(image, seg_image):
    """
    Takes a T1 and its segmentation, processes them, and returns 
    the processed images

    This is really the only thing that needs to be changed according
    to the user's preferences for preprocessing
    """
    #image_mask = ants.get_mask(image)

    # run N4 bias correction
    image = ants.n4_bias_field_correction(image)  #, mask=image_mask)

    # downsample to 2mm^3 resolution
    image = image.resample_image((2, 2, 2), interp_type=0)

    seg_image = seg_image.resample_image((2, 2, 2), interp_type=1)

    return image, seg_image
def bias_field_correction(path: str, extension: str = '.nii.gz'):
    """
    This ROI generator follows the structure FILE/FILE+extension
    and generates a ROI file with the name   FILE/FILE+_norm+extension
    Parameters
    ----------
    path        Images Path

    Returns     Generated ROI images
    -------

    """
    for scan_id in os.listdir(path):
        print('Bias Field correction : ', scan_id)
        image = ants.image_read(
            os.path.join(path, scan_id, scan_id + extension))
        image_n4 = ants.n4_bias_field_correction(image)
        ants.image_write(image_n4,
                         os.path.join(path, scan_id, scan_id + extension))
    return
Exemple #8
0
def preprocess_brain_image(image,
                           truncate_intensity=(0.01, 0.99),
                           brain_extraction_modality=None,
                           template_transform_type=None,
                           template="biobank",
                           do_bias_correction=True,
                           return_bias_field=False,
                           do_denoising=True,
                           intensity_matching_type=None,
                           reference_image=None,
                           intensity_normalization_type=None,
                           antsxnet_cache_directory=None,
                           verbose=True):

    """
    Basic preprocessing pipeline for T1-weighted brain MRI

    Standard preprocessing steps that have been previously described
    in various papers including the cortical thickness pipeline:

         https://www.ncbi.nlm.nih.gov/pubmed/24879923

    Arguments
    ---------
    image : ANTsImage
        input image

    truncate_intensity : 2-length tuple
        Defines the quantile threshold for truncating the image intensity

    brain_extraction_modality : string or None
        Perform brain extraction using antspynet tools.  One of "t1", "t1v0",
        "t1nobrainer", "t1combined", "flair", "t2", "bold", "fa", "t1infant",
        "t2infant", or None.

    template_transform_type : string
        See details in help for ants.registration.  Typically "Rigid" or
        "Affine".

    template : ANTs image (not skull-stripped)
        Alternatively, one can specify the default "biobank" or "croppedMni152"
        to download and use premade templates.

    do_bias_correction : boolean
        Perform N4 bias field correction.

    return_bias_field : boolean
        If True, return bias field as an additional output *without* bias
        correcting the preprocessed image.

    do_denoising : boolean
        Perform non-local means denoising.

    intensity_matching_type : string
        Either "regression" or "histogram". Only is performed if reference_image
        is not None.

    reference_image : ANTs image
        Reference image for intensity matching.

    intensity_normalization_type : string
        Either rescale the intensities to [0,1] (i.e., "01") or zero-mean, unit variance
        (i.e., "0mean").  If None normalization is not performed.

    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
    -------
    Dictionary with preprocessing information ANTs image (i.e., source_image) matched to the
    (reference_image).

    Example
    -------
    >>> import ants
    >>> image = ants.image_read(ants.get_ants_data('r16'))
    >>> preprocessed_image = preprocess_brain_image(image, do_brain_extraction=False)
    """

    from ..utilities import brain_extraction
    from ..utilities import regression_match_image
    from ..utilities import get_antsxnet_data

    preprocessed_image = ants.image_clone(image)

    if antsxnet_cache_directory == None:
        antsxnet_cache_directory = "ANTsXNet"

    # Truncate intensity
    if truncate_intensity is not None:
        quantiles = (image.quantile(truncate_intensity[0]), image.quantile(truncate_intensity[1]))
        if verbose == True:
            print("Preprocessing:  truncate intensities ( low =", quantiles[0], ", high =", quantiles[1], ").")

        preprocessed_image[image < quantiles[0]] = quantiles[0]
        preprocessed_image[image > quantiles[1]] = quantiles[1]

    # Brain extraction
    mask = None
    if brain_extraction_modality is not None:
        if verbose == True:
            print("Preprocessing:  brain extraction.")

        probability_mask = brain_extraction(preprocessed_image, modality=brain_extraction_modality,
            antsxnet_cache_directory=antsxnet_cache_directory, verbose=verbose)
        mask = ants.threshold_image(probability_mask, 0.5, 1, 1, 0)
        mask = ants.morphology(mask,"close",6).iMath_fill_holes()

    # Template normalization
    transforms = None
    if template_transform_type is not None:
        template_image = None
        if isinstance(template, str):
            template_file_name_path = get_antsxnet_data(template, antsxnet_cache_directory=antsxnet_cache_directory)
            template_image = ants.image_read(template_file_name_path)
        else:
            template_image = template

        if mask is None:
            registration = ants.registration(fixed=template_image, moving=preprocessed_image,
                type_of_transform=template_transform_type, verbose=verbose)
            preprocessed_image = registration['warpedmovout']
            transforms = dict(fwdtransforms=registration['fwdtransforms'],
                              invtransforms=registration['invtransforms'])
        else:
            template_probability_mask = brain_extraction(template_image, modality=brain_extraction_modality, 
                antsxnet_cache_directory=antsxnet_cache_directory, verbose=verbose)
            template_mask = ants.threshold_image(template_probability_mask, 0.5, 1, 1, 0)
            template_brain_image = template_mask * template_image

            preprocessed_brain_image = preprocessed_image * mask

            registration = ants.registration(fixed=template_brain_image, moving=preprocessed_brain_image,
                type_of_transform=template_transform_type, verbose=verbose)
            transforms = dict(fwdtransforms=registration['fwdtransforms'],
                              invtransforms=registration['invtransforms'])

            preprocessed_image = ants.apply_transforms(fixed = template_image, moving = preprocessed_image,
                transformlist=registration['fwdtransforms'], interpolator="linear", verbose=verbose)
            mask = ants.apply_transforms(fixed = template_image, moving = mask,
                transformlist=registration['fwdtransforms'], interpolator="genericLabel", verbose=verbose)

    # Do bias correction
    bias_field = None
    if do_bias_correction == True:
        if verbose == True:
            print("Preprocessing:  brain correction.")
        n4_output = None
        if mask is None:
            n4_output = ants.n4_bias_field_correction(preprocessed_image, shrink_factor=4, return_bias_field=return_bias_field, verbose=verbose)
        else:
            n4_output = ants.n4_bias_field_correction(preprocessed_image, mask, shrink_factor=4, return_bias_field=return_bias_field, verbose=verbose)
        if return_bias_field == True:
            bias_field = n4_output
        else:
            preprocessed_image = n4_output

    # Denoising
    if do_denoising == True:
        if verbose == True:
            print("Preprocessing:  denoising.")

        if mask is None:
            preprocessed_image = ants.denoise_image(preprocessed_image, shrink_factor=1)
        else:
            preprocessed_image = ants.denoise_image(preprocessed_image, mask, shrink_factor=1)

    # Image matching
    if reference_image is not None and intensity_matching_type is not None:
        if verbose == True:
            print("Preprocessing:  intensity matching.")

        if intensity_matching_type == "regression":
            preprocessed_image = regression_match_image(preprocessed_image, reference_image)
        elif intensity_matching_type == "histogram":
            preprocessed_image = ants.histogram_match_image(preprocessed_image, reference_image)
        else:
            raise ValueError("Unrecognized intensity_matching_type.")

    # Intensity normalization
    if intensity_normalization_type is not None:
        if verbose == True:
            print("Preprocessing:  intensity normalization.")

        if intensity_normalization_type == "01":
            preprocessed_image = (preprocessed_image - preprocessed_image.min())/(preprocessed_image.max() - preprocessed_image.min())
        elif intensity_normalization_type == "0mean":
            preprocessed_image = (preprocessed_image - preprocessed_image.mean())/preprocessed_image.std()
        else:
            raise ValueError("Unrecognized intensity_normalization_type.")

    return_dict = {'preprocessed_image' : preprocessed_image}
    if mask is not None:
        return_dict['brain_mask'] = mask
    if bias_field is not None:
        return_dict['bias_field'] = bias_field
    if transforms is not None:
        return_dict['template_transforms'] = transforms

    return(return_dict)
Exemple #9
0
def preprocess(img_path,
               out_dir,
               mask_path=None,
               res=(1, 1, 1),
               orientation='RAI',
               n4_opts=None):
    """
    preprocess.py MR images according to a simple scheme,
    that is:
        1) N4 bias field correction
        2) resample to 1mm x 1mm x 1mm
        3) reorient images to RAI
    Args:
        img_dir (str): path to directory containing images
        out_dir (str): path to directory for output preprocessed files
        mask_dir (str): path to directory containing masks
        res (tuple): resolution for resampling (default: (1,1,1) in mm
        n4_opts (dict): n4 processing options (default: None)
    Returns:
        None, outputs preprocessed images to file in given out_dir
    """

    if n4_opts is None:
        n4_opts = {'iters': [200, 200, 200, 200], 'tol': 0.0005}
    logger.debug('N4 Options are: {}'.format(n4_opts))

    # get and check the images and masks
    img_fns = img_path
    mask_fns = mask_path

    # create the output directory structure
    out_img_dir = os.path.join(out_dir, 'imgs')
    out_mask_dir = os.path.join(out_dir, 'masks')
    if not os.path.exists(out_dir):
        logger.info('Making output directory structure: {}'.format(out_dir))
        os.mkdir(out_dir)
    if not os.path.exists(out_img_dir):
        logger.info('Making image output directory: {}'.format(out_img_dir))
        os.mkdir(out_img_dir)
    if not os.path.exists(out_mask_dir) and mask_path is not None:
        logger.info('Making mask output directory: {}'.format(out_mask_dir))
        os.mkdir(out_mask_dir)

    # preprocess the images by n4 correction, resampling, and reorientation

    _, img_base, img_ext = split_filename(img_fns)
    #logger.info('Preprocessing image: {} ({:d}/{:d})'.format(img_base, i, len(img_fns)))

    img = ants.image_read(img_fns)
    if mask_path is not None:
        _, mask_base, mask_ext = split_filename(mask_fns)
        mask = ants.image_read(mask_fns)
        smoothed_mask = ants.smooth_image(mask, 1)
        # this should be a second n4 after an initial n4 (and coregistration), once masks are obtained
        img = ants.n4_bias_field_correction(img,
                                            convergence=n4_opts,
                                            weight_mask=smoothed_mask)

        out_mask = os.path.join(out_mask_dir, mask_base + mask_ext)
        ants.image_write(mask, out_mask)
    else:
        img = ants.n4_bias_field_correction(img, convergence=n4_opts)
    if hasattr(img, 'reorient_image2'):
        img = img.reorient_image2(orientation)
    else:
        logger.info(
            'Cannot reorient image to a custom orientation. Update ANTsPy to a version >= 0.1.5.'
        )
        img = img.reorient_image((1, 0, 0))['reoimage']
    out_img = os.path.join(out_img_dir, img_base + img_ext)
    ants.image_write(img, out_img)
Exemple #10
0
def preprocess(img_dir,
               out_dir,
               mask_dir=None,
               res=(1., 1., 1.),
               orientation='RAI',
               n4_opts=None):
    """
    preprocess.py MR images according to a simple scheme,
    that is:
        1) N4 bias field correction
        2) resample to x mm x y mm x z mm
        3) reorient images to RAI

    Args:
        img_dir (str): path to directory containing images
        out_dir (str): path to directory for output preprocessed files
        mask_dir (str): path to directory containing masks
        res (tuple): resolution for resampling (default: (1,1,1) in mm)
        n4_opts (dict): n4 processing options. See ANTsPy for details. (default: None)

    Returns:
        None, outputs preprocessed images to file in given out_dir
    """

    if n4_opts is None:
        n4_opts = {'iters': [200, 200, 200, 200], 'tol': 0.0005}
    logger.debug('N4 Options are: {}'.format(n4_opts))

    # get and check the images and masks
    img_fns = glob_nii(img_dir)
    mask_fns = glob_nii(
        mask_dir) if mask_dir is not None else [None] * len(img_fns)
    assert len(img_fns) == len(mask_fns), 'Number of images and masks must be equal ({:d} != {:d})' \
        .format(len(img_fns), len(mask_fns))

    # create the output directory structure
    out_img_dir = os.path.join(out_dir, 'imgs')
    out_mask_dir = os.path.join(out_dir, 'masks')
    if not os.path.exists(out_dir):
        logger.info('Making output directory structure: {}'.format(out_dir))
        os.mkdir(out_dir)
    if not os.path.exists(out_img_dir):
        logger.info('Making image output directory: {}'.format(out_img_dir))
        os.mkdir(out_img_dir)
    if not os.path.exists(out_mask_dir) and mask_dir is not None:
        logger.info('Making mask output directory: {}'.format(out_mask_dir))
        os.mkdir(out_mask_dir)

    # preprocess the images by n4 correction, resampling, and reorientation
    for i, (img_fn, mask_fn) in enumerate(zip(img_fns, mask_fns), 1):
        _, img_base, img_ext = split_filename(img_fn)
        logger.info('Preprocessing image: {} ({:d}/{:d})'.format(
            img_base, i, len(img_fns)))
        img = ants.image_read(img_fn)
        if mask_dir is not None:
            _, mask_base, mask_ext = split_filename(mask_fn)
            mask = ants.image_read(mask_fn)
            smoothed_mask = ants.smooth_image(mask, 1)
            # this should be a second n4 after an initial n4 (and coregistration), once masks are obtained
            img = ants.n4_bias_field_correction(img,
                                                convergence=n4_opts,
                                                weight_mask=smoothed_mask)
            if res is not None:
                if res != img.spacing:
                    mask = ants.resample_image(mask, res, False, 1)
            mask = mask.reorient_image2(orientation) if hasattr(img, 'reorient_image2') else \
                mask.reorient_image((1, 0, 0))['reoimage']
            out_mask = os.path.join(out_mask_dir, mask_base + mask_ext)
            ants.image_write(mask, out_mask)
        else:
            img = ants.n4_bias_field_correction(img, convergence=n4_opts)
        if res is not None:
            if res != img.spacing:
                img = ants.resample_image(img, res, False, 4)
        if hasattr(img, 'reorient_image2'):
            img = img.reorient_image2(orientation)
        else:
            logger.info(
                'Cannot reorient image to a custom orientation. Update ANTsPy to a version >= 0.1.5.'
            )
            img = img.reorient_image((1, 0, 0))['reoimage']
        logger.info('Writing preprocessed image: {} ({:d}/{:d})'.format(
            img_base, i, len(img_fns)))
        out_img = os.path.join(out_img_dir, img_base + img_ext)
        ants.image_write(img, out_img)
Exemple #11
0
 def __init__(self, ants_image=[[0.0]], **options):
     import ants
     self.n4bias = ants.n4_bias_field_correction(ants_image, **options)
Exemple #12
0
def predict_mask(in_file: str,
                 masking_config_path=None,
                 input_type: str = 'anat'):
    """
    The image is first resampled into the resolution of the template space, which has a voxel size of 0.2 × 0.2 × 0.2.
    This is done with the Resample command from the FSL library which is an analysis tool for FMRI, MRI and DTI brain
    imaging data. Then, the image is preprocessed using the preprocessing methods of the model class.
    The predictions of the model are reconstructed to a 3D mask via the command Nifit1Image from nibabel.
    This is done using the same affine space as the input image. The latter is then reshaped into the original shape
    inverting the preprocessing step, either with the opencv resize method or by cropping.
    Additionally, the binary mask is resampled into its original affine space, before being multiplied with the brain
    image to extract the ROI.

    Parameters
    ----------
    in_file : str
        path to the file that is to be masked
    masking_config_path : str
        path to the masking config. The masking config is a json file. All parameters have default values that will
        be set in the "get_masking_opts" method.
        The masking config may contain following parameters (if any of them is not given in the config,
        the default value will be taken from mlebe/masking/config/default_schema.json):
        model_folder_path: str The path to the pretrained model. If not set the default mlebe model will be selected.
        use_cuda: bool
            boolean indicating if cuda will be used for the masking
        visualisation_path: str
            if set, the masking predictions will be saved to this destination.
        crop_values:
            if set, the input bids images will be cropped with given values in the x-y dimensions.
        bias_field_correction: dict
            If set, the input image will be bias corrected before given as input to the model.
            The parameter of the bias correction can be given as a dictionary.
            The default values can be found in the default_schema.json config.
    input_type : str
        either 'func' for CDV or BOLD contrast or 'anat' for T2 contrast

    Returns
    -------
    resampled_mask_path : str
        path to the mask
    nii_path_masked : str
        path to the masked image
    """
    import os
    from os import path
    from pathlib import Path

    import ants
    import nibabel as nib
    import numpy as np
    import pandas as pd
    from ants.registration import resample_image
    from nipype.interfaces.fsl.maths import MeanImage

    from mlebe import log
    from mlebe.masking.utils import get_mask, get_mlebe_models, get_biascorrect_opts_defaults
    from mlebe.masking.utils import remove_outliers, get_masking_opts, crop_bids_image, \
        reconstruct_image, pad_to_shape, get_model_config

    log.info(
        f'Starting masking of {in_file} with config {masking_config_path}.')
    masking_opts = get_masking_opts(masking_config_path, input_type)

    if masking_opts['masked_dir']:
        masked_dir = masking_opts['masked_dir']
        df_selection = pd.read_csv(f'{masked_dir}/data_selection.csv')
        df_selection = df_selection.loc[df_selection.path.str.endswith(
            in_file)]

        nii_path_masked = df_selection.masked_path.item()
        resampled_mask_path = df_selection.mask_path.item()

        assert nii_path_masked, f'nii_path_masked not found for {in_file}'
        assert resampled_mask_path, f'nii_path_masked not found for {resampled_mask_path}'

        assert Path(nii_path_masked).exists(
        ), f'nii_path_masked {nii_path_masked} does not exist.'
        assert Path(resampled_mask_path).exists(
        ), f'resampled_mask_path {resampled_mask_path} does not exist.'

        return nii_path_masked, [resampled_mask_path], resampled_mask_path

    if 'model_folder_path' not in masking_opts or not masking_opts[
            'model_folder_path']:
        # if no model_folder_path is given in the config, the default models are selected.
        masking_opts['model_folder_path'] = get_mlebe_models(input_type)
    model_config = get_model_config(masking_opts)
    input = in_file
    if input_type == 'func':
        tMean_path = 'tMean_.nii.gz'
        mean_image = MeanImage(in_file=input,
                               dimension='T',
                               out_file=tMean_path)
        mean_image.run()
        # command = 'fslmaths {a} -Tmean {b}'.format(a=input, b=tMean_path)
        # log.info(f'Executing command "{command}"')
        # os.system(command)
        assert Path(tMean_path).exists()
        input = tMean_path

    resampled_path = 'resampled_input.nii.gz'
    resampled_nii_path = path.abspath(path.expanduser(resampled_path))
    if masking_opts['testing']:
        resampled_nii = resample_image(ants.image_read(str(input)),
                                       (0.2, 0.2, 0.2), False)
        nib.save(resampled_nii, resampled_nii_path)
    else:
        resample_cmd = 'ResampleImage 3 {input} '.format(
            input=input) + resampled_nii_path + ' 0.2x0.2x0.2'
        os.system(resample_cmd)
        log.info(f'Resample image with "{resample_cmd}"')

    if 'crop_values' in masking_opts and masking_opts['crop_values']:
        crop_bids_image(resampled_nii_path, masking_opts['crop_values'])
    """
    Bias correction
    """
    if 'bias_field_correction' in masking_opts and masking_opts[
            'bias_field_correction']:

        bias_correction_config = get_biascorrect_opts_defaults(masking_opts)
        bias_corrected_path = path.abspath(
            path.expanduser('corrected_input.nii.gz'))

        if masking_opts['testing']:
            convergence_args = bias_correction_config['convergence'].strip(
                '][').split(', ')
            iters = [int(elem) for elem in convergence_args[0].split('x')]
            tol = float(convergence_args[1])
            bias_corrected = ants.n4_bias_field_correction(
                ants.image_read(resampled_nii_path),
                bias_correction_config['bspline_fitting'],
                convergence={
                    'iters': iters,
                    'tol': tol
                },
                shrink_factor=bias_correction_config['shrink_factor'])
            nib.save(bias_corrected, bias_corrected_path)
        else:
            command = 'N4BiasFieldCorrection --bspline-fitting {} -d 3 --input-image {} --convergence {} --output {} ' \
                      '--shrink-factor {}'.format(
                bias_correction_config['bspline_fitting'], resampled_nii_path,
                bias_correction_config['convergence'],
                bias_corrected_path, bias_correction_config['shrink_factor'])

            os.system(command)
            log.info(f'Apply bias correction with "{command}"')

    else:
        bias_corrected_path = resampled_nii_path

    image = nib.load(bias_corrected_path)
    in_file_data = image.get_data()
    """
    Getting the mask
    """
    ori_shape = np.moveaxis(in_file_data, 2, 0).shape
    in_file_data, mask_pred, network_input = get_mask(
        model_config,
        in_file_data,
        ori_shape,
        use_cuda=masking_opts['use_cuda'])

    mask_pred = remove_outliers(mask_pred)
    if 'visualisation_path' in masking_opts and masking_opts[
            'visualisation_path']:
        log.info(f'visualisation_path is {masking_opts["visualisation_path"]}')
        save_visualisation(masking_opts, in_file, network_input, mask_pred)
    """
    Reconstruct to original image size
    """
    resized = reconstruct_image(ori_shape, mask_pred)

    resized_path = 'resized_mask.nii.gz'
    resized_path = path.abspath(path.expanduser(resized_path))
    resized_mask = nib.Nifti1Image(resized, image.affine, image.header)
    nib.save(resized_mask, resized_path)

    # get voxel sizes from input
    input_image = nib.load(input)
    input_img_affine = input_image.affine
    voxel_sizes = nib.affines.voxel_sizes(input_img_affine)

    resampled_mask_path = 'resampled_mask.nii.gz'
    resampled_mask_path = path.abspath(path.expanduser(resampled_mask_path))

    if masking_opts['testing']:
        resized_mask = ants.image_read(resized_path)
        resampled_mask_data = resample_image(
            resized_mask, (voxel_sizes[0], voxel_sizes[1], voxel_sizes[2]),
            False, 1)
    else:
        resample_cmd = 'ResampleImage 3 {input} '.format(
            input=resized_path
        ) + ' ' + resampled_mask_path + ' {x}x{y}x{z} '.format(
            x=voxel_sizes[0], y=voxel_sizes[1], z=voxel_sizes[2]) + ' 0 1'
        log.info(f'Resample image with "{resample_cmd}"')
        os.system(resample_cmd)

        resampled_mask = nib.load(resampled_mask_path)
        resampled_mask_data = resampled_mask.get_data()
    input_image_data = input_image.get_data()
    if resampled_mask_data.shape != input_image_data.shape:
        resampled_mask_data = pad_to_shape(resampled_mask_data,
                                           input_image_data)

    if masking_opts['testing']:
        nib.save(resampled_mask_data, resampled_mask_path)
        resampled_mask_data = resampled_mask_data.numpy()
    else:
        nib.save(
            nib.Nifti1Image(resampled_mask_data, input_image.affine,
                            input_image.header), resampled_mask_path)
    """
    Masking of the input image
    """
    log.info('Masking the input image with the generated mask.')
    masked_image = np.multiply(resampled_mask_data, input_image_data).astype(
        'float32'
    )  # nibabel gives a non-helpful error if trying to save data that has dtype float64
    nii_path_masked = 'masked_output.nii.gz'
    nii_path_masked = path.abspath(path.expanduser(nii_path_masked))
    masked_image = nib.Nifti1Image(masked_image, input_image.affine,
                                   input_image.header)
    nib.save(masked_image, nii_path_masked)

    log.info(f'Masking of input image {in_file} finished successfully.')
    # f/s_biascorrect takes a list as input for the mask while biascorrect takes directly the path
    return nii_path_masked, [resampled_mask_path], resampled_mask_path
Exemple #13
0
def arterial_lesion_segmentation(image,
                                 antsxnet_cache_directory=None,
                                 verbose=False):
    """
    Perform arterial lesion segmentation using U-net.

    Arguments
    ---------
    image : ANTsImage
        input image

    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
    -------
    Foreground probability image.

    Example
    -------
    >>> output = arterial_lesion_segmentation(histology_image)
    """

    from ..architectures import create_unet_model_2d
    from ..utilities import get_pretrained_network

    if image.dimension != 2:
        raise ValueError("Image dimension must be 2.")

    if antsxnet_cache_directory == None:
        antsxnet_cache_directory = "ANTsXNet"

    channel_size = 1

    weights_file_name = get_pretrained_network(
        "arterialLesionWeibinShi",
        antsxnet_cache_directory=antsxnet_cache_directory)

    resampled_image_size = (512, 512)

    unet_model = create_unet_model_2d(
        (*resampled_image_size, channel_size),
        number_of_outputs=1,
        mode="sigmoid",
        number_of_filters=(64, 96, 128, 256, 512),
        convolution_kernel_size=(3, 3),
        deconvolution_kernel_size=(2, 2),
        dropout_rate=0.0,
        weight_decay=0,
        additional_options=("initialConvolutionKernelSize[5]",
                            "attentionGating"))
    unet_model.load_weights(weights_file_name)

    if verbose == True:
        print("Preprocessing:  Resampling and N4 bias correction.")

    preprocessed_image = ants.image_clone(image)
    preprocessed_image = preprocessed_image / preprocessed_image.max()
    preprocessed_image = ants.resample_image(preprocessed_image,
                                             resampled_image_size,
                                             use_voxels=True,
                                             interp_type=0)
    mask = ants.image_clone(preprocessed_image) * 0 + 1
    preprocessed_image = ants.n4_bias_field_correction(preprocessed_image,
                                                       mask=mask,
                                                       shrink_factor=2,
                                                       return_bias_field=False,
                                                       verbose=verbose)

    batchX = np.expand_dims(preprocessed_image.numpy(), axis=0)
    batchX = np.expand_dims(batchX, axis=-1)
    batchX = (batchX - batchX.min()) / (batchX.max() - batchX.min())

    predicted_data = unet_model.predict(batchX, verbose=int(verbose))

    origin = preprocessed_image.origin
    spacing = preprocessed_image.spacing
    direction = preprocessed_image.direction

    foreground_probability_image = ants.from_numpy(np.squeeze(
        predicted_data[0, :, :, 0]),
                                                   origin=origin,
                                                   spacing=spacing,
                                                   direction=direction)

    if verbose == True:
        print("Post-processing:  resampling to original space.")

    foreground_probability_image = ants.resample_image_to_target(
        foreground_probability_image, image)

    return (foreground_probability_image)
outputDirectory = baseDirectory + 'OutputANTsPy/'
if not os.path.isdir( outputDirectory ):
  os.mkdir( outputDirectory )

outputPrefix = outputDirectory + 'antspy'

numberOfOuterIterations = 5

image = ants.image_read( dataDirectory + 'KKI2009-01-MPRAGE_slice150.nii.gz', dimension = 2 )
mask = ants.image_read( dataDirectory + 'KKI2009-01-MPRAGE_slice150_mask.nii.gz', dimension = 2 )
weightMask = None

for i in range( numberOfOuterIterations ):
  print( "***************   N4 <---> Atropos iteration ", i, "  ******************\n" )
  n4Results = ants.n4_bias_field_correction( image, mask = mask,
    weight_mask = weightMask, verbose = True )
  image = n4Results
  atroposResults = ants.atropos( a = image, x = mask )
  onesImage = ants.make_image( image.shape, voxval = 0,
    spacing = ants.get_spacing( image ),
    origin = ants.get_origin( image ),
    direction = ants.get_direction( image ) )
  weightMask = atroposResults['probabilityimages'][1] *\
    ( onesImage - atroposResults['probabilityimages'][0] ) *\
    ( onesImage - atroposResults['probabilityimages'][2] ) +\
    atroposResults['probabilityimages'][2] *\
    ( onesImage - atroposResults['probabilityimages'][1] ) *\
    ( onesImage - atroposResults['probabilityimages'][0] )

ants.image_write( image, outputPrefix + "N4Corrected.nii.gz" )
ants.image_write( atroposResults['segmentation'], outputPrefix + "AtroposSegmentation.nii.gz" )
Exemple #15
0
def deep_flash(t1,
               t2=None,
               do_preprocessing=True,
               use_rank_intensity=True,
               antsxnet_cache_directory=None,
               verbose=False):
    """
    Hippocampal/Enthorhinal segmentation using "Deep Flash"

    Perform hippocampal/entorhinal segmentation in T1 and T1/T2 images using
    labels from Mike Yassa's lab

    https://faculty.sites.uci.edu/myassa/

    The labeling is as follows:
    Label 0 :  background
    Label 5 :  left aLEC
    Label 6 :  right aLEC
    Label 7 :  left pMEC
    Label 8 :  right pMEC
    Label 9 :  left perirhinal
    Label 10:  right perirhinal
    Label 11:  left parahippocampal
    Label 12:  right parahippocampal
    Label 13:  left DG/CA2/CA3/CA4
    Label 14:  right DG/CA2/CA3/CA4
    Label 15:  left CA1
    Label 16:  right CA1
    Label 17:  left subiculum
    Label 18:  right subiculum

    Preprocessing on the training data consisted of:
       * n4 bias correction,
       * affine registration to the "deep flash" template.
    which is performed on the input images if do_preprocessing = True.

    Arguments
    ---------
    t1 : ANTsImage
        raw or preprocessed 3-D T1-weighted brain image.

    t2 : ANTsImage
        Optional 3-D T2-weighted brain image.  If specified, it is assumed to be
        pre-aligned to the t1.

    do_preprocessing : boolean
        See description above.

    use_rank_intensity : boolean
        If false, use histogram matching with cropped template ROI.  Otherwise,
        use a rank intensity transform on the cropped ROI.

    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
    -------
    List consisting of the segmentation image and probability images for
    each label and foreground.

    Example
    -------
    >>> image = ants.image_read("t1.nii.gz")
    >>> flash = deep_flash(image)
    """

    from ..architectures import create_unet_model_3d
    from ..utilities import get_pretrained_network
    from ..utilities import get_antsxnet_data
    from ..utilities import brain_extraction

    if t1.dimension != 3:
        raise ValueError("Image dimension must be 3.")

    if antsxnet_cache_directory == None:
        antsxnet_cache_directory = "ANTsXNet"

    ################################
    #
    # Options temporarily taken from the user
    #
    ################################

    # use_hierarchical_parcellation : boolean
    #     If True, use u-net model with additional outputs of the medial temporal lobe
    #     region, hippocampal, and entorhinal/perirhinal/parahippocampal regions.  Otherwise
    #     the only additional output is the medial temporal lobe.
    #
    # use_contralaterality : boolean
    #     Use both hemispherical models to also predict the corresponding contralateral
    #     segmentation and use both sets of priors to produce the results.  Mainly used
    #     for debugging.

    use_hierarchical_parcellation = True
    use_contralaterality = True

    ################################
    #
    # Preprocess images
    #
    ################################

    t1_preprocessed = t1
    t1_mask = None
    t1_preprocessed_flipped = None
    t1_template = ants.image_read(
        get_antsxnet_data("deepFlashTemplateT1SkullStripped"))
    template_transforms = None
    if do_preprocessing:

        if verbose == True:
            print("Preprocessing T1.")

        # Brain extraction
        probability_mask = brain_extraction(
            t1_preprocessed,
            modality="t1",
            antsxnet_cache_directory=antsxnet_cache_directory,
            verbose=verbose)
        t1_mask = ants.threshold_image(probability_mask, 0.5, 1, 1, 0)
        t1_preprocessed = t1_preprocessed * t1_mask

        # Do bias correction
        t1_preprocessed = ants.n4_bias_field_correction(t1_preprocessed,
                                                        t1_mask,
                                                        shrink_factor=4,
                                                        verbose=verbose)

        # Warp to template
        registration = ants.registration(
            fixed=t1_template,
            moving=t1_preprocessed,
            type_of_transform="antsRegistrationSyNQuickRepro[a]",
            verbose=verbose)
        template_transforms = dict(fwdtransforms=registration['fwdtransforms'],
                                   invtransforms=registration['invtransforms'])
        t1_preprocessed = registration['warpedmovout']

    if use_contralaterality:
        t1_preprocessed_array = t1_preprocessed.numpy()
        t1_preprocessed_array_flipped = np.flip(t1_preprocessed_array, axis=0)
        t1_preprocessed_flipped = ants.from_numpy(
            t1_preprocessed_array_flipped,
            origin=t1_preprocessed.origin,
            spacing=t1_preprocessed.spacing,
            direction=t1_preprocessed.direction)

    t2_preprocessed = t2
    t2_preprocessed_flipped = None
    t2_template = None
    if t2 is not None:
        t2_template = ants.image_read(
            get_antsxnet_data("deepFlashTemplateT2SkullStripped"))
        t2_template = ants.copy_image_info(t1_template, t2_template)
        if do_preprocessing:

            if verbose == True:
                print("Preprocessing T2.")

            # Brain extraction
            t2_preprocessed = t2_preprocessed * t1_mask

            # Do bias correction
            t2_preprocessed = ants.n4_bias_field_correction(t2_preprocessed,
                                                            t1_mask,
                                                            shrink_factor=4,
                                                            verbose=verbose)

            # Warp to template
            t2_preprocessed = ants.apply_transforms(
                fixed=t1_template,
                moving=t2_preprocessed,
                transformlist=template_transforms['fwdtransforms'],
                verbose=verbose)

        if use_contralaterality:
            t2_preprocessed_array = t2_preprocessed.numpy()
            t2_preprocessed_array_flipped = np.flip(t2_preprocessed_array,
                                                    axis=0)
            t2_preprocessed_flipped = ants.from_numpy(
                t2_preprocessed_array_flipped,
                origin=t2_preprocessed.origin,
                spacing=t2_preprocessed.spacing,
                direction=t2_preprocessed.direction)

    probability_images = list()
    labels = (0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)
    image_size = (64, 64, 96)

    ################################
    #
    # Process left/right in split networks
    #
    ################################

    ################################
    #
    # Download spatial priors
    #
    ################################

    spatial_priors_file_name_path = get_antsxnet_data(
        "deepFlashPriors", antsxnet_cache_directory=antsxnet_cache_directory)
    spatial_priors = ants.image_read(spatial_priors_file_name_path)
    priors_image_list = ants.ndimage_to_list(spatial_priors)
    for i in range(len(priors_image_list)):
        priors_image_list[i] = ants.copy_image_info(t1_preprocessed,
                                                    priors_image_list[i])

    labels_left = labels[1::2]
    priors_image_left_list = priors_image_list[1::2]
    probability_images_left = list()
    foreground_probability_images_left = list()
    lower_bound_left = (76, 74, 56)
    upper_bound_left = (140, 138, 152)
    tmp_cropped = ants.crop_indices(t1_preprocessed, lower_bound_left,
                                    upper_bound_left)
    origin_left = tmp_cropped.origin

    spacing = tmp_cropped.spacing
    direction = tmp_cropped.direction

    t1_template_roi_left = ants.crop_indices(t1_template, lower_bound_left,
                                             upper_bound_left)
    t1_template_roi_left = (t1_template_roi_left - t1_template_roi_left.min(
    )) / (t1_template_roi_left.max() - t1_template_roi_left.min()) * 2.0 - 1.0
    t2_template_roi_left = None
    if t2_template is not None:
        t2_template_roi_left = ants.crop_indices(t2_template, lower_bound_left,
                                                 upper_bound_left)
        t2_template_roi_left = (t2_template_roi_left -
                                t2_template_roi_left.min()) / (
                                    t2_template_roi_left.max() -
                                    t2_template_roi_left.min()) * 2.0 - 1.0

    labels_right = labels[2::2]
    priors_image_right_list = priors_image_list[2::2]
    probability_images_right = list()
    foreground_probability_images_right = list()
    lower_bound_right = (20, 74, 56)
    upper_bound_right = (84, 138, 152)
    tmp_cropped = ants.crop_indices(t1_preprocessed, lower_bound_right,
                                    upper_bound_right)
    origin_right = tmp_cropped.origin

    t1_template_roi_right = ants.crop_indices(t1_template, lower_bound_right,
                                              upper_bound_right)
    t1_template_roi_right = (
        t1_template_roi_right - t1_template_roi_right.min()
    ) / (t1_template_roi_right.max() - t1_template_roi_right.min()) * 2.0 - 1.0
    t2_template_roi_right = None
    if t2_template is not None:
        t2_template_roi_right = ants.crop_indices(t2_template,
                                                  lower_bound_right,
                                                  upper_bound_right)
        t2_template_roi_right = (t2_template_roi_right -
                                 t2_template_roi_right.min()) / (
                                     t2_template_roi_right.max() -
                                     t2_template_roi_right.min()) * 2.0 - 1.0

    ################################
    #
    # Create model
    #
    ################################

    channel_size = 1 + len(labels_left)
    if t2 is not None:
        channel_size += 1

    number_of_classification_labels = 1 + len(labels_left)

    unet_model = create_unet_model_3d(
        (*image_size, channel_size),
        number_of_outputs=number_of_classification_labels,
        mode="classification",
        number_of_filters=(32, 64, 96, 128, 256),
        convolution_kernel_size=(3, 3, 3),
        deconvolution_kernel_size=(2, 2, 2),
        dropout_rate=0.0,
        weight_decay=0)

    penultimate_layer = unet_model.layers[-2].output

    # medial temporal lobe
    output1 = Conv3D(
        filters=1,
        kernel_size=(1, 1, 1),
        activation='sigmoid',
        kernel_regularizer=regularizers.l2(0.0))(penultimate_layer)

    if use_hierarchical_parcellation:

        # EC, perirhinal, and parahippo.
        output2 = Conv3D(
            filters=1,
            kernel_size=(1, 1, 1),
            activation='sigmoid',
            kernel_regularizer=regularizers.l2(0.0))(penultimate_layer)

        # Hippocampus
        output3 = Conv3D(
            filters=1,
            kernel_size=(1, 1, 1),
            activation='sigmoid',
            kernel_regularizer=regularizers.l2(0.0))(penultimate_layer)

        unet_model = Model(
            inputs=unet_model.input,
            outputs=[unet_model.output, output1, output2, output3])
    else:
        unet_model = Model(inputs=unet_model.input,
                           outputs=[unet_model.output, output1])

    ################################
    #
    # Left:  build model and load weights
    #
    ################################

    network_name = 'deepFlashLeftT1'
    if t2 is not None:
        network_name = 'deepFlashLeftBoth'

    if use_hierarchical_parcellation:
        network_name += "Hierarchical"

    if use_rank_intensity:
        network_name += "_ri"

    if verbose:
        print("DeepFlash: retrieving model weights (left).")
    weights_file_name = get_pretrained_network(
        network_name, antsxnet_cache_directory=antsxnet_cache_directory)
    unet_model.load_weights(weights_file_name)

    ################################
    #
    # Left:  do prediction and normalize to native space
    #
    ################################

    if verbose:
        print("Prediction (left).")

    batchX = None
    if use_contralaterality:
        batchX = np.zeros((2, *image_size, channel_size))
    else:
        batchX = np.zeros((1, *image_size, channel_size))

    t1_cropped = ants.crop_indices(t1_preprocessed, lower_bound_left,
                                   upper_bound_left)
    if use_rank_intensity:
        t1_cropped = ants.rank_intensity(t1_cropped)
    else:
        t1_cropped = ants.histogram_match_image(t1_cropped,
                                                t1_template_roi_left, 255, 64,
                                                False)
    batchX[0, :, :, :, 0] = t1_cropped.numpy()
    if use_contralaterality:
        t1_cropped = ants.crop_indices(t1_preprocessed_flipped,
                                       lower_bound_left, upper_bound_left)
        if use_rank_intensity:
            t1_cropped = ants.rank_intensity(t1_cropped)
        else:
            t1_cropped = ants.histogram_match_image(t1_cropped,
                                                    t1_template_roi_left, 255,
                                                    64, False)
        batchX[1, :, :, :, 0] = t1_cropped.numpy()
    if t2 is not None:
        t2_cropped = ants.crop_indices(t2_preprocessed, lower_bound_left,
                                       upper_bound_left)
        if use_rank_intensity:
            t2_cropped = ants.rank_intensity(t2_cropped)
        else:
            t2_cropped = ants.histogram_match_image(t2_cropped,
                                                    t2_template_roi_left, 255,
                                                    64, False)
        batchX[0, :, :, :, 1] = t2_cropped.numpy()
        if use_contralaterality:
            t2_cropped = ants.crop_indices(t2_preprocessed_flipped,
                                           lower_bound_left, upper_bound_left)
            if use_rank_intensity:
                t2_cropped = ants.rank_intensity(t2_cropped)
            else:
                t2_cropped = ants.histogram_match_image(
                    t2_cropped, t2_template_roi_left, 255, 64, False)
            batchX[1, :, :, :, 1] = t2_cropped.numpy()

    for i in range(len(priors_image_left_list)):
        cropped_prior = ants.crop_indices(priors_image_left_list[i],
                                          lower_bound_left, upper_bound_left)
        for j in range(batchX.shape[0]):
            batchX[j, :, :, :, i +
                   (channel_size - len(labels_left))] = cropped_prior.numpy()

    predicted_data = unet_model.predict(batchX, verbose=verbose)

    for i in range(1 + len(labels_left)):
        for j in range(predicted_data[0].shape[0]):
            probability_image = \
                ants.from_numpy(np.squeeze(predicted_data[0][j, :, :, :, i]),
                origin=origin_left, spacing=spacing, direction=direction)
            if i > 0:
                probability_image = ants.decrop_image(probability_image,
                                                      t1_preprocessed * 0)
            else:
                probability_image = ants.decrop_image(probability_image,
                                                      t1_preprocessed * 0 + 1)

            if j == 1:  # flipped
                probability_array_flipped = np.flip(probability_image.numpy(),
                                                    axis=0)
                probability_image = ants.from_numpy(
                    probability_array_flipped,
                    origin=probability_image.origin,
                    spacing=probability_image.spacing,
                    direction=probability_image.direction)

            if do_preprocessing:
                probability_image = ants.apply_transforms(
                    fixed=t1,
                    moving=probability_image,
                    transformlist=template_transforms['invtransforms'],
                    whichtoinvert=[True],
                    interpolator="linear",
                    verbose=verbose)

            if j == 0:  # not flipped
                probability_images_left.append(probability_image)
            else:  # flipped
                probability_images_right.append(probability_image)

    ################################
    #
    # Left:  do prediction of mtl, hippocampal, and ec regions and normalize to native space
    #
    ################################

    for i in range(1, len(predicted_data)):
        for j in range(predicted_data[i].shape[0]):
            probability_image = \
                ants.from_numpy(np.squeeze(predicted_data[i][j, :, :, :, 0]),
                origin=origin_left, spacing=spacing, direction=direction)
            probability_image = ants.decrop_image(probability_image,
                                                  t1_preprocessed * 0)

            if j == 1:  # flipped
                probability_array_flipped = np.flip(probability_image.numpy(),
                                                    axis=0)
                probability_image = ants.from_numpy(
                    probability_array_flipped,
                    origin=probability_image.origin,
                    spacing=probability_image.spacing,
                    direction=probability_image.direction)

            if do_preprocessing:
                probability_image = ants.apply_transforms(
                    fixed=t1,
                    moving=probability_image,
                    transformlist=template_transforms['invtransforms'],
                    whichtoinvert=[True],
                    interpolator="linear",
                    verbose=verbose)

            if j == 0:  # not flipped
                foreground_probability_images_left.append(probability_image)
            else:
                foreground_probability_images_right.append(probability_image)

    ################################
    #
    # Right:  build model and load weights
    #
    ################################

    network_name = 'deepFlashRightT1'
    if t2 is not None:
        network_name = 'deepFlashRightBoth'

    if use_hierarchical_parcellation:
        network_name += "Hierarchical"

    if use_rank_intensity:
        network_name += "_ri"

    if verbose:
        print("DeepFlash: retrieving model weights (right).")
    weights_file_name = get_pretrained_network(
        network_name, antsxnet_cache_directory=antsxnet_cache_directory)
    unet_model.load_weights(weights_file_name)

    ################################
    #
    # Right:  do prediction and normalize to native space
    #
    ################################

    if verbose:
        print("Prediction (right).")

    batchX = None
    if use_contralaterality:
        batchX = np.zeros((2, *image_size, channel_size))
    else:
        batchX = np.zeros((1, *image_size, channel_size))

    t1_cropped = ants.crop_indices(t1_preprocessed, lower_bound_right,
                                   upper_bound_right)
    if use_rank_intensity:
        t1_cropped = ants.rank_intensity(t1_cropped)
    else:
        t1_cropped = ants.histogram_match_image(t1_cropped,
                                                t1_template_roi_right, 255, 64,
                                                False)
    batchX[0, :, :, :, 0] = t1_cropped.numpy()
    if use_contralaterality:
        t1_cropped = ants.crop_indices(t1_preprocessed_flipped,
                                       lower_bound_right, upper_bound_right)
        if use_rank_intensity:
            t1_cropped = ants.rank_intensity(t1_cropped)
        else:
            t1_cropped = ants.histogram_match_image(t1_cropped,
                                                    t1_template_roi_right, 255,
                                                    64, False)
        batchX[1, :, :, :, 0] = t1_cropped.numpy()
    if t2 is not None:
        t2_cropped = ants.crop_indices(t2_preprocessed, lower_bound_right,
                                       upper_bound_right)
        if use_rank_intensity:
            t2_cropped = ants.rank_intensity(t2_cropped)
        else:
            t2_cropped = ants.histogram_match_image(t2_cropped,
                                                    t2_template_roi_right, 255,
                                                    64, False)
        batchX[0, :, :, :, 1] = t2_cropped.numpy()
        if use_contralaterality:
            t2_cropped = ants.crop_indices(t2_preprocessed_flipped,
                                           lower_bound_right,
                                           upper_bound_right)
            if use_rank_intensity:
                t2_cropped = ants.rank_intensity(t2_cropped)
            else:
                t2_cropped = ants.histogram_match_image(
                    t2_cropped, t2_template_roi_right, 255, 64, False)
            batchX[1, :, :, :, 1] = t2_cropped.numpy()

    for i in range(len(priors_image_right_list)):
        cropped_prior = ants.crop_indices(priors_image_right_list[i],
                                          lower_bound_right, upper_bound_right)
        for j in range(batchX.shape[0]):
            batchX[j, :, :, :, i +
                   (channel_size - len(labels_right))] = cropped_prior.numpy()

    predicted_data = unet_model.predict(batchX, verbose=verbose)

    for i in range(1 + len(labels_right)):
        for j in range(predicted_data[0].shape[0]):
            probability_image = \
                ants.from_numpy(np.squeeze(predicted_data[0][j, :, :, :, i]),
                origin=origin_right, spacing=spacing, direction=direction)
            if i > 0:
                probability_image = ants.decrop_image(probability_image,
                                                      t1_preprocessed * 0)
            else:
                probability_image = ants.decrop_image(probability_image,
                                                      t1_preprocessed * 0 + 1)

            if j == 1:  # flipped
                probability_array_flipped = np.flip(probability_image.numpy(),
                                                    axis=0)
                probability_image = ants.from_numpy(
                    probability_array_flipped,
                    origin=probability_image.origin,
                    spacing=probability_image.spacing,
                    direction=probability_image.direction)

            if do_preprocessing:
                probability_image = ants.apply_transforms(
                    fixed=t1,
                    moving=probability_image,
                    transformlist=template_transforms['invtransforms'],
                    whichtoinvert=[True],
                    interpolator="linear",
                    verbose=verbose)

            if j == 0:  # not flipped
                if use_contralaterality:
                    probability_images_right[i] = (
                        probability_images_right[i] + probability_image) / 2
                else:
                    probability_images_right.append(probability_image)
            else:  # flipped
                probability_images_left[i] = (probability_images_left[i] +
                                              probability_image) / 2

    ################################
    #
    # Right:  do prediction of mtl, hippocampal, and ec regions and normalize to native space
    #
    ################################

    for i in range(1, len(predicted_data)):
        for j in range(predicted_data[i].shape[0]):
            probability_image = \
                ants.from_numpy(np.squeeze(predicted_data[i][j, :, :, :, 0]),
                origin=origin_right, spacing=spacing, direction=direction)
            probability_image = ants.decrop_image(probability_image,
                                                  t1_preprocessed * 0)

            if j == 1:  # flipped
                probability_array_flipped = np.flip(probability_image.numpy(),
                                                    axis=0)
                probability_image = ants.from_numpy(
                    probability_array_flipped,
                    origin=probability_image.origin,
                    spacing=probability_image.spacing,
                    direction=probability_image.direction)

            if do_preprocessing:
                probability_image = ants.apply_transforms(
                    fixed=t1,
                    moving=probability_image,
                    transformlist=template_transforms['invtransforms'],
                    whichtoinvert=[True],
                    interpolator="linear",
                    verbose=verbose)

            if j == 0:  # not flipped
                if use_contralaterality:
                    foreground_probability_images_right[
                        i - 1] = (foreground_probability_images_right[i - 1] +
                                  probability_image) / 2
                else:
                    foreground_probability_images_right.append(
                        probability_image)
            else:
                foreground_probability_images_left[
                    i - 1] = (foreground_probability_images_left[i - 1] +
                              probability_image) / 2

    ################################
    #
    # Combine priors
    #
    ################################

    probability_background_image = ants.image_clone(t1) * 0
    for i in range(1, len(probability_images_left)):
        probability_background_image += probability_images_left[i]
    for i in range(1, len(probability_images_right)):
        probability_background_image += probability_images_right[i]

    probability_images.append(probability_background_image * -1 + 1)
    for i in range(1, len(probability_images_left)):
        probability_images.append(probability_images_left[i])
        probability_images.append(probability_images_right[i])

    ################################
    #
    # Convert probability images to segmentation
    #
    ################################

    # image_matrix = ants.image_list_to_matrix(probability_images, t1 * 0 + 1)
    # segmentation_matrix = np.argmax(image_matrix, axis=0)
    # segmentation_image = ants.matrix_to_images(
    #     np.expand_dims(segmentation_matrix, axis=0), t1 * 0 + 1)[0]

    image_matrix = ants.image_list_to_matrix(
        probability_images[1:(len(probability_images))], t1 * 0 + 1)
    background_foreground_matrix = np.stack([
        ants.image_list_to_matrix([probability_images[0]], t1 * 0 + 1),
        np.expand_dims(np.sum(image_matrix, axis=0), axis=0)
    ])
    foreground_matrix = np.argmax(background_foreground_matrix, axis=0)
    segmentation_matrix = (np.argmax(image_matrix, axis=0) +
                           1) * foreground_matrix
    segmentation_image = ants.matrix_to_images(
        np.expand_dims(segmentation_matrix, axis=0), t1 * 0 + 1)[0]

    relabeled_image = ants.image_clone(segmentation_image)
    for i in range(len(labels)):
        relabeled_image[segmentation_image == i] = labels[i]

    foreground_probability_images = list()
    for i in range(len(foreground_probability_images_left)):
        foreground_probability_images.append(
            foreground_probability_images_left[i] +
            foreground_probability_images_right[i])

    return_dict = None
    if use_hierarchical_parcellation:
        return_dict = {
            'segmentation_image':
            relabeled_image,
            'probability_images':
            probability_images,
            'medial_temporal_lobe_probability_image':
            foreground_probability_images[0],
            'other_region_probability_image':
            foreground_probability_images[1],
            'hippocampal_probability_image':
            foreground_probability_images[2]
        }
    else:
        return_dict = {
            'segmentation_image':
            relabeled_image,
            'probability_images':
            probability_images,
            'medial_temporal_lobe_probability_image':
            foreground_probability_images[0]
        }

    return (return_dict)
Exemple #16
0
# ants.plot( t1, t1mask, axis=2, overlay_alpha = 0.33 )
t1rig = ants.registration( und * bmask, t1 * t1mask, "BOLDRigid" )
t1reg = ants.registration( und * bmask, t1 * t1mask, "SyNOnly",
  initialTransform = t1rig['fwdtransforms'],
  synMetric = 'CC', synSampling = 2, regIterations = (5) )
###########################


# The distortion to the T1 is greatly reduced.

# Brain masking
# Use the BOLD mask to extract the brain from the t1

t1maskFromBold = ants.apply_transforms( t1, bmask, t1reg['invtransforms'],
                                      interpolator = 'nearestNeighbor' )
t1 = ants.n4_bias_field_correction( t1, t1mask, 8 ).n4_bias_field_correction( t1mask, 4 )
bmask =  ants.apply_transforms( und, t1mask, t1reg['fwdtransforms'],
  interpolator = 'nearestNeighbor' ).morphology("close",3)
ofn = rdir + "features/LS" + id + "_mask_py.nii.gz"
ants.image_write( bmask, ofn )
t1toBOLD = ants.apply_transforms( und, t1, t1reg['fwdtransforms'] )
ofn = rdir + "features/LS" + id + "_t1ToBold_py.nii.gz"
ants.image_write( t1toBOLD, ofn )

## Tissue segmentation
# a simple method
################################################
qt1 = ants.iMath_truncate_intensity( t1, 0, 0.95 )
t1seg = ants.kmeans_segmentation( qt1, 3, t1mask, 0.2 )
volumes = ants.label_stats( t1seg['segmentation'], t1seg['segmentation'] )
Exemple #17
0
print("Download: test image")
url_image = "https://github.com/ANTsXNet/BrainExtraction/blob/master/Data/Example/1097782_defaced_MPRAGE.nii.gz?raw=true"
target_file_image = tempfile.NamedTemporaryFile(suffix=".nii.gz",
                                                dir=temp_directory.name)
target_file_image.close()
target_file_image_name = target_file_image.name
if not path.exists(target_file_image_name):
    r = requests.get(url_image)
    with open(target_file_image_name, 'wb') as f:
        f.write(r.content)

image = ants.image_read(target_file_image_name)

print("Preprocessing: bias correction")
image_n4 = ants.n4_bias_field_correction(image)
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)
Exemple #18
0
    def mask_one(self, bids_path: str, elem, masking_opts, model,
                 model_config) -> Tuple[Path, Path]:
        bids_file = ants.image_read(bids_path)
        bids_data = bids_file.numpy()
        bids_file_nib = nib.load(bids_path)

        # resample bids image into the voxel space for which the masking model was trained.
        resampled_bids: ants.ANTsImage = resample_image(
            bids_file, (0.2, 0.2, 0.2), False)

        # crop bids image one the side with given values to alleviate the task of the masking model.
        if 'crop_values' in masking_opts and masking_opts['crop_values']:
            raise NotImplemented('crop_values not yet implemented.')
            crop_values = masking_opts['crop_values']
            cropped = resampled_bids[crop_values[0]:resampled_bids.shape[0] -
                                     crop_values[1], ...]
            resampled_bids = nib.Nifti1Image(cropped, resampled_bids.affine,
                                             resampled_bids.header)
        if 'bias_field_correction' in masking_opts and masking_opts[
                'bias_field_correction']:
            bias_correction_config = get_biascorrect_opts_defaults(
                masking_opts)

            convergence_args = bias_correction_config['convergence'].strip(
                '][').split(', ')
            iters = [int(elem) for elem in convergence_args[0].split('x')]
            tol = float(convergence_args[1])
            resampled_bids = ants.n4_bias_field_correction(
                resampled_bids,
                bias_correction_config['bspline_fitting'],
                convergence={
                    'iters': iters,
                    'tol': tol
                },
                shrink_factor=bias_correction_config['shrink_factor'])
        # get the mask
        in_data = resampled_bids.numpy()
        resampled_shape = np.moveaxis(in_data, 2, 0).shape
        in_file_data, mask_pred, model_input = get_mask(
            model_config,
            in_data,
            resampled_shape,
            use_cuda=masking_opts['use_cuda'],
            model=model)
        mask_pred = remove_outliers(mask_pred)

        resampled_mask = self.reconstruct_to_imgsize(bids_file,
                                                     resampled_shape,
                                                     mask_pred, resampled_bids)
        resampled_mask_data = resampled_mask.numpy()
        if resampled_mask_data.shape != bids_data.shape:
            resampled_mask_data = pad_to_shape(resampled_mask_data, bids_data)

        # Masking of the input image
        masked_image_data = np.multiply(resampled_mask_data, bids_file.numpy()) \
            .astype('float32')  # nibabel gives a non-helpful error if trying to save data that has dtype float64
        masked_image = nib.Nifti1Image(masked_image_data, bids_file_nib.affine,
                                       bids_file_nib.header)

        if 'visualisation_path' in masking_opts and masking_opts[
                'visualisation_path']:
            save_masking_visualisation(
                masking_opts,
                Path(bids_path).name,
                model_input=model_input,
                predicted_mask=mask_pred,
                input_data=np.moveaxis(bids_file.numpy(), 2, 0),
                resampled_mask=np.moveaxis(masked_image_data, 2, 0))

        # saving results
        filename = bids_path.split('/')[-1]
        out_dir = self.preprocessing_dir / 'masked_bids' / f'sub-{elem.subject}' / f'ses-{elem.session}' / elem.datatype
        out_dir.mkdir(parents=True, exist_ok=True)
        mask_path = out_dir / f'mask_{filename}'
        masked_path = out_dir / f'masked_{filename}'
        nib.save(
            nib.Nifti1Image(resampled_mask_data, bids_file_nib.affine,
                            bids_file_nib.header), mask_path)
        nib.save(masked_image, masked_path)
        return mask_path, masked_path
def n4_bias_correction(image):
    import ants
    as_ants = ants.from_numpy(image)
    corrected = ants.n4_bias_field_correction(as_ants)
    return corrected.numpy()
def preprocess_images(
    atlas_id: int,
    atlas_csf_id: int,
    atlas_grey_id: int,
    atlas_white_id: int,
    dataset_id: int,
    replace: bool = False,
    downsample: float = 3.0,
):
    atlas = models.Atlas.objects.get(pk=atlas_id)
    atlas_csf = models.Atlas.objects.get(pk=atlas_csf_id)
    atlas_grey = models.Atlas.objects.get(pk=atlas_grey_id)
    atlas_white = models.Atlas.objects.get(pk=atlas_white_id)
    dataset = models.Dataset.objects.get(pk=dataset_id)

    print('Downloading atlas files')
    with NamedTemporaryFile(
            suffix='atlas.nii') as tmp, atlas.blob.open() as blob:
        for chunk in blob.chunks():
            tmp.write(chunk)
        atlas_img = ants.image_read(tmp.name)

    with NamedTemporaryFile(
            suffix='atlas_csf.nii') as tmp, atlas_csf.blob.open() as blob:
        for chunk in blob.chunks():
            tmp.write(chunk)
        atlas_csf_img = ants.image_read(tmp.name)

    with NamedTemporaryFile(
            suffix='atlas_grey.nii') as tmp, atlas_grey.blob.open() as blob:
        for chunk in blob.chunks():
            tmp.write(chunk)
        atlas_grey_img = ants.image_read(tmp.name)

    with NamedTemporaryFile(
            suffix='atlas_white.nii') as tmp, atlas_white.blob.open() as blob:
        for chunk in blob.chunks():
            tmp.write(chunk)
        atlas_white_img = ants.image_read(tmp.name)

    print('Creating mask')
    priors = [atlas_csf_img, atlas_grey_img, atlas_white_img]
    mask = priors[0].copy()
    mask_view = mask.view()
    for i in range(1, len(priors)):
        mask_view[priors[i].numpy() > 0] = 1
    mask_view[mask_view > 0] = 1

    for image in dataset.images.all():
        if replace:
            _delete_preprocessing_artifacts(image)
        elif _already_preprocessed(image):
            continue
        with NamedTemporaryFile(
                suffix=image.name) as tmp, image.blob.open() as blob:
            for chunk in blob.chunks():
                tmp.write(chunk)
            input_img = ants.image_read(tmp.name)

        print(f'Running N4 bias correction: {image.name}')
        im_n4 = ants.n4_bias_field_correction(input_img)
        del input_img
        print(f'Running registration: {image.name}')
        reg = ants.registration(atlas_img, im_n4)
        del im_n4
        jac_img = ants.create_jacobian_determinant_image(
            atlas_img, reg['fwdtransforms'][0], 1)
        jac_img = jac_img.apply(np.abs)

        reg_model = models.RegisteredImage(source_image=image, atlas=atlas)
        reg_img = reg['warpedmovout']
        with NamedTemporaryFile(suffix='registered.nii') as tmp:
            ants.image_write(reg_img, tmp.name)
            reg_model.blob = File(tmp, name='registered.nii')
            reg_model.save()

        jac_model = models.JacobianImage(source_image=image, atlas=atlas)
        with NamedTemporaryFile(suffix='jacobian.nii') as tmp:
            ants.image_write(jac_img, tmp.name)
            jac_model.blob = File(tmp, name='jacobian.nii')
            jac_model.save()

        print(f'Running segmentation: {image.name}')
        seg = ants.prior_based_segmentation(reg_img, priors, mask)
        del reg_img

        seg_model = models.SegmentedImage(source_image=image, atlas=atlas)
        with NamedTemporaryFile(suffix='segmented.nii') as tmp:
            ants.image_write(seg['segmentation'], tmp.name)
            seg_model.blob = File(tmp, name='segmented.nii')
            seg_model.save()

        print(f'Creating feature image: {image.name}')
        seg_img_view = seg['segmentation'].view()
        feature_img = seg['segmentation'].copy()
        feature_img_view = feature_img.view()
        feature_img_view.fill(0)
        feature_img_view[seg_img_view == 3] = 1  # 3 is white matter label

        intensity_img_view = jac_img.view()
        feature_img_view *= intensity_img_view

        if downsample > 1:
            shape = np.round(np.asarray(feature_img.shape) / downsample)
            feature_img = ants.resample_image(feature_img, shape, True)

        feature_model = models.FeatureImage(source_image=image,
                                            atlas=atlas,
                                            downsample_factor=downsample)
        with NamedTemporaryFile(suffix='feature.nii') as tmp:
            ants.image_write(feature_img, tmp.name)
            feature_model.blob = File(tmp, name='feature.nii')
            feature_model.save()

    dataset.preprocessing_complete = True
    dataset.save()
def preprocess(
    image: NiftiImage,
    mask: Optional[NiftiImage] = None,
    resolution: Optional[Tuple[float, float, float]] = None,
    orientation: str = "RAS",
    n4_convergence_options: Optional[dict] = None,
    interp_type: str = "linear",
    second_n4_with_smoothed_mask: bool = True,
) -> Tuple[NiftiImage, NiftiImage]:
    """Preprocess an MR image

    Preprocess an MR image according to a simple scheme:
    1) N4 bias field correction
    2) resample to X mm x Y mm x Z mm
    3) reorient images to RAI

    Args:
        image: image to preprocess
        mask: mask covering the brain of image (none if already skull-stripped)
        resolution: resolution for resampling. None for no resampling.
        orientation: reorient the image according to this. See ANTsPy for details.
        n4_convergence_options: n4 processing options. See ANTsPy for details.
        interp_type: interpolation type for resampling
            choices: linear, nearest_neighbor, gaussian, windowed_sinc, bspline
        second_n4_with_smoothed_mask: do a second N4 with a smoothed mask
            often improves the bias field correction in the image

    Returns:
        preprocessed image and corresponding foreground mask
    """

    if n4_convergence_options is None:
        n4_convergence_options = {"iters": [200, 200, 200, 200], "tol": 1e-7}
    logger.debug(f"N4 Options are: {n4_convergence_options}")

    if isinstance(image, nib.Nifti1Image):
        image = ants.from_nibabel(image)
    if mask is not None:
        if isinstance(mask, nib.Nifti1Image):
            mask = ants.from_nibabel(mask)
    else:
        mask = image.get_mask()
    logger.debug("Starting bias field correction")
    image = ants.n4_bias_field_correction(image,
                                          convergence=n4_convergence_options)
    if second_n4_with_smoothed_mask:
        smoothed_mask = ants.smooth_image(mask, 1.0)
        logger.debug("Starting 2nd bias field correction")
        image = ants.n4_bias_field_correction(
            image,
            convergence=n4_convergence_options,
            weight_mask=smoothed_mask,
        )
    if resolution is not None:
        if resolution != mask.spacing:
            logger.debug(f"Resampling mask to {resolution}")
            mask = ants.resample_image(
                mask,
                resolution,
                use_voxels=False,
                interp_type=interp_type_dict["nearest_neighbor"],
            )
        if resolution != image.spacing:
            logger.debug(f"Resampling image to {resolution}")
            image = ants.resample_image(
                image,
                resolution,
                use_voxels=False,
                interp_type=interp_type_dict[interp_type],
            )
    image = image.reorient_image2(orientation)
    mask = mask.reorient_image2(orientation)
    image = image.to_nibabel()
    mask = mask.to_nibabel()
    return image, mask