katielink commited on
Commit
4f26579
1 Parent(s): f8233c8

Initial version

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ models/model.ts filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ tags:
3
+ - monai
4
+ - medical
5
+ library_name: monai
6
+ license: unknown
7
+ ---
8
+
9
+ # 3 Label Ventricular Segmentation
10
+
11
+ This network segments cardiac ventricle in 2D short axis MR images. The left ventricular pool is class 1, left ventricular myocardium class 2, and right ventricular pool class 3. Full cycle segmentation with this network is possible although much of the training data is composed of segmented end-diastole images. The input to the network is single 2D images thus segmenting whole time-dependent volumes consists of multiple inference operations.
12
+
13
+ The network and training scheme are essentially identical to that described in:
14
+
15
+ `Kerfoot E., Clough J., Oksuz I., Lee J., King A.P., Schnabel J.A. (2019) Left-Ventricle Quantification Using Residual U-Net. In: Pop M. et al. (eds) Statistical Atlases and Computational Models of the Heart. Atrial Segmentation and LV Quantification Challenges. STACOM 2018. Lecture Notes in Computer Science, vol 11395. Springer, Cham. https://doi.org/10.1007/978-3-030-12029-0_40`
16
+
17
+ ## Data
18
+
19
+ The dataset used to train this network unfortunately cannot be made public as it contains unreleased image data from King's College London. Existing public datasets such as the[Sunnybrook Cardiac Dataset](http://www.cardiacatlas.org/studies/sunnybrook-cardiac-data/) and [ACDC Challenge](https://www.creatis.insa-lyon.fr/Challenge/acdc/) set can be used to train a similar network.
20
+
21
+ The `train.json` configuration assumes all data is stored in a single npz file with keys "images" and "segs" containing respectively the raw image data and their accompanying segmentations. The given network was training with stored volumes with shapes `(9095, 256, 256)` thus other data of differing spatial dimensions must be cropped to `(256, 256)` or zero-padded to that size. For the training data this was done as a preprocessing step but the original pixel values are otherwise unchanged from their original forms.
22
+
23
+ ## Training
24
+
25
+ The network is trained with this data in conjunction with a series of augmentations for regularisation and robustness. Many of the original images are smaller than the expected size of `(256, 256)` and so were zero-padded, the network can thus be expected to be robust against large amounts of empty space in the inputs. Rotation and zooming is also applied to force the network to learn different sizes and orientations of the heart in the field of view.
26
+
27
+ Free-form deformation is applied to vary the shape of the heart and its surrounding tissues which mimics to a degree deformation like what would be observed through the cardiac cycle. This of course does not replicate the heart moving through plane during the cycle or represent other observed changes but does provide enough variation that full-cycle segmentation is generally acceptable.
28
+
29
+ Smooth fields are used to vary contrast and intensity in localised regions to simulate some of the variation in image quality caused by acquisition artefacts. Guassian noise is also added to simulate poor quality acquisition. These together force the network to learn to deal with a wider variation of image quality and partially to account for the difference between scanner vendors.
30
+
31
+ Training is invoked with the following command line:
32
+
33
+ ```sh
34
+ python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf --bundle_root .
35
+ ```
36
+
37
+ The dataset file is assumed to be `allimages3label.npz` but can be changed by setting the `dataset_file` value to your own file.
38
+
39
+ ## Inference
40
+
41
+ An example notebook [visualise.ipynb](./visualise.ipynb) demonstrates using the network directly with input images. Inference of 3D volumes only can be accomplished with the `inference.json` configuration:
42
+
43
+ ```sh
44
+ python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf --dataset_dir dataset --output_dir ./output/ --bundle_root .
45
+ ```
configs/inference.json ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "imports": [
3
+ "$import glob"
4
+ ],
5
+ "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')",
6
+ "ckpt_path": "$@bundle_root + '/models/model.pt'",
7
+ "dataset_dir": "/workspace/data",
8
+ "output_dir": "./output",
9
+ "datalist": "$list(sorted(glob.glob(@dataset_dir + '/*.nii*')))",
10
+ "network_def": {
11
+ "_target_": "UNet",
12
+ "spatial_dims": 2,
13
+ "in_channels": 1,
14
+ "out_channels": 4,
15
+ "channels": [
16
+ 16,
17
+ 32,
18
+ 64,
19
+ 128,
20
+ 256
21
+ ],
22
+ "strides": [
23
+ 2,
24
+ 2,
25
+ 2,
26
+ 2
27
+ ],
28
+ "num_res_units": 2
29
+ },
30
+ "network": "$@network_def.to(@device)",
31
+ "preprocessing": {
32
+ "_target_": "Compose",
33
+ "transforms": [
34
+ {
35
+ "_target_": "LoadImaged",
36
+ "keys": "image"
37
+ },
38
+ {
39
+ "_target_": "EnsureChannelFirstd",
40
+ "keys": "image"
41
+ },
42
+ {
43
+ "_target_": "ScaleIntensityd",
44
+ "keys": "image"
45
+ },
46
+ {
47
+ "_target_": "EnsureTyped",
48
+ "keys": "image",
49
+ "device": "@device"
50
+ }
51
+ ]
52
+ },
53
+ "dataset": {
54
+ "_target_": "Dataset",
55
+ "data": "$[{'image': i} for i in @datalist]",
56
+ "transform": "@preprocessing"
57
+ },
58
+ "dataloader": {
59
+ "_target_": "DataLoader",
60
+ "dataset": "@dataset",
61
+ "batch_size": 1,
62
+ "shuffle": false,
63
+ "num_workers": 0
64
+ },
65
+ "inferer": {
66
+ "_target_": "SliceInferer",
67
+ "roi_size": [
68
+ 256,
69
+ 256
70
+ ],
71
+ "spatial_dim": 2
72
+ },
73
+ "postprocessing": {
74
+ "_target_": "Compose",
75
+ "transforms": [
76
+ {
77
+ "_target_": "Activationsd",
78
+ "keys": "pred",
79
+ "softmax": true
80
+ },
81
+ {
82
+ "_target_": "Invertd",
83
+ "keys": "pred",
84
+ "transform": "@preprocessing",
85
+ "orig_keys": "image",
86
+ "meta_key_postfix": "meta_dict",
87
+ "nearest_interp": false,
88
+ "to_tensor": true
89
+ },
90
+ {
91
+ "_target_": "AsDiscreted",
92
+ "keys": "pred",
93
+ "argmax": true
94
+ },
95
+ {
96
+ "_target_": "SaveImaged",
97
+ "keys": "pred",
98
+ "meta_keys": "pred_meta_dict",
99
+ "output_dir": "@output_dir"
100
+ }
101
+ ]
102
+ },
103
+ "handlers": [
104
+ {
105
+ "_target_": "CheckpointLoader",
106
+ "load_path": "@ckpt_path",
107
+ "load_dict": {
108
+ "model": "@network"
109
+ }
110
+ }
111
+ ],
112
+ "evaluator": {
113
+ "_target_": "SupervisedEvaluator",
114
+ "device": "@device",
115
+ "val_data_loader": "@dataloader",
116
+ "network": "@network",
117
+ "inferer": "@inferer",
118
+ "postprocessing": "@postprocessing",
119
+ "val_handlers": "@handlers"
120
+ },
121
+ "evaluating": [
122
+ "$@evaluator.run()"
123
+ ]
124
+ }
configs/logging.conf ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [loggers]
2
+ keys=root
3
+
4
+ [handlers]
5
+ keys=consoleHandler
6
+
7
+ [formatters]
8
+ keys=fullFormatter
9
+
10
+ [logger_root]
11
+ level=INFO
12
+ handlers=consoleHandler
13
+
14
+ [handler_consoleHandler]
15
+ class=StreamHandler
16
+ level=INFO
17
+ formatter=fullFormatter
18
+ args=(sys.stdout,)
19
+
20
+ [formatter_fullFormatter]
21
+ format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
configs/metadata.json ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json",
3
+ "version": "0.1.0",
4
+ "changelog": {
5
+ "0.1.0": "Initial version"
6
+ },
7
+ "monai_version": "0.9.0",
8
+ "pytorch_version": "1.10.2",
9
+ "numpy_version": "1.21.2",
10
+ "optional_packages_version": {
11
+ "nibabel": "3.2.1",
12
+ "pytorch-ignite": "0.4.8"
13
+ },
14
+ "task": "Segments the left and right ventricle in 2D short axis MR images",
15
+ "description": "This network segments full cycle short axis images of the ventricles, labelling LV pool separate from myocardium and RV pool",
16
+ "authors": "Eric Kerfoot",
17
+ "copyright": "Copyright (c) Eric Kerfoot, KCL",
18
+ "license": "See license.txt",
19
+ "network_data_format": {
20
+ "inputs": {
21
+ "image": {
22
+ "type": "image",
23
+ "format": "magnitude",
24
+ "modality": "MR",
25
+ "num_channels": 1,
26
+ "spatial_shape": [
27
+ 256,
28
+ 256
29
+ ],
30
+ "dtype": "float32",
31
+ "value_range": [],
32
+ "is_patch_data": false,
33
+ "channel_def": {
34
+ "0": "image"
35
+ }
36
+ }
37
+ },
38
+ "outputs": {
39
+ "pred": {
40
+ "type": "image",
41
+ "format": "segmentation",
42
+ "num_channels": 4,
43
+ "spatial_shape": [
44
+ 256,
45
+ 256
46
+ ],
47
+ "dtype": "float32",
48
+ "value_range": [
49
+ 0,
50
+ 3
51
+ ],
52
+ "is_patch_data": false,
53
+ "channel_def": {
54
+ "0": "background",
55
+ "1": "lv_pool",
56
+ "2": "myocardium",
57
+ "3": "rv_pool"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
configs/train.json ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "imports": [
3
+ "$from functools import partial",
4
+ "$import numpy as np",
5
+ "$import torch",
6
+ "$from ignite.engine import Events"
7
+ ],
8
+ "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')",
9
+ "ckpt_path": "$@bundle_root + '/models/model.pt'",
10
+ "dataset_file": "./allimages3label.npz",
11
+ "network_def": {
12
+ "_target_": "UNet",
13
+ "spatial_dims": 2,
14
+ "in_channels": 1,
15
+ "out_channels": 4,
16
+ "channels": [
17
+ 16,
18
+ 32,
19
+ 64,
20
+ 128,
21
+ 256
22
+ ],
23
+ "strides": [
24
+ 2,
25
+ 2,
26
+ 2,
27
+ 2
28
+ ],
29
+ "num_res_units": 2
30
+ },
31
+ "network": "$@network_def.to(@device)",
32
+ "npz": {
33
+ "_target_": "NPZDictItemDataset",
34
+ "npzfile": "$@dataset_file",
35
+ "keys": {
36
+ "images": "image",
37
+ "segs": "label"
38
+ }
39
+ },
40
+ "partitions": "$monai.data.partition_dataset(np.arange(len(@npz)),(8,2), shuffle=True)",
41
+ "train_sub": "$torch.utils.data.Subset(@npz,@partitions[0])",
42
+ "eval_sub": "$torch.utils.data.Subset(@npz,@partitions[1])",
43
+ "im_shape": "$@train_sub[0]['image'].shape",
44
+ "both_keys": [
45
+ "image",
46
+ "label"
47
+ ],
48
+ "rand_prob": 0.5,
49
+ "train_transforms": {
50
+ "_target_": "Compose",
51
+ "transforms": [
52
+ {
53
+ "_target_": "CastToTyped",
54
+ "keys": "@both_keys",
55
+ "dtype": "$(np.float32, np.int32)"
56
+ },
57
+ {
58
+ "_target_": "ScaleIntensityd",
59
+ "keys": "image"
60
+ },
61
+ {
62
+ "_target_": "AddChanneld",
63
+ "keys": "@both_keys"
64
+ },
65
+ {
66
+ "_target_": "RandAxisFlipd",
67
+ "keys": "@both_keys",
68
+ "prob": "@rand_prob"
69
+ },
70
+ {
71
+ "_target_": "RandRotate90d",
72
+ "keys": "@both_keys",
73
+ "prob": "@rand_prob"
74
+ },
75
+ {
76
+ "_target_": "RandSmoothDeformd",
77
+ "keys": "@both_keys",
78
+ "prob": "@rand_prob",
79
+ "spatial_size": "@im_shape",
80
+ "rand_size": [
81
+ 3,
82
+ 3
83
+ ],
84
+ "pad": 2,
85
+ "def_range": 0.1,
86
+ "field_mode": "$monai.utils.InterpolateMode.BICUBIC",
87
+ "grid_mode": "$(monai.utils.GridSampleMode.BICUBIC, monai.utils.GridSampleMode.NEAREST)",
88
+ "align_corners": true
89
+ },
90
+ {
91
+ "_target_": "RandAffined",
92
+ "keys": "@both_keys",
93
+ "prob": "@rand_prob",
94
+ "rotate_range": 0.5,
95
+ "translate_range": 50,
96
+ "scale_range": 0.25,
97
+ "padding_mode": "$monai.utils.GridSamplePadMode.ZEROS",
98
+ "mode": "$(monai.utils.GridSampleMode.BILINEAR,monai.utils.GridSampleMode.NEAREST)",
99
+ "as_tensor_output": false
100
+ },
101
+ {
102
+ "_target_": "RandSmoothFieldAdjustContrastd",
103
+ "keys": "image",
104
+ "prob": "@rand_prob",
105
+ "spatial_size": "@im_shape",
106
+ "rand_size": [
107
+ 8,
108
+ 8
109
+ ],
110
+ "gamma": [
111
+ 0.25,
112
+ 3
113
+ ],
114
+ "mode": "$monai.utils.InterpolateMode.BICUBIC",
115
+ "align_corners": true
116
+ },
117
+ {
118
+ "_target_": "RandSmoothFieldAdjustIntensityd",
119
+ "keys": "image",
120
+ "prob": "@rand_prob",
121
+ "spatial_size": "@im_shape",
122
+ "rand_size": [
123
+ 5,
124
+ 5
125
+ ],
126
+ "gamma": [
127
+ 0.1,
128
+ 1
129
+ ],
130
+ "mode": "$monai.utils.InterpolateMode.BICUBIC",
131
+ "align_corners": true
132
+ },
133
+ {
134
+ "_target_": "RandGaussianNoised",
135
+ "keys": "image",
136
+ "prob": "@rand_prob",
137
+ "std": 0.05
138
+ },
139
+ {
140
+ "_target_": "ScaleIntensityd",
141
+ "keys": "image"
142
+ },
143
+ {
144
+ "_target_": "CastToTyped",
145
+ "keys": "@both_keys",
146
+ "dtype": "$(np.float32, np.int32)"
147
+ },
148
+ {
149
+ "_target_": "EnsureTyped",
150
+ "keys": "@both_keys"
151
+ }
152
+ ]
153
+ },
154
+ "eval_transforms": {
155
+ "_target_": "Compose",
156
+ "transforms": [
157
+ {
158
+ "_target_": "CastToTyped",
159
+ "keys": "@both_keys",
160
+ "dtype": "$(np.float32, np.int32)"
161
+ },
162
+ {
163
+ "_target_": "ScaleIntensityd",
164
+ "keys": "image"
165
+ },
166
+ {
167
+ "_target_": "AddChanneld",
168
+ "keys": "@both_keys"
169
+ },
170
+ {
171
+ "_target_": "EnsureTyped",
172
+ "keys": "@both_keys"
173
+ }
174
+ ]
175
+ },
176
+ "train_dataset": {
177
+ "_target_": "CacheDataset",
178
+ "data": "@train_sub",
179
+ "transform": "@train_transforms"
180
+ },
181
+ "eval_dataset": {
182
+ "_target_": "CacheDataset",
183
+ "data": "@eval_sub",
184
+ "transform": "@eval_transforms"
185
+ },
186
+ "train_no_aug_dataset": {
187
+ "_target_": "CacheDataset",
188
+ "data": "@train_sub",
189
+ "transform": "@eval_transforms"
190
+ },
191
+ "num_iters": 400,
192
+ "batch_size": 200,
193
+ "num_epochs": 50,
194
+ "num_substeps": 5,
195
+ "sampler": {
196
+ "_target_": "torch.utils.data.WeightedRandomSampler",
197
+ "weights": "$torch.ones(len(@train_dataset))",
198
+ "replacement": true,
199
+ "num_samples": "$@num_iters*@batch_size"
200
+ },
201
+ "train_dataloader": {
202
+ "_target_": "ThreadDataLoader",
203
+ "dataset": "@train_dataset",
204
+ "batch_size": "@batch_size",
205
+ "repeats": "@num_substeps",
206
+ "num_workers": 8,
207
+ "sampler": "@sampler"
208
+ },
209
+ "eval_dataloader": {
210
+ "_target_": "DataLoader",
211
+ "dataset": "@eval_dataset",
212
+ "batch_size": "@batch_size",
213
+ "num_workers": 4
214
+ },
215
+ "lossfn": {
216
+ "_target_": "DiceLoss",
217
+ "include_background": false,
218
+ "to_onehot_y": true,
219
+ "softmax": true
220
+ },
221
+ "optimizer": {
222
+ "_target_": "torch.optim.Adam",
223
+ "params": "$@network.parameters()",
224
+ "lr": 0.001
225
+ },
226
+ "post_transform": {
227
+ "_target_": "Compose",
228
+ "transforms": [
229
+ {
230
+ "_target_": "Activationsd",
231
+ "keys": "pred",
232
+ "softmax": true
233
+ },
234
+ {
235
+ "_target_": "AsDiscreted",
236
+ "keys": [
237
+ "pred",
238
+ "label"
239
+ ],
240
+ "argmax": [
241
+ true,
242
+ false
243
+ ],
244
+ "to_onehot": 4
245
+ }
246
+ ]
247
+ },
248
+ "evaluator": {
249
+ "_target_": "SupervisedEvaluator",
250
+ "device": "@device",
251
+ "val_data_loader": "@eval_dataloader",
252
+ "network": "@network",
253
+ "postprocessing": "@post_transform",
254
+ "key_val_metric": {
255
+ "val_mean_dice": {
256
+ "_target_": "MeanDice",
257
+ "include_background": false,
258
+ "output_transform": "$monai.handlers.from_engine(['pred', 'label'])"
259
+ }
260
+ },
261
+ "val_handlers": [
262
+ {
263
+ "_target_": "StatsHandler",
264
+ "output_transform": "$lambda x: None"
265
+ }
266
+ ]
267
+ },
268
+ "handlers": [
269
+ {
270
+ "_target_": "ValidationHandler",
271
+ "validator": "@evaluator",
272
+ "epoch_level": true,
273
+ "interval": 1
274
+ },
275
+ {
276
+ "_target_": "CheckpointSaver",
277
+ "save_dir": "$@bundle_root + '/models'",
278
+ "save_dict": {
279
+ "model": "@network"
280
+ },
281
+ "save_interval": 1,
282
+ "save_final": true,
283
+ "epoch_level": true
284
+ },
285
+ {
286
+ "_target_": "StatsHandler",
287
+ "tag_name": "train_loss",
288
+ "output_transform": "$monai.handlers.from_engine(['loss'], first=True)"
289
+ }
290
+ ],
291
+ "trainer": {
292
+ "_target_": "SupervisedTrainer",
293
+ "max_epochs": "@num_epochs",
294
+ "device": "@device",
295
+ "train_data_loader": "@train_dataloader",
296
+ "network": "@network",
297
+ "loss_function": "@lossfn",
298
+ "optimizer": "@optimizer",
299
+ "postprocessing": "@post_transform",
300
+ "key_train_metric": null,
301
+ "train_handlers": "@handlers"
302
+ },
303
+ "training": [
304
+ "$@trainer.run()"
305
+ ]
306
+ }
docs/README.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # 3 Label Ventricular Segmentation
3
+
4
+ This network segments cardiac ventricle in 2D short axis MR images. The left ventricular pool is class 1, left ventricular myocardium class 2, and right ventricular pool class 3. Full cycle segmentation with this network is possible although much of the training data is composed of segmented end-diastole images. The input to the network is single 2D images thus segmenting whole time-dependent volumes consists of multiple inference operations.
5
+
6
+ The network and training scheme are essentially identical to that described in:
7
+
8
+ `Kerfoot E., Clough J., Oksuz I., Lee J., King A.P., Schnabel J.A. (2019) Left-Ventricle Quantification Using Residual U-Net. In: Pop M. et al. (eds) Statistical Atlases and Computational Models of the Heart. Atrial Segmentation and LV Quantification Challenges. STACOM 2018. Lecture Notes in Computer Science, vol 11395. Springer, Cham. https://doi.org/10.1007/978-3-030-12029-0_40`
9
+
10
+ ## Data
11
+
12
+ The dataset used to train this network unfortunately cannot be made public as it contains unreleased image data from King's College London. Existing public datasets such as the[Sunnybrook Cardiac Dataset](http://www.cardiacatlas.org/studies/sunnybrook-cardiac-data/) and [ACDC Challenge](https://www.creatis.insa-lyon.fr/Challenge/acdc/) set can be used to train a similar network.
13
+
14
+ The `train.json` configuration assumes all data is stored in a single npz file with keys "images" and "segs" containing respectively the raw image data and their accompanying segmentations. The given network was training with stored volumes with shapes `(9095, 256, 256)` thus other data of differing spatial dimensions must be cropped to `(256, 256)` or zero-padded to that size. For the training data this was done as a preprocessing step but the original pixel values are otherwise unchanged from their original forms.
15
+
16
+ ## Training
17
+
18
+ The network is trained with this data in conjunction with a series of augmentations for regularisation and robustness. Many of the original images are smaller than the expected size of `(256, 256)` and so were zero-padded, the network can thus be expected to be robust against large amounts of empty space in the inputs. Rotation and zooming is also applied to force the network to learn different sizes and orientations of the heart in the field of view.
19
+
20
+ Free-form deformation is applied to vary the shape of the heart and its surrounding tissues which mimics to a degree deformation like what would be observed through the cardiac cycle. This of course does not replicate the heart moving through plane during the cycle or represent other observed changes but does provide enough variation that full-cycle segmentation is generally acceptable.
21
+
22
+ Smooth fields are used to vary contrast and intensity in localised regions to simulate some of the variation in image quality caused by acquisition artefacts. Guassian noise is also added to simulate poor quality acquisition. These together force the network to learn to deal with a wider variation of image quality and partially to account for the difference between scanner vendors.
23
+
24
+ Training is invoked with the following command line:
25
+
26
+ ```sh
27
+ python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf --bundle_root .
28
+ ```
29
+
30
+ The dataset file is assumed to be `allimages3label.npz` but can be changed by setting the `dataset_file` value to your own file.
31
+
32
+ ## Inference
33
+
34
+ An example notebook [visualise.ipynb](./visualise.ipynb) demonstrates using the network directly with input images. Inference of 3D volumes only can be accomplished with the `inference.json` configuration:
35
+
36
+ ```sh
37
+ python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf --dataset_dir dataset --output_dir ./output/ --bundle_root .
38
+ ```
docs/SC-N-2-3-0.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:03c7fae03f14710b9b1e6709d1d4d101b8569a94f3781376ac92f659483d6f16
3
+ size 524416
docs/license.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
docs/visualise.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
models/model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:464ca796028831f6c9e2b1cdaebe9af002fc1d7f494f7a89a63f2079e38837a1
3
+ size 6533160
models/model.ts ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:27d5532401fa6c1883872fa21635adbb7615981e7f385d0c58dd75b355e340b3
3
+ size 6631889