Ejemplo n.º 1
0
    def test_center_crop_odd(self):
        """
        This test will check if center crop really crops the center
        :return:
        """
        data = np.zeros((8, 4, 30, 30, 30))
        seg = np.zeros(data.shape)

        # we set the center that we expect to be cropped to 1 and then check if we only get 1's in the result
        # crop_size is [10, 20, 16] and data_shape is [30, 30, 30]
        crop_size = np.array([9, 19, 13])
        shp = np.array(data.shape[2:])
        border = (shp - crop_size) // 2
        data[:, :, border[0]:(shp[0] + crop_size[0]),
             border[1]:(shp[1] + crop_size[0]),
             border[2]:(shp[2] + crop_size[0])] = 1
        # same with seg
        seg[:, :, border[0]:(shp[0] + crop_size[0]),
            border[1]:(shp[1] + crop_size[0]),
            border[2]:(shp[2] + crop_size[0])] = 1

        data_cropped, seg_cropped = crop(data,
                                         seg,
                                         crop_size,
                                         margins=(0, 0, 0),
                                         crop_type="center")

        assert np.sum(data_cropped == 0) == 0, "Center crop did not crop the center of data (even data " \
                                               "and odd crop size)"
        assert np.sum(
            seg_cropped == 0
        ) == 0, "Center crop did not crop the center of seg (even data and odd crop size)"
    def generate_train_batch(self):
        # DataLoader has its own methods for selecting what patients to use next, see its Documentation
        idx = self.get_indices()
        patients_for_batch = [self._data[i] for i in idx]

        # initialize empty array for data and seg
        data = np.zeros((self.batch_size, self.num_modalities,
                         *self.patch_size), dtype=np.float32)
        seg = np.zeros((self.batch_size, 1, *self.patch_size),
                       dtype=np.float32)

        metadata = []
        patient_names = []

       # iterate over patients_for_batch and include them in the batch
        for i, j in enumerate(patients_for_batch):
            patient_data, patient_metadata = self.load_patient(j)

            # this will only pad patient_data if its shape is smaller than self.patch_size
            patient_data = pad_nd_image(patient_data, self.patch_size)

            # now random crop to self.patch_size
            # crop expects the data to be (b, c, x, y, z) but patient_data is (c, x, y, z) so we need to add one
            # dummy dimension in order for it to work (@Todo, could be improved)
            patient_data, patient_seg = crop(
                patient_data[:-1][None], patient_data[-1:][None], self.patch_size, crop_type="random")

            data[i] = patient_data[0]
            seg[i] = patient_seg[0]

            metadata.append(patient_metadata)
            patient_names.append(j)

        return {'data': data, 'seg': seg, 'metadata': metadata, 'names': patient_names}
Ejemplo n.º 3
0
    def generate_train_batch(self):

        subjects = self._data[0]
        subject_idx = int(random.uniform(0, len(subjects)))

        data, seg = load_training_data(self.Config, subjects[subject_idx])

        # Convert peaks to tensors if tensor model
        if self.Config.NR_OF_GRADIENTS == 18*self.Config.NR_SLICES:
            data = peak_utils.peaks_to_tensors(data)

        slice_direction = data_utils.slice_dir_to_int(self.Config.TRAINING_SLICE_DIRECTION)
        if data.shape[slice_direction] <= self.batch_size:
            print("INFO: Batch size bigger than nr of slices. Therefore sampling with replacement.")
            slice_idxs = np.random.choice(data.shape[slice_direction], self.batch_size, True, None)
        else:
            slice_idxs = np.random.choice(data.shape[slice_direction], self.batch_size, False, None)

        if self.Config.NR_SLICES > 1:
            x, y = data_utils.sample_Xslices(data, seg, slice_idxs, slice_direction=slice_direction,
                                             labels_type=self.Config.LABELS_TYPE, slice_window=self.Config.NR_SLICES)
        else:
            x, y = data_utils.sample_slices(data, seg, slice_idxs, slice_direction=slice_direction,
                                            labels_type=self.Config.LABELS_TYPE)


        # Can be replaced by crop
        # x = pad_nd_image(x, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # y = pad_nd_image(y, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # x = center_crop_2D_image_batched(x, self.Config.INPUT_DIM)
        # y = center_crop_2D_image_batched(y, self.Config.INPUT_DIM)

        # If want to convert e.g. 1.25mm (HCP) image to 2mm image (bb)
        # x, y = self._zoom_x_and_y(x, y, 0.67)  # very slow -> try spatial_transform, should be fast

        if self.Config.PAD_TO_SQUARE:
            #Crop and pad to input size
            x, y = crop(x, y, crop_size=self.Config.INPUT_DIM)  # does not work with img with batches and channels
        else:
            # Works -> results as good?
            # Will pad each axis to be multiple of 16. (Each sample can end up having different dimensions. Also x and y
            # can be different)
            # This is needed for Schizo dataset
            x = pad_nd_image(x, shape_must_be_divisible_by=(16, 16), mode='constant', kwargs={'constant_values': 0})
            y = pad_nd_image(y, shape_must_be_divisible_by=(16, 16), mode='constant', kwargs={'constant_values': 0})

        # Does not make it slower
        x = x.astype(np.float32)
        y = y.astype(np.float32)

        # possible optimization: sample slices from different patients and pad all to same size (size of biggest)

        data_dict = {"data": x,  # (batch_size, channels, x, y, [z])
                     "seg": y,
                     "slice_dir": slice_direction}  # (batch_size, channels, x, y, [z])
        return data_dict
Ejemplo n.º 4
0
    def generate_train_batch(self):

        # np.random.seed(1234)

        subjects = self._data[0]
        subject_idx = int(random.uniform(0, len(subjects)))     # len(subjects)-1 not needed because int always rounds to floor

        data, seg = load_training_data(self.Config, subjects[subject_idx])

        #Convert peaks to tensors if tensor model
        if self.Config.NR_OF_GRADIENTS == 18*self.Config.NR_SLICES:
            data = peak_utils.peaks_to_tensors(data)

        slice_direction = data_utils.slice_dir_to_int(self.Config.TRAINING_SLICE_DIRECTION)
        slice_idxs = np.random.choice(data.shape[slice_direction], self.batch_size, False, None)

        if self.Config.NR_SLICES > 1:
            x, y = data_utils.sample_Xslices(data, seg, slice_idxs, slice_direction=slice_direction,
                                             labels_type=self.Config.LABELS_TYPE, slice_window=self.Config.NR_SLICES)
        else:
            x, y = data_utils.sample_slices(data, seg, slice_idxs, slice_direction=slice_direction,
                                            labels_type=self.Config.LABELS_TYPE)


        # Can be replaced by crop
        # x = pad_nd_image(x, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # y = pad_nd_image(y, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # x = center_crop_2D_image_batched(x, self.Config.INPUT_DIM)
        # y = center_crop_2D_image_batched(y, self.Config.INPUT_DIM)

        #Crop and pad to input size
        x, y = crop(x, y, crop_size=self.Config.INPUT_DIM)  # does not work with img with batches and channels

        # Works -> results as good? -> todo: make the same way for inference!
        # This is needed for Schizo dataset
        # x = pad_nd_image(x, shape_must_be_divisible_by=(16, 16), mode='constant', kwargs={'constant_values': 0})
        # y = pad_nd_image(y, shape_must_be_divisible_by=(16, 16), mode='constant', kwargs={'constant_values': 0})

        # Does not make it slower
        x = x.astype(np.float32)
        y = y.astype(np.float32)  # if not doing this: during validation: ConnectionResetError: [Errno 104] Connection
                                  # reset by peer

        #possible optimization: sample slices from different patients and pad all to same size (size of biggest)

        data_dict = {"data": x,     # (batch_size, channels, x, y, [z])
                     "seg": y,
                     "slice_dir": slice_direction}      # (batch_size, channels, x, y, [z])
        return data_dict
Ejemplo n.º 5
0
    def generate_train_batch(self):
        idx = self.get_indices(
        )  # get batch_size subjects randomly, return a list
        data = np.zeros(
            (self.batch_size, self.nb_modalities, *self.patch_size),
            dtype=np.float32)

        for i, j in enumerate(idx):
            tmp_data = pad_nd_image(self._data[j]['img'], self.patch_size)
            cropped_data, cropped_seg = crop(tmp_data,
                                             None,
                                             self.patch_size,
                                             crop_type='random')
            data[i] = cropped_data[0]
        return {'data': data}  # (b, 2, d, h, w), (b, 1, d, h, w)
Ejemplo n.º 6
0
    def generate_train_batch(self):
        subjects = self._data[0]
        # subject_idx = int(random.uniform(0, len(subjects)))     # len(subjects)-1 not needed because int always rounds to floor
        subject_idxs = np.random.choice(len(subjects), self.batch_size, False,
                                        None)

        x = []
        y = []
        for subject_idx in subject_idxs:
            data, seg = load_training_data(
                self.Config, subjects[subject_idx])  # (x, y, z, channels)
            data = data.transpose(3, 0, 1, 2)  # channels have to be first
            seg = seg.transpose(3, 0, 1, 2)

            # Crop here instead of cropping entire batch at once to make each element in batch have same dimensions
            data, seg = crop(data[None, ...],
                             seg[None, ...],
                             crop_size=self.Config.INPUT_DIM)
            data = data.squeeze(axis=0)
            seg = seg.squeeze(axis=0)

            x.append(data)
            y.append(seg)

        x = np.array(x)
        y = np.array(y)

        # Can be replaced by crop -> shorter
        # x = pad_nd_image(x, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # y = pad_nd_image(y, self.Config.INPUT_DIM, mode='constant', kwargs={'constant_values': 0})
        # x = center_crop_3D_image_batched(x, self.Config.INPUT_DIM)
        # y = center_crop_3D_image_batched(y, self.Config.INPUT_DIM)

        # Crop and pad to input size
        # x, y = crop(x, y, crop_size=self.Config.INPUT_DIM)

        # This is needed for Schizo dataset, but only works with DAug=True
        # x = pad_nd_image(x, shape_must_be_divisible_by=(8, 8), mode='constant', kwargs={'constant_values': 0})
        # y = pad_nd_image(y, shape_must_be_divisible_by=(8, 8), mode='constant', kwargs={'constant_values': 0})

        x = x.astype(np.float32)
        y = y.astype(np.float32)

        data_dict = {
            "data": x,  # (batch_size, channels, x, y, [z])
            "seg": y
        }  # (batch_size, channels, x, y, [z])
        return data_dict
Ejemplo n.º 7
0
    def test_crop_roi(self):

        img = np.zeros((1, 3, 10, 10, 10))
        img[:, :, 2:4, 2:4, 2:4] = 1

        lbl = np.zeros((10, 10, 10))
        lbl[2:4, 2:4, 2:4] = 1
        crop_size = (5, 5, 5)
        lbl = np.expand_dims(np.expand_dims(lbl, axis=0), axis=0)

        for i in range(10):
            img_ret, lbl_ret = crop(img, lbl, crop_size, crop_type='roi')
            img_sum = np.sum(img)
            lbl_sum = np.sum(lbl)
            assert (img_sum == 3 * lbl_sum)
            assert (img_sum == np.sum(img_ret))
            assert (lbl_sum == np.sum(lbl_ret))
Ejemplo n.º 8
0
    def get_data_from_array(self, open_array):
        data = []
        fnames = []
        slice_idxs = []
        labels = []

        for slice in open_array:
            fn_name = self.files[slice[0]]

            numpy_array = np.load(fn_name, mmap_mode="r")

            numpy_slice = numpy_array[:, slice[1]]
            print("numpy_array shape :", numpy_array.shape,
                  "numpy_slice shape :", numpy_slice.shape)
            # this will only pad patient_data if its shape is smaller than self.patch_size
            patient_data = pad_nd_image(numpy_slice, self.patch_size)

            # now random crop to self.patch_size
            # crop expects the data to be (b, c, x, y, z) but patient_data is (c, x, y, z) so we need to add one
            # dummy dimension in order for it to work (@Todo, could be improved)
            patient_data, patient_seg = crop(patient_data[:-1][None],
                                             patient_data[-1:][None],
                                             self.patch_size,
                                             crop_type="random")

            dataslice = patient_data[0][0][None]
            dataslice = dataslice[0][None]
            segGt = patient_seg[0]
            #print("Before data shape :",dataslice.shape ,"sdpegGt :",segGt.shape)
            #dataslice = dataslice[0]
            print("After data shape :", dataslice.shape, "segGt :",
                  segGt.shape)
            data.append(dataslice)  # 'None' keeps the dimension

            if self.label_slice is not None:
                labels.append(segGt)  # 'None' keeps the dimension

            fnames.append(self.files[slice[0]])
            slice_idxs.append(slice[1])

        ret_dict = {'data': data, 'fnames': fnames, 'slice_idxs': slice_idxs}
        if self.label_slice is not None:
            ret_dict['seg'] = labels
        print("data shape :", len(data), "labels :", len(labels))
        return ret_dict
 def __call__(self, **data_dict):
     data = data_dict["data"]
     dimensionality = len(data.shape) - 2
     size = np.array(data.shape[-dimensionality:], dtype=int)
     zoom = 1 + (np.random.random() * (self.max_zoom - 1))
     samples = []
     for sample in np.split(data, data.shape[0], 0):
         if np.random.random() < self.p_per_sample:
             sample = crop(sample,
                           crop_size=(size / zoom).astype(int),
                           crop_type="random")[0]
             sample = augment_resize(sample.squeeze(0),
                                     sample_seg=None,
                                     target_size=size.tolist())[0]
         else:
             sample = sample.squeeze(0)
         samples.append(sample)
     data = np.stack(samples)
     data_dict["data"] = data
     return data_dict
Ejemplo n.º 10
0
    def generate_train_batch(self):

        idx = self.get_indices()
        patients_for_batch = [self._data[i] for i in idx]

        data = np.zeros((self.batch_size, self.num_modalities, *self.patch_size), dtype=np.float32)

        for i, _ in enumerate(patients_for_batch):
            patient_data = patients_for_batch[i]
            if not self.crop:
                patient_data = resize(patient_data, (patient_data.shape[0],)+self.patch_size,
                                      anti_aliasing=True)
                data[i] = patient_data
            else:

                # this will only pad patient_data if its shape is smaller than self.patch_size
                patient_data = pad_nd_image(patient_data, self.patch_size)

                # now random crop to self.patch_size

                patient_data = crop(patient_data[None], crop_size=self.patch_size, crop_type="center")
                data[i] = patient_data[0]

        return {'data': data}
Ejemplo n.º 11
0
    def generate_train_batch(self):
        # DataLoader has its own methods for selecting what patients to use next, see its Documentation
        idx = self.get_indices()
        patients_for_batch = [self._data[i] for i in idx]

        print(idx)
        patch_size = None
        if self.patch_size == None:
            shapes = []
            for i in patients_for_batch:
                patient_data, _ = self.load_patient(i)
                shapes.append(patient_data[0].shape)
            patch_size = np.max(shapes, 0)
            patch_size = (patch_size[0] + 16 - patch_size[0] % 16,
                          patch_size[1] + 16 - patch_size[1] % 16,
                          patch_size[2] + 16 - patch_size[2] % 16)
        else:
            patch_size = self.patch_size

        # initialize empty array for data and seg
        data = np.zeros((self.batch_size, self.num_modalities, *patch_size),
                        dtype=np.float32)
        seg = np.zeros((self.batch_size, 1, *patch_size), dtype=np.float32)

        metadata = []
        patient_names = []

        # iterate over patients_for_batch and include them in the batch
        for i, j in enumerate(patients_for_batch):
            patient_data, patient_metadata = self.load_patient(j)
            if self.patch_size is not None:
                # this will only pad patient_data if its shape is smaller than self.patch_size
                patient_data = pad_nd_image(patient_data, patch_size)

                # now random crop to self.patch_size
                # crop expects the data to be (b, c, x, y, z) but patient_data is (c, x, y, z) so we need to add one
                # dummy dimension in order for it to work (@Todo, could be improved)
                patient_data, patient_seg = crop(patient_data[:-1][None],
                                                 patient_data[-1:][None],
                                                 patch_size,
                                                 crop_type="random")

                data[i] = patient_data[0]
                seg[i] = patient_seg[0]

            else:
                for j in range(len(patient_data)):
                    if j != len(patient_data) - 1:
                        data[i][j] = resize_image_by_padding(
                            patient_data[j], patch_size)
                    else:
                        seg[i][0] = resize_image_by_padding(
                            patient_data[j], patch_size)

            metadata.append(patient_metadata)
            patient_names.append(j)

        return {
            'data': data,
            'seg': seg,
            'metadata': metadata,
            'names': patient_names
        }
def augment_spatial(data,
                    seg,
                    patch_size,
                    patch_center_dist_from_border=30,
                    do_elastic_deform=True,
                    alpha=(0., 1000.),
                    sigma=(10., 13.),
                    do_rotation=True,
                    angle_x=(0, 2 * np.pi),
                    angle_y=(0, 2 * np.pi),
                    angle_z=(0, 2 * np.pi),
                    do_scale=True,
                    scale=(0.75, 1.25),
                    border_mode_data='nearest',
                    border_cval_data=0,
                    order_data=3,
                    border_mode_seg='constant',
                    border_cval_seg=0,
                    order_seg=0,
                    crop_mode='random',
                    p_el_per_sample=1,
                    p_scale_per_sample=1,
                    p_rot_per_sample=1):
    dim = len(patch_size)
    seg_result = None
    if seg is not None:
        if dim == 2:
            seg_result = np.zeros(
                (seg.shape[0], seg.shape[1], patch_size[0], patch_size[1]),
                dtype=np.float32)
        else:
            seg_result = np.zeros((seg.shape[0], seg.shape[1], patch_size[0],
                                   patch_size[1], patch_size[2]),
                                  dtype=np.float32)

    if dim == 2:
        data_result = np.zeros(
            (data.shape[0], data.shape[1], patch_size[0], patch_size[1]),
            dtype=np.float32)
    else:
        data_result = np.zeros((data.shape[0], data.shape[1], patch_size[0],
                                patch_size[1], patch_size[2]),
                               dtype=np.float32)

    if not isinstance(patch_center_dist_from_border,
                      (list, tuple, np.ndarray)):
        patch_center_dist_from_border = dim * [patch_center_dist_from_border]

    for sample_id in range(data.shape[0]):
        coords = create_zero_centered_coordinate_mesh(patch_size)
        modified_coords = False

        if np.random.uniform() < p_el_per_sample and do_elastic_deform:
            a = np.random.uniform(alpha[0], alpha[1])
            s = np.random.uniform(sigma[0], sigma[1])
            coords = elastic_deform_coordinates(coords, a, s)
            modified_coords = True

        if np.random.uniform() < p_rot_per_sample and do_rotation:
            if angle_x[0] == angle_x[1]:
                a_x = angle_x[0]
            else:
                a_x = np.random.uniform(angle_x[0], angle_x[1])
            if dim == 3:
                if angle_y[0] == angle_y[1]:
                    a_y = angle_y[0]
                else:
                    a_y = np.random.uniform(angle_y[0], angle_y[1])
                if angle_z[0] == angle_z[1]:
                    a_z = angle_z[0]
                else:
                    a_z = np.random.uniform(angle_z[0], angle_z[1])
                coords = rotate_coords_3d(coords, a_x, a_y, a_z)
            else:
                coords = rotate_coords_2d(coords, a_x)
            modified_coords = True

        if np.random.uniform() < p_scale_per_sample and do_scale:
            if np.random.random() < 0.5 and scale[0] < 1:
                sc = np.random.uniform(scale[0], 1)
            else:
                sc = np.random.uniform(max(scale[0], 1), scale[1])
            coords = scale_coords(coords, sc)
            modified_coords = True

        # now find a nice center location
        if modified_coords:
            if crop_mode == 'roi':
                lbs = get_lbls_for_roi_crop(patch_size, data.shape,
                                            seg[sample_id, 0])

            for d in range(dim):
                if crop_mode == 'roi':
                    ctr = int(lbs[d] + np.round(patch_size[d] / 2.))
                elif crop_mode == 'center':
                    ctr = int(np.round(data.shape[d + 2] / 2.))
                else:
                    ctr = np.random.uniform(
                        patch_center_dist_from_border[d],
                        data.shape[d + 2] - patch_center_dist_from_border[d])

                coords[d] += ctr
            for channel_id in range(data.shape[1]):
                data_result[sample_id, channel_id] = interpolate_img(
                    data[sample_id, channel_id],
                    coords,
                    order_data,
                    border_mode_data,
                    cval=border_cval_data)
            if seg is not None:
                for channel_id in range(seg.shape[1]):
                    seg_result[sample_id, channel_id] = interpolate_img(
                        seg[sample_id, channel_id],
                        coords,
                        order_seg,
                        border_mode_seg,
                        cval=border_cval_seg,
                        is_seg=True)
        else:
            if seg is None:
                s = None
            else:
                s = seg[sample_id:sample_id + 1]

            if crop_mode == 'roi':
                d, s = crop(data[sample_id:sample_id + 1],
                            s,
                            patch_size,
                            crop_type='roi')
            elif crop_mode == 'center':
                d, s = center_crop_aug(data[sample_id:sample_id + 1],
                                       patch_size, s)
            else:  #crop_mode ==  'random'
                margin = [
                    patch_center_dist_from_border[d] - patch_size[d] // 2
                    for d in range(dim)
                ]
                d, s = random_crop_aug(data[sample_id:sample_id + 1], s,
                                       patch_size, margin)

            data_result[sample_id] = d[0]
            if seg is not None:
                seg_result[sample_id] = s[0]

    return data_result, seg_result