def test_transforms(self): landmarks_dict = dict( t1=np.linspace(0, 100, 13), t2=np.linspace(0, 100, 13), ) elastic = torchio.RandomElasticDeformation(max_displacement=1) transforms = ( torchio.CropOrPad((9, 21, 30)), torchio.ToCanonical(), torchio.Resample((1, 1.1, 1.25)), torchio.RandomFlip(axes=(0, 1, 2), flip_probability=1), torchio.RandomMotion(), torchio.RandomGhosting(axes=(0, 1, 2)), torchio.RandomSpike(), torchio.RandomNoise(), torchio.RandomBlur(), torchio.RandomSwap(patch_size=2, num_iterations=5), torchio.Lambda(lambda x: 2 * x, types_to_apply=torchio.INTENSITY), torchio.RandomBiasField(), torchio.RescaleIntensity((0, 1)), torchio.ZNormalization(masking_method='label'), torchio.HistogramStandardization(landmarks_dict=landmarks_dict), elastic, torchio.RandomAffine(), torchio.OneOf({ torchio.RandomAffine(): 3, elastic: 1 }), torchio.Pad((1, 2, 3, 0, 5, 6), padding_mode='constant', fill=3), torchio.Crop((3, 2, 8, 0, 1, 4)), ) transform = torchio.Compose(transforms) transform(self.sample)
def byol_aug(filename): """ BYOL minimizes the distance between representations of each sample and a transformation of that sample. Examples of transformations include: translation, rotation, blurring, color inversion, color jitter, gaussian noise. Return an augmented dataset that consisted the above mentioned transformation. Will be used in the training. """ image = tio.ScalarImage(filename) get_foreground = tio.ZNormalization.mean training_transform = tio.Compose([ tio.CropOrPad((180, 220, 170)), # zero mean, unit variance of foreground tio.ZNormalization( masking_method=get_foreground), tio.RandomBlur(p=0.25), # blur 25% of times tio.RandomNoise(p=0.25), # Gaussian noise 25% of times tio.OneOf({ # either tio.RandomAffine(): 0.8, # random affine tio.RandomElasticDeformation(): 0.2, # or random elastic deformation }, p=0.8), # applied to 80% of images tio.RandomBiasField(p=0.3), # magnetic field inhomogeneity 30% of times tio.OneOf({ # either tio.RandomMotion(): 1, # random motion artifact tio.RandomSpike(): 2, # or spikes tio.RandomGhosting(): 2, # or ghosts }, p=0.5), # applied to 50% of images ]) tfs_image = training_transform(image) return tfs_image
def get_train_transform(landmarks_path, resection_params=None): spatial_transform = tio.Compose(( tio.OneOf({ tio.RandomAffine(): 0.9, tio.RandomElasticDeformation(): 0.1, }), tio.RandomFlip(), )) resolution_transform = tio.OneOf( ( tio.RandomAnisotropy(), tio.RandomBlur(), ), p=0.75, ) transforms = [] if resection_params is not None: transforms.append(get_simulation_transform(resection_params)) if landmarks_path is not None: transforms.append( tio.HistogramStandardization({'image': landmarks_path})) transforms.extend([ # tio.RandomGamma(p=0.2), resolution_transform, tio.RandomGhosting(p=0.2), tio.RandomSpike(p=0.2), tio.RandomMotion(p=0.2), tio.RandomBiasField(p=0.5), tio.ZNormalization(masking_method=tio.ZNormalization.mean), tio.RandomNoise(p=0.75), # always after ZNorm and after blur! spatial_transform, get_tight_crop(), ]) return tio.Compose(transforms)
def get_transform(self, channels, is_3d=True, labels=True): landmarks_dict = { channel: np.linspace(0, 100, 13) for channel in channels } disp = 1 if is_3d else (1, 1, 0.01) elastic = tio.RandomElasticDeformation(max_displacement=disp) cp_args = (9, 21, 30) if is_3d else (21, 30, 1) resize_args = (10, 20, 30) if is_3d else (10, 20, 1) flip_axes = axes_downsample = (0, 1, 2) if is_3d else (0, 1) swap_patch = (2, 3, 4) if is_3d else (3, 4, 1) pad_args = (1, 2, 3, 0, 5, 6) if is_3d else (0, 0, 3, 0, 5, 6) crop_args = (3, 2, 8, 0, 1, 4) if is_3d else (0, 0, 8, 0, 1, 4) remapping = {1: 2, 2: 1, 3: 20, 4: 25} transforms = [ tio.CropOrPad(cp_args), tio.EnsureShapeMultiple(2, method='crop'), tio.Resize(resize_args), tio.ToCanonical(), tio.RandomAnisotropy(downsampling=(1.75, 2), axes=axes_downsample), tio.CopyAffine(channels[0]), tio.Resample((1, 1.1, 1.25)), tio.RandomFlip(axes=flip_axes, flip_probability=1), tio.RandomMotion(), tio.RandomGhosting(axes=(0, 1, 2)), tio.RandomSpike(), tio.RandomNoise(), tio.RandomBlur(), tio.RandomSwap(patch_size=swap_patch, num_iterations=5), tio.Lambda(lambda x: 2 * x, types_to_apply=tio.INTENSITY), tio.RandomBiasField(), tio.RescaleIntensity(out_min_max=(0, 1)), tio.ZNormalization(), tio.HistogramStandardization(landmarks_dict), elastic, tio.RandomAffine(), tio.OneOf({ tio.RandomAffine(): 3, elastic: 1, }), tio.RemapLabels(remapping=remapping, masking_method='Left'), tio.RemoveLabels([1, 3]), tio.SequentialLabels(), tio.Pad(pad_args, padding_mode=3), tio.Crop(crop_args), ] if labels: transforms.append(tio.RandomLabelsToImage(label_key='label')) return tio.Compose(transforms)
def get_transform(self, channels, is_3d=True, labels=True): landmarks_dict = { channel: np.linspace(0, 100, 13) for channel in channels } disp = 1 if is_3d else (1, 1, 0.01) elastic = torchio.RandomElasticDeformation(max_displacement=disp) cp_args = (9, 21, 30) if is_3d else (21, 30, 1) flip_axes = axes_downsample = (0, 1, 2) if is_3d else (0, 1) swap_patch = (2, 3, 4) if is_3d else (3, 4, 1) pad_args = (1, 2, 3, 0, 5, 6) if is_3d else (0, 0, 3, 0, 5, 6) crop_args = (3, 2, 8, 0, 1, 4) if is_3d else (0, 0, 8, 0, 1, 4) transforms = [ torchio.CropOrPad(cp_args), torchio.ToCanonical(), torchio.RandomDownsample(downsampling=(1.75, 2), axes=axes_downsample), torchio.Resample((1, 1.1, 1.25)), torchio.RandomFlip(axes=flip_axes, flip_probability=1), torchio.RandomMotion(), torchio.RandomGhosting(axes=(0, 1, 2)), torchio.RandomSpike(), torchio.RandomNoise(), torchio.RandomBlur(), torchio.RandomSwap(patch_size=swap_patch, num_iterations=5), torchio.Lambda(lambda x: 2 * x, types_to_apply=torchio.INTENSITY), torchio.RandomBiasField(), torchio.RescaleIntensity((0, 1)), torchio.ZNormalization(), torchio.HistogramStandardization(landmarks_dict), elastic, torchio.RandomAffine(), torchio.OneOf({ torchio.RandomAffine(): 3, elastic: 1, }), torchio.Pad(pad_args, padding_mode=3), torchio.Crop(crop_args), ] if labels: transforms.append(torchio.RandomLabelsToImage(label_key='label')) return torchio.Compose(transforms)
mni_bias = add_bias(fpg_ras) mni_bias.seg = mni_bias.heart show_fpg(mni_bias) #k -space transforms #MR images are generated by computing the inverse Fourier transform of the k-space, which is the signal received by the coils #in the scanner. If the k-space is altered, an artifact will be created in the image. These artifacts are typically # accidental, but we can use transforms to simulate them. #Random spike #Sometimes, signal peaks can appear in k-space. If one adds a high-energy component at e.g. 440 Hz in the spectrum of # an audio signal, a tone of that frequency will be audible in the time domain. Similarly, spikes in k-space manifest # as stripes in image space. They can be simulated using RandomSpike. The number of spikes doesn't affect the transform # run time, so try adding more! add_spike = tio.RandomSpike(seed=42) with_spike = add_spike(fpg_ras) show_fpg(with_spike) #Random ghosting #Ghosting artifacts, caused by patient motion, can be simulated by removing every nth plane from the k-space, # and can be generated using RandomGhosting. As with the previous transform, the number of ghosts doesn't affect # the run time, so you can add as many as you like. add_ghosts = tio.RandomGhosting(intensity=1.8, seed=42) with_ghosts = add_ghosts(fpg_ras) show_fpg(with_ghosts) #Random motion #If the patient moves during the MRI acquisition, motion artifacts will be present. TorchIO includes an implementation of
def dataloader(handles, mode = 'train'): # If pickle exists, load it try: with open('../inputs/flpickles/' + mode + '.pickle', 'rb') as f: images = pickle.load(f) except: images = {} images['Image'] = [] images['Label'] = [] images['Gap'] = [] images['ID'] = [] # Data augmentations random_flip = tio.RandomFlip(axes=1) random_flip2 = tio.RandomFlip(axes=2) random_affine = tio.RandomAffine(seed=0, scales=(3, 3)) random_elastic = tio.RandomElasticDeformation( max_displacement=(0, 20, 40), num_control_points=20, seed=0, ) rescale = tio.RescaleIntensity((-1, 1), percentiles=(1, 99)) standardize_foreground = tio.ZNormalization(masking_method=lambda x: x > x.mean()) blur = tio.RandomBlur(seed=0) standardize = tio.ZNormalization() add_noise = tio.RandomNoise(std=0.5, seed=42) add_spike = tio.RandomSpike(seed=42) add_ghosts = tio.RandomGhosting(intensity=1.5, seed=42) add_motion = tio.RandomMotion(num_transforms=6, image_interpolation='nearest', seed=42) swap = tio.RandomSwap(patch_size = 7) # For each image for idx, row in handles.iterrows(): im_aug = [] lb_aug = [] gap_aug = [] imgs = np.zeros(shape=(1, 1,7,1024, 1024), dtype=np.float32) # change patch shape if necessary lbs = np.zeros(shape=(1, 1,7,1024, 1024), dtype=np.float32) gaps = np.zeros(shape=(1, 1,7,1024, 1024), dtype=np.float32) im = io.imread(row['Image']) im = im / 255 # Normalization im = np.expand_dims(im, axis=0) imgs[0] = im im_aug.append(imgs) images['ID'].append(row['ID']) if mode == 'train': im_flip1 = random_flip(im) imgs[0] = im_flip1 im_aug.append(imgs) im_flip2 = random_flip2(im) imgs[0] = im_flip2 im_aug.append(imgs) im_affine = random_affine(im) imgs[0] = im_affine im_aug.append(imgs) im_elastic = random_elastic(im) imgs[0] = im_elastic im_aug.append(imgs) im_rescale = rescale(im) imgs[0] = im_rescale im_aug.append(imgs) im_standard = standardize_foreground(im) imgs[0] = im_standard im_aug.append(imgs) im_blur = blur(im) imgs[0] = im_blur im_aug.append(imgs) im_noisy = add_noise(standardize(im)) imgs[0] = im_noisy im_aug.append(imgs) im_spike = add_spike(im) imgs[0] = im_spike im_aug.append(imgs) im_ghost = add_ghosts(im) imgs[0] = im_ghost im_aug.append(imgs) im_motion = add_motion(im) imgs[0] = im_motion im_aug.append(imgs) im_swap = swap(im) imgs[0] = im_swap im_aug.append(imgs) images['Image'].append(np.array(im_aug)) if mode != 'test': lb = io.imread(row['Label']) lb = label_converter(lb) lb = np.expand_dims(lb, axis=0) lbs[0] = lb lb_aug.append(lbs) gap = io.imread(row['Gap']) gap = np.expand_dims(gap, axis = 0) gaps[0] = gap gap_aug.append(gaps) if mode == 'train': lb_flip1 = random_flip(lb) lbs[0] = lb_flip1 lb_aug.append(lbs) lb_flip2 = random_flip2(lb) lbs[0] = lb_flip2 lb_aug.append(lbs) lb_affine = random_affine(lb) lbs[0] = lb_affine lb_aug.append(lbs) lb_elastic = random_elastic(lb) lbs[0] = lb_elastic lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) lbs[0] = lb lb_aug.append(lbs) gap_flip1 = random_flip(gap) gaps[0] = gap_flip1 gap_aug.append(gaps) gap_flip2 = random_flip2(gap) gaps[0] = gap_flip2 gap_aug.append(gaps) gap_affine = random_affine(gap) gaps[0] = gap_affine gap_aug.append(gaps) gap_elastic = random_elastic(gap) gaps[0] = gap_elastic gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) gaps[0] = gap gap_aug.append(gaps) images['Label'].append(np.array(lb_aug)) images['Gap'].append(np.array(gap_aug)) # Save images with open("../inputs/flpickles/" + mode + '.pickle', 'wb') as f: pickle.dump(images, f) with open('../inputs/flpickles/' + mode + '.pickle', 'rb') as f: images = pickle.load(f) return images