Skip to content

Aug batchgenerators

BatchgeneratorsAugmentation ¤

The Batchgenerators Augmentation class performs diverse augmentation methods on given numpy array. The class acts as an easy to use function/interface for applying all types of augmentations with just one function call.

The class can be configured beforehand by selecting desired augmentation techniques and method ranges or strength. Afterwards, the class is passed to the DataGenerator which utilizes it during batch generation.

The specific configurations of selected methods can be adjusted by class variables.

Build on top of the library

Batchgenerators from the DKFZ - https://github.com/MIC-DKFZ/batchgenerators

Reference - Publication

Isensee Fabian, Jäger Paul, Wasserthal Jakob, Zimmerer David, Petersen Jens, Kohl Simon, Schock Justus, Klein Andre, Roß Tobias, Wirkert Sebastian, Neher Peter, Dinkelacker Stefan, Köhler Gregor, Maier-Hein Klaus (2020). batchgenerators - a python framework for data augmentation. doi:10.5281/zenodo.3632567

Source code in aucmedi/data_processing/augmentation/aug_batchgenerators.py
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
class BatchgeneratorsAugmentation():
    """ The Batchgenerators Augmentation class performs diverse augmentation methods on given
        numpy array. The class acts as an easy to use function/interface for applying
        all types of augmentations with just one function call.

    The class can be configured beforehand by selecting desired augmentation techniques
    and method ranges or strength.
    Afterwards, the class is passed to the [DataGenerator][aucmedi.data_processing.data_generator.DataGenerator]
    which utilizes it during batch generation.

    The specific configurations of selected methods can be adjusted by class variables.

    ???+ abstract "Build on top of the library"
        Batchgenerators from the DKFZ - https://github.com/MIC-DKFZ/batchgenerators

    ???+ abstract "Reference - Publication"
        Isensee Fabian, Jäger Paul, Wasserthal Jakob, Zimmerer David, Petersen Jens, Kohl Simon,
        Schock Justus, Klein Andre, Roß Tobias, Wirkert Sebastian, Neher Peter, Dinkelacker Stefan,
        Köhler Gregor, Maier-Hein Klaus (2020). batchgenerators - a python framework for data
        augmentation. doi:10.5281/zenodo.3632567
    """
    #-----------------------------------------------------#
    #              Augmentation Configuration             #
    #-----------------------------------------------------#
    # Define augmentation operator
    operator = None
    # Option for augmentation refinement (clipping)
    refine = True
    # Augmentation: Mirror
    aug_mirror = False
    aug_mirror_p = 0.5
    aug_mirror_axes = (0, 1, 2)
    # Augmentation: 90 degree rotate
    aug_rotate = False
    aug_rotate_p = 0.5
    aug_rotate_angleX = (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi)
    aug_rotate_angleY = (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi)
    aug_rotate_angleZ = (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi)
    # Augmentation: Brightness
    aug_brightness = False
    aug_brightness_p = 0.5
    aug_brightness_range = (0.5, 2)
    aug_brightness_per_channel = False
    # Augmentation: Contrast
    aug_contrast = False
    aug_contrast_p = 0.5
    aug_contrast_range = (0.3, 3.0)
    aug_contrast_per_channel = False
    aug_contrast_preserverange = True
    # Augmentation: Scale
    aug_scale = False
    aug_scale_p = 0.5
    aug_scale_range = (0.85, 1.25)
    # Augmentation: Gaussian Noise
    aug_gaussianNoise = False
    aug_gaussianNoise_p = 0.5
    aug_gaussianNoise_range = (0.0, 0.05)
    # Augmentation: Gamma
    aug_gamma = False
    aug_gamma_p = 0.5
    aug_gamma_range = (0.7, 1.5)
    aug_gamma_per_channel = False
    # Augmentation: Elastic Transformation
    aug_elasticTransform = False
    aug_elasticTransform_p = 0.5
    aug_elasticTransform_alpha = (0.0, 900.0)
    aug_elasticTransform_sigma = (9.0, 13.0)

    #-----------------------------------------------------#
    #                    Initialization                   #
    #-----------------------------------------------------#
    def __init__(self, image_shape, mirror=False, rotate=True, scale=True,
                 elastic_transform=False, gaussian_noise=True,
                 brightness=True, contrast=True, gamma=True):
        """ Initialization function for the Batchgenerators Augmentation interface.

        With boolean switches, it is possible to selected desired augmentation techniques.
        Recommended augmentation configurations are defined as class variables.
        Of course, these configs can be adjusted if needed.

        Args:
            image_shape (tuple of int):     Target shape of image, which will be passed to the neural network model.
            mirror (bool):                  Boolean, whether mirroring should be performed as data augmentation.
            rotate (bool):                  Boolean, whether rotations should be performed as data augmentation.
            scale (bool):                   Boolean, whether scaling should be performed as data augmentation.
            elastic_transform (bool):       Boolean, whether elastic deformation should be performed as data augmentation.
            gaussian_noise (bool):          Boolean, whether Gaussian noise should be added as data augmentation.
            brightness (bool):              Boolean, whether brightness changes should be added as data augmentation.
            contrast (bool):                Boolean, whether contrast changes should be added as data augmentation.
            gamma (bool):                   Boolean, whether gamma changes should be added as data augmentation.

        !!! warning
            If class variables (attributes) are modified, the internal augmentation operator
            has to be rebuild via the following call:

            ```python
            # initialize
            aug = BatchgeneratorsAugmentation(model.meta_input, mirror=True)

            # set probability to 100% = always
            aug.aug_mirror_p = 1.0
            # rebuild
            aug.build()
            ```

        Attributes:
            refine (bool):                  Boolean, whether clipping to [0,255] should be performed if outside of range.
            aug_mirror_p (float):           Probability of mirroring application if activated. Default=0.5.
            aug_rotate_p (float):           Probability of rotation application if activated. Default=0.5.
            aug_scale_p (float):            Probability of scaling application if activated. Default=0.5.
            aug_elasticTransform_p (float): Probability of elastic deformation application if activated. Default=0.5.
            aug_gaussianNoise_p (float):    Probability of Gaussian noise application if activated. Default=0.5.
            aug_brightness_p (float):       Probability of brightness application if activated. Default=0.5.
            aug_contrast_p (float):         Probability of contrast application if activated. Default=0.5.
            aug_gamma_p (float):            Probability of gamma application if activated. Default=0.5.
        """
        # Cache class variables
        self.image_shape = image_shape
        self.aug_mirror = mirror
        self.aug_rotate = rotate
        self.aug_scale = scale
        self.aug_elasticTransform = elastic_transform
        self.aug_gaussianNoise = gaussian_noise
        self.aug_brightness = brightness
        self.aug_contrast = contrast
        self.aug_gamma = gamma
        # Build augmentation operator
        self.build()

    #-----------------------------------------------------#
    #               Batchgenerators Builder               #
    #-----------------------------------------------------#
    def build(self):
        """ Builds the batchgenerators augmentator by initializing  all transformations.

        The activated transformation and their configurations are defined as
        class variables.

        -> Builds a new self.operator
        """
        # Initialize transform list
        transforms = []
        # Fill transform list
        if self.aug_mirror:
            tf = MirrorTransform(axes=self.aug_mirror_axes,
                                 p_per_sample=self.aug_mirror_p)
            transforms.append(tf)
        if self.aug_contrast:
            tf = ContrastAugmentationTransform(
                                 self.aug_contrast_range,
                                 preserve_range=self.aug_contrast_preserverange,
                                 per_channel=self.aug_contrast_per_channel,
                                 p_per_sample=self.aug_contrast_p)
            transforms.append(tf)
        if self.aug_brightness:
            tf = BrightnessMultiplicativeTransform(
                                 self.aug_brightness_range,
                                 per_channel=self.aug_brightness_per_channel,
                                 p_per_sample=self.aug_brightness_p)
            transforms.append(tf)
        if self.aug_gaussianNoise:
            tf = GaussianNoiseTransform(self.aug_gaussianNoise_range,
                                        p_per_sample=self.aug_gaussianNoise_p)
            transforms.append(tf)
        if self.aug_gamma:
            tf = GammaTransform(self.aug_gamma_range,
                                invert_image=False,
                                per_channel=self.aug_gamma_per_channel,
                                retain_stats=True,
                                p_per_sample=self.aug_gamma_p)
            transforms.append(tf)
        if self.aug_rotate or self.aug_scale or self.aug_elasticTransform:
            tf = SpatialTransform(self.image_shape,
                                  [i // 2 for i in self.image_shape],
                                  do_elastic_deform=self.aug_elasticTransform,
                                  alpha=self.aug_elasticTransform_alpha,
                                  sigma=self.aug_elasticTransform_sigma,
                                  do_rotation=self.aug_rotate,
                                  angle_x=self.aug_rotate_angleX,
                                  angle_y=self.aug_rotate_angleY,
                                  angle_z=self.aug_rotate_angleZ,
                                  do_scale=self.aug_scale,
                                  scale=self.aug_scale_range,
                                  border_mode_data='constant',
                                  border_cval_data=0,
                                  border_mode_seg='constant',
                                  border_cval_seg=0,
                                  order_data=3, order_seg=0,
                                  p_el_per_sample=self.aug_elasticTransform_p,
                                  p_rot_per_sample=self.aug_rotate_p,
                                  p_scale_per_sample=self.aug_scale_p,
                                  random_crop=False)
            transforms.append(tf)

        # Compose transforms
        self.operator = Compose(transforms)

    #-----------------------------------------------------#
    #                 Perform Augmentation                #
    #-----------------------------------------------------#
    def apply(self, image):
        """ Performs image augmentation with defined configuration on an image.

        This **internal** function is called in the DataGenerator during batch generation.

        Args:
            image (numpy.ndarray):          An image encoded as NumPy array with shape (z, y, x, channels).
        Returns:
            aug_image (numpy.ndarray):      An augmented / transformed image.
        """
        # Convert image to batchgenerators format (float32, channel first and with batch axis)
        image_bg = image.astype(np.float32)
        image_bg = np.expand_dims(image_bg, axis=0)
        image_bg = np.moveaxis(image_bg, -1, 1)
        # Perform image augmentation
        aug_image = self.operator(data=image_bg)["data"]
        # Remove batch axis and return to channel last
        aug_image = np.moveaxis(aug_image, 1, -1)
        aug_image = np.squeeze(aug_image, axis=0)
        # Perform clipping if image is out of grayscale/RGB encodings
        if self.refine and (np.min(aug_image) < 0 or np.max(aug_image) > 255):
            aug_image = np.clip(aug_image, a_min=0, a_max=255)
        # Return augmented image
        return aug_image

__init__(image_shape, mirror=False, rotate=True, scale=True, elastic_transform=False, gaussian_noise=True, brightness=True, contrast=True, gamma=True) ¤

Initialization function for the Batchgenerators Augmentation interface.

With boolean switches, it is possible to selected desired augmentation techniques. Recommended augmentation configurations are defined as class variables. Of course, these configs can be adjusted if needed.

Parameters:

Name Type Description Default
image_shape tuple of int

Target shape of image, which will be passed to the neural network model.

required
mirror bool

Boolean, whether mirroring should be performed as data augmentation.

False
rotate bool

Boolean, whether rotations should be performed as data augmentation.

True
scale bool

Boolean, whether scaling should be performed as data augmentation.

True
elastic_transform bool

Boolean, whether elastic deformation should be performed as data augmentation.

False
gaussian_noise bool

Boolean, whether Gaussian noise should be added as data augmentation.

True
brightness bool

Boolean, whether brightness changes should be added as data augmentation.

True
contrast bool

Boolean, whether contrast changes should be added as data augmentation.

True
gamma bool

Boolean, whether gamma changes should be added as data augmentation.

True

Warning

If class variables (attributes) are modified, the internal augmentation operator has to be rebuild via the following call:

# initialize
aug = BatchgeneratorsAugmentation(model.meta_input, mirror=True)

# set probability to 100% = always
aug.aug_mirror_p = 1.0
# rebuild
aug.build()

Attributes:

Name Type Description
refine bool

Boolean, whether clipping to [0,255] should be performed if outside of range.

aug_mirror_p float

Probability of mirroring application if activated. Default=0.5.

aug_rotate_p float

Probability of rotation application if activated. Default=0.5.

aug_scale_p float

Probability of scaling application if activated. Default=0.5.

aug_elasticTransform_p float

Probability of elastic deformation application if activated. Default=0.5.

aug_gaussianNoise_p float

Probability of Gaussian noise application if activated. Default=0.5.

aug_brightness_p float

Probability of brightness application if activated. Default=0.5.

aug_contrast_p float

Probability of contrast application if activated. Default=0.5.

aug_gamma_p float

Probability of gamma application if activated. Default=0.5.

Source code in aucmedi/data_processing/augmentation/aug_batchgenerators.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
def __init__(self, image_shape, mirror=False, rotate=True, scale=True,
             elastic_transform=False, gaussian_noise=True,
             brightness=True, contrast=True, gamma=True):
    """ Initialization function for the Batchgenerators Augmentation interface.

    With boolean switches, it is possible to selected desired augmentation techniques.
    Recommended augmentation configurations are defined as class variables.
    Of course, these configs can be adjusted if needed.

    Args:
        image_shape (tuple of int):     Target shape of image, which will be passed to the neural network model.
        mirror (bool):                  Boolean, whether mirroring should be performed as data augmentation.
        rotate (bool):                  Boolean, whether rotations should be performed as data augmentation.
        scale (bool):                   Boolean, whether scaling should be performed as data augmentation.
        elastic_transform (bool):       Boolean, whether elastic deformation should be performed as data augmentation.
        gaussian_noise (bool):          Boolean, whether Gaussian noise should be added as data augmentation.
        brightness (bool):              Boolean, whether brightness changes should be added as data augmentation.
        contrast (bool):                Boolean, whether contrast changes should be added as data augmentation.
        gamma (bool):                   Boolean, whether gamma changes should be added as data augmentation.

    !!! warning
        If class variables (attributes) are modified, the internal augmentation operator
        has to be rebuild via the following call:

        ```python
        # initialize
        aug = BatchgeneratorsAugmentation(model.meta_input, mirror=True)

        # set probability to 100% = always
        aug.aug_mirror_p = 1.0
        # rebuild
        aug.build()
        ```

    Attributes:
        refine (bool):                  Boolean, whether clipping to [0,255] should be performed if outside of range.
        aug_mirror_p (float):           Probability of mirroring application if activated. Default=0.5.
        aug_rotate_p (float):           Probability of rotation application if activated. Default=0.5.
        aug_scale_p (float):            Probability of scaling application if activated. Default=0.5.
        aug_elasticTransform_p (float): Probability of elastic deformation application if activated. Default=0.5.
        aug_gaussianNoise_p (float):    Probability of Gaussian noise application if activated. Default=0.5.
        aug_brightness_p (float):       Probability of brightness application if activated. Default=0.5.
        aug_contrast_p (float):         Probability of contrast application if activated. Default=0.5.
        aug_gamma_p (float):            Probability of gamma application if activated. Default=0.5.
    """
    # Cache class variables
    self.image_shape = image_shape
    self.aug_mirror = mirror
    self.aug_rotate = rotate
    self.aug_scale = scale
    self.aug_elasticTransform = elastic_transform
    self.aug_gaussianNoise = gaussian_noise
    self.aug_brightness = brightness
    self.aug_contrast = contrast
    self.aug_gamma = gamma
    # Build augmentation operator
    self.build()

apply(image) ¤

Performs image augmentation with defined configuration on an image.

This internal function is called in the DataGenerator during batch generation.

Parameters:

Name Type Description Default
image numpy.ndarray

An image encoded as NumPy array with shape (z, y, x, channels).

required

Returns:

Name Type Description
aug_image numpy.ndarray

An augmented / transformed image.

Source code in aucmedi/data_processing/augmentation/aug_batchgenerators.py
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
def apply(self, image):
    """ Performs image augmentation with defined configuration on an image.

    This **internal** function is called in the DataGenerator during batch generation.

    Args:
        image (numpy.ndarray):          An image encoded as NumPy array with shape (z, y, x, channels).
    Returns:
        aug_image (numpy.ndarray):      An augmented / transformed image.
    """
    # Convert image to batchgenerators format (float32, channel first and with batch axis)
    image_bg = image.astype(np.float32)
    image_bg = np.expand_dims(image_bg, axis=0)
    image_bg = np.moveaxis(image_bg, -1, 1)
    # Perform image augmentation
    aug_image = self.operator(data=image_bg)["data"]
    # Remove batch axis and return to channel last
    aug_image = np.moveaxis(aug_image, 1, -1)
    aug_image = np.squeeze(aug_image, axis=0)
    # Perform clipping if image is out of grayscale/RGB encodings
    if self.refine and (np.min(aug_image) < 0 or np.max(aug_image) > 255):
        aug_image = np.clip(aug_image, a_min=0, a_max=255)
    # Return augmented image
    return aug_image

build() ¤

Builds the batchgenerators augmentator by initializing all transformations.

The activated transformation and their configurations are defined as class variables.

-> Builds a new self.operator

Source code in aucmedi/data_processing/augmentation/aug_batchgenerators.py
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
def build(self):
    """ Builds the batchgenerators augmentator by initializing  all transformations.

    The activated transformation and their configurations are defined as
    class variables.

    -> Builds a new self.operator
    """
    # Initialize transform list
    transforms = []
    # Fill transform list
    if self.aug_mirror:
        tf = MirrorTransform(axes=self.aug_mirror_axes,
                             p_per_sample=self.aug_mirror_p)
        transforms.append(tf)
    if self.aug_contrast:
        tf = ContrastAugmentationTransform(
                             self.aug_contrast_range,
                             preserve_range=self.aug_contrast_preserverange,
                             per_channel=self.aug_contrast_per_channel,
                             p_per_sample=self.aug_contrast_p)
        transforms.append(tf)
    if self.aug_brightness:
        tf = BrightnessMultiplicativeTransform(
                             self.aug_brightness_range,
                             per_channel=self.aug_brightness_per_channel,
                             p_per_sample=self.aug_brightness_p)
        transforms.append(tf)
    if self.aug_gaussianNoise:
        tf = GaussianNoiseTransform(self.aug_gaussianNoise_range,
                                    p_per_sample=self.aug_gaussianNoise_p)
        transforms.append(tf)
    if self.aug_gamma:
        tf = GammaTransform(self.aug_gamma_range,
                            invert_image=False,
                            per_channel=self.aug_gamma_per_channel,
                            retain_stats=True,
                            p_per_sample=self.aug_gamma_p)
        transforms.append(tf)
    if self.aug_rotate or self.aug_scale or self.aug_elasticTransform:
        tf = SpatialTransform(self.image_shape,
                              [i // 2 for i in self.image_shape],
                              do_elastic_deform=self.aug_elasticTransform,
                              alpha=self.aug_elasticTransform_alpha,
                              sigma=self.aug_elasticTransform_sigma,
                              do_rotation=self.aug_rotate,
                              angle_x=self.aug_rotate_angleX,
                              angle_y=self.aug_rotate_angleY,
                              angle_z=self.aug_rotate_angleZ,
                              do_scale=self.aug_scale,
                              scale=self.aug_scale_range,
                              border_mode_data='constant',
                              border_cval_data=0,
                              border_mode_seg='constant',
                              border_cval_seg=0,
                              order_data=3, order_seg=0,
                              p_el_per_sample=self.aug_elasticTransform_p,
                              p_rot_per_sample=self.aug_rotate_p,
                              p_scale_per_sample=self.aug_scale_p,
                              random_crop=False)
        transforms.append(tf)

    # Compose transforms
    self.operator = Compose(transforms)