|
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)) |