Switch to unified view

a b/scripts/tutorials/2-generation_explained.py
1
"""
2
3
This script explains how the different parameters controlling the generation of the synthetic data.
4
These parameters will be reused in the training function, but we describe them here, as the synthetic images are saved,
5
and thus can be visualised.
6
Note that most of the parameters here are set to their default value, but we show them nonetheless, just to explain
7
their effect. Moreover, we encourage the user to play with them to get a sense of their impact on the generation.
8
9
10
11
If you use this code, please cite one of the SynthSeg papers:
12
https://github.com/BBillot/SynthSeg/blob/master/bibtex.bib
13
14
Copyright 2020 Benjamin Billot
15
16
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
17
compliance with the License. You may obtain a copy of the License at
18
https://www.apache.org/licenses/LICENSE-2.0
19
Unless required by applicable law or agreed to in writing, software distributed under the License is
20
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
21
implied. See the License for the specific language governing permissions and limitations under the
22
License.
23
"""
24
25
26
import os
27
from ext.lab2im import utils
28
from SynthSeg.brain_generator import BrainGenerator
29
30
# script parameters
31
n_examples = 5  # number of examples to generate in this script
32
result_dir = './outputs_tutorial_2'  # folder where examples will be saved
33
34
35
# ---------- Input label maps and associated values ----------
36
37
# folder containing label maps to generate images from (note that they must have a ".nii", ".nii.gz" or ".mgz" format)
38
path_label_map = '../../data/training_label_maps'
39
40
# Here we specify the structures in the label maps for which we want to generate intensities.
41
# This is given as a list of label values, which do not necessarily need to be present in every label map.
42
# However, these labels must follow a specific order: first the background, and then all the other labels. Moreover, if
43
# 1) the label maps contain some right/left-specific label values, and 2) we activate flipping augmentation (which is
44
# true by default), then the rest of the labels must follow a strict order:
45
# first the non-sided labels (i.e. those which are not right/left specific), then all the left labels, and finally the
46
# corresponding right labels (in the same order as the left ones). Please make sure each that each sided label has a
47
# right and a left value (this is essential!!!).
48
#
49
# Example: generation_labels = [0,    # background
50
#                               24,   # CSF
51
#                               507,  # extra-cerebral soft tissues
52
#                               2,    # left white matter
53
#                               3,    # left cerebral cortex
54
#                               4,    # left lateral ventricle
55
#                               17,   # left hippocampus
56
#                               25,   # left lesions
57
#                               41,   # right white matter
58
#                               42,   # right cerebral cortex
59
#                               43,   # right lateral ventricle
60
#                               53,   # right hippocampus
61
#                               57]   # right lesions
62
# Note that plenty of structures are not represented here..... but it's just an example ! :)
63
generation_labels = '../../data/labels_classes_priors/generation_labels.npy'
64
65
66
# We also have to specify the number of non-sided labels in order to differentiate them from the labels with
67
# right/left values.
68
# Example: (continuing the previous one): in this example it would be 3 (background, CSF, extra-cerebral soft tissues).
69
n_neutral_labels = 18
70
71
# By default, the output label maps (i.e. the target segmentations) contain all the labels used for generation.
72
# However, we may want not to predict all the generation labels (e.g. extra-cerebral soft tissues).
73
# For this reason, we specify here the target segmentation label corresponding to every generation structure.
74
# This new list must have the same length as generation_labels, and follow the same order.
75
#
76
# Example: (continuing the previous one)  generation_labels = [0, 24, 507, 2, 3, 4, 17, 25, 41, 42, 43, 53, 57]
77
#                                             output_labels = [0,  0,  0,  2, 3, 4, 17,  2, 41, 42, 43, 53, 41]
78
# Note that in this example the labels 24 (CSF), and 507 (extra-cerebral soft tissues) are not predicted, or said
79
# differently they are segmented as background.
80
# Also, the left and right lesions (labels 25 and 57) are segmented as left and right white matter (labels 2 and 41).
81
output_labels = '../../data/labels_classes_priors/synthseg_segmentation_labels.npy'
82
83
84
# ---------- Shape and resolution of the outputs ----------
85
86
# number of channel to synthesise for multi-modality settings. Set this to 1 (default) in the uni-modality scenario.
87
n_channels = 1
88
89
# We have the possibility to generate training examples at a different resolution than the training label maps (e.g.
90
# when using ultra HR training label maps). Here we want to generate at the same resolution as the training label maps,
91
# so we set this to None.
92
target_res = None
93
94
# The generative model offers the possibility to randomly crop the training examples to a given size.
95
# Here we crop them to 160^3, such that the produced images fit on the GPU during training.
96
output_shape = 160
97
98
99
# ---------- GMM sampling parameters ----------
100
101
# Here we use uniform prior distribution to sample the means/stds of the GMM. Because we don't specify prior_means and
102
# prior_stds, those priors will have default bounds of [0, 250], and [0, 35]. Those values enable to generate a wide
103
# range of contrasts (often unrealistic), which will make the segmentation network contrast-agnostic.
104
prior_distributions = 'uniform'
105
106
# We regroup labels with similar tissue types into K "classes", so that intensities of similar regions are sampled
107
# from the same Gaussian distribution. This is achieved by providing a list indicating the class of each label.
108
# It should have the same length as generation_labels, and follow the same order. Importantly the class values must be
109
# between 0 and K-1, where K is the total number of different classes.
110
#
111
# Example: (continuing the previous one)  generation_labels = [0, 24, 507, 2, 3, 4, 17, 25, 41, 42, 43, 53, 57]
112
#                                        generation_classes = [0,  1,   2, 3, 4, 5,  4,  6,  7,  8,  9,  8, 10]
113
# In this example labels 3 and 17 are in the same *class* 4 (that has nothing to do with *label* 4), and thus will be
114
# associated to the same Gaussian distribution when sampling the GMM.
115
generation_classes = '../../data/labels_classes_priors/generation_classes.npy'
116
117
118
# ---------- Spatial augmentation ----------
119
120
# We now introduce some parameters concerning the spatial deformation. They enable to set the range of the uniform
121
# distribution from which the corresponding parameters are selected.
122
# We note that because the label maps will be resampled with nearest neighbour interpolation, they can look less smooth
123
# than the original segmentations.
124
125
flipping = True  # enable right/left flipping
126
scaling_bounds = 0.2  # the scaling coefficients will be sampled from U(1-scaling_bounds; 1+scaling_bounds)
127
rotation_bounds = 15  # the rotation angles will be sampled from U(-rotation_bounds; rotation_bounds)
128
shearing_bounds = 0.012  # the shearing coefficients will be sampled from U(-shearing_bounds; shearing_bounds)
129
translation_bounds = False  # no translation is performed, as this is already modelled by the random cropping
130
nonlin_std = 4.  # this controls the maximum elastic deformation (higher = more deformation)
131
bias_field_std = 0.7  # this controls the maximum bias field corruption (higher = more bias)
132
133
134
# ---------- Resolution parameters ----------
135
136
# This enables us to randomise the resolution of the produces images.
137
# Although being only one parameter, this is crucial !!
138
randomise_res = True
139
140
141
# ------------------------------------------------------ Generate ------------------------------------------------------
142
143
# instantiate BrainGenerator object
144
brain_generator = BrainGenerator(labels_dir=path_label_map,
145
                                 generation_labels=generation_labels,
146
                                 n_neutral_labels=n_neutral_labels,
147
                                 prior_distributions=prior_distributions,
148
                                 generation_classes=generation_classes,
149
                                 output_labels=output_labels,
150
                                 n_channels=n_channels,
151
                                 target_res=target_res,
152
                                 output_shape=output_shape,
153
                                 flipping=flipping,
154
                                 scaling_bounds=scaling_bounds,
155
                                 rotation_bounds=rotation_bounds,
156
                                 shearing_bounds=shearing_bounds,
157
                                 translation_bounds=translation_bounds,
158
                                 nonlin_std=nonlin_std,
159
                                 bias_field_std=bias_field_std,
160
                                 randomise_res=randomise_res)
161
162
for n in range(n_examples):
163
164
    # generate new image and corresponding labels
165
    im, lab = brain_generator.generate_brain()
166
167
    # save output image and label map
168
    utils.save_volume(im, brain_generator.aff, brain_generator.header,
169
                      os.path.join(result_dir, 'image_%s.nii.gz' % n))
170
    utils.save_volume(lab, brain_generator.aff, brain_generator.header,
171
                      os.path.join(result_dir, 'labels_%s.nii.gz' % n))