Update body MR/CT 6mm
Browse files- body/{M299.pt → M598.pt} +2 -2
- body/Prediction.yml +11 -7
- body/app.json +4 -4
- body/model.py +6 -20
- body/requirements.txt +1 -0
- build.py +1 -3
- total_mr-3mm/Prediction.yml +2 -2
body/{M299.pt → M598.pt}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c0fbbaf9375502a08f765750374c8dc31736cf938966ed8eb8f2cf6b919e1933
|
| 3 |
+
size 22427409
|
body/Prediction.yml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
Predictor:
|
| 2 |
Model:
|
| 3 |
-
classpath: model:
|
| 4 |
-
|
| 5 |
outputs_criterions: None
|
| 6 |
channels:
|
| 7 |
- 1
|
|
@@ -9,8 +9,6 @@ Predictor:
|
|
| 9 |
- 64
|
| 10 |
- 128
|
| 11 |
- 256
|
| 12 |
-
- 320
|
| 13 |
-
- 320
|
| 14 |
Dataset:
|
| 15 |
groups_src:
|
| 16 |
Volume_0:
|
|
@@ -24,10 +22,16 @@ Predictor:
|
|
| 24 |
inverse: true
|
| 25 |
ResampleToResolution:
|
| 26 |
spacing:
|
| 27 |
-
-
|
| 28 |
-
-
|
| 29 |
-
-
|
| 30 |
inverse: true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
Padding:
|
| 32 |
padding:
|
| 33 |
- 32
|
|
|
|
| 1 |
Predictor:
|
| 2 |
Model:
|
| 3 |
+
classpath: model:Unet_TS_MR
|
| 4 |
+
Unet_TS_MR:
|
| 5 |
outputs_criterions: None
|
| 6 |
channels:
|
| 7 |
- 1
|
|
|
|
| 9 |
- 64
|
| 10 |
- 128
|
| 11 |
- 256
|
|
|
|
|
|
|
| 12 |
Dataset:
|
| 13 |
groups_src:
|
| 14 |
Volume_0:
|
|
|
|
| 22 |
inverse: true
|
| 23 |
ResampleToResolution:
|
| 24 |
spacing:
|
| 25 |
+
- 6
|
| 26 |
+
- 6
|
| 27 |
+
- 6
|
| 28 |
inverse: true
|
| 29 |
+
Standardize:
|
| 30 |
+
lazy: false
|
| 31 |
+
mean: None
|
| 32 |
+
std: None
|
| 33 |
+
mask: None
|
| 34 |
+
inverse: false
|
| 35 |
Padding:
|
| 36 |
padding:
|
| 37 |
- 32
|
body/app.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
{
|
| 2 |
-
"display_name": "Segmentation: Body CT",
|
| 3 |
-
"short_description": "<b>Description:</b><br>KonfAI adaptation of
|
| 4 |
-
"description": "<b>Description:</b><br>This model
|
| 5 |
"tta": 0,
|
| 6 |
"mc_dropout": 0,
|
| 7 |
-
"models": ["
|
| 8 |
"inputs": {
|
| 9 |
"Volume": {
|
| 10 |
"display_name": "Input Volume",
|
|
|
|
| 1 |
{
|
| 2 |
+
"display_name": "Segmentation: Body MRI/CT 6mm",
|
| 3 |
+
"short_description": "<b>Description:</b><br>Lightweight <b>KonfAI</b> adaptation of <a href='https://github.com/wasserth/TotalSegmentator'>TotalSegmentator MRI</a> for fast body segmentation into <b>body trunk</b> and <b>extremities</b> from <b>MRI and CT</b> scans at <b>6 mm isotropic</b> resolution.<br><br><b>How to cite:</b><br><cite>T. Akinci D’Antonoli et al., <i>TotalSegmentator MRI: Robust Sequence-Independent Segmentation of Multiple Anatomic Structures in MRI</i>, Radiology, 2025.</cite>",
|
| 4 |
+
"description": "<b>Description:</b><br>This model integrates the reduced-resolution body configuration of <a href='https://github.com/wasserth/TotalSegmentator'>TotalSegmentator MRI</a> into the <b>KonfAI</b> inference pipeline for efficient <b>MRI/CT</b> body mask generation.<br><br><b>Capabilities:</b><br>• Segmentation of <b>2 body classes</b>: body_trunc and body_extremities<br>• <b>6 mm isotropic</b> input for lower memory usage and fast preprocessing workflows<br>• Robust body mask generation for both <b>MRI and CT</b> downstream pipelines<br><br><b>Training data:</b><br>Trained on a multimodal cohort with <b>MRI and CT</b> scans, with labels for the body trunk and extremities<br><br><b>How to cite:</b><br><cite>T. Akinci D’Antonoli et al., <i>TotalSegmentator MRI: Robust Sequence-Independent Segmentation of Multiple Anatomic Structures in MRI</i>, Radiology, 2025.</cite>",
|
| 5 |
"tta": 0,
|
| 6 |
"mc_dropout": 0,
|
| 7 |
+
"models": ["M598.pt"],
|
| 8 |
"inputs": {
|
| 9 |
"Volume": {
|
| 10 |
"display_name": "Input Volume",
|
body/model.py
CHANGED
|
@@ -21,30 +21,17 @@ class UNetBlock(network.ModuleArgsDict):
|
|
| 21 |
|
| 22 |
def __init__(self, channels, i : int = 0) -> None:
|
| 23 |
super().__init__()
|
| 24 |
-
self.add_module("DownConvBlock", ConvBlock(in_channels=channels[0], out_channels=channels[1], stride= 2 if i>0 else 1))
|
| 25 |
|
| 26 |
if len(channels) > 2:
|
| 27 |
self.add_module("UNetBlock", UNetBlock(channels[1:], i+1))
|
| 28 |
self.add_module("UpConvBlock", ConvBlock(in_channels=channels[1]*2, out_channels=channels[1]))
|
| 29 |
|
| 30 |
if i > 0:
|
| 31 |
-
self.add_module("CONV_TRANSPOSE", torch.nn.ConvTranspose3d(in_channels = channels[1], out_channels = channels[0], kernel_size = 2, stride = 2, padding = 0))
|
| 32 |
self.add_module("SkipConnection", blocks.Concat(), in_branch=[0, 1])
|
| 33 |
|
| 34 |
-
class
|
| 35 |
-
|
| 36 |
-
def __init__(self) -> None:
|
| 37 |
-
super().__init__()
|
| 38 |
-
self.register_buffer("clip_min", torch.empty(1))
|
| 39 |
-
self.register_buffer("clip_max", torch.empty(1))
|
| 40 |
-
self.register_buffer("mean", torch.empty(1))
|
| 41 |
-
self.register_buffer("std", torch.empty(1))
|
| 42 |
-
|
| 43 |
-
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 44 |
-
x = torch.clamp(x, self.clip_min, self.clip_max)
|
| 45 |
-
return (x - self.mean) / (self.std)
|
| 46 |
-
|
| 47 |
-
class Unet_TS_CT(network.Network):
|
| 48 |
|
| 49 |
def __init__(self,
|
| 50 |
optimizer: network.OptimizerLoader = network.OptimizerLoader(),
|
|
@@ -52,7 +39,7 @@ class Unet_TS_CT(network.Network):
|
|
| 52 |
"default:ReduceLROnPlateau": network.LRSchedulersLoader(0)
|
| 53 |
},
|
| 54 |
outputs_criterions: dict[str, network.TargetCriterionsLoader] = {"default": network.TargetCriterionsLoader()},
|
| 55 |
-
channels: list[int] = [1, 32, 64, 128, 320
|
| 56 |
super().__init__(
|
| 57 |
in_channels=channels[0],
|
| 58 |
optimizer=optimizer,
|
|
@@ -61,9 +48,8 @@ class Unet_TS_CT(network.Network):
|
|
| 61 |
patch=None,
|
| 62 |
dim=3,
|
| 63 |
)
|
| 64 |
-
self.add_module("ClipAndNormalize", ClipAndNormalize())
|
| 65 |
self.add_module("UNetBlock", UNetBlock(channels))
|
| 66 |
-
self.add_module("Head", UNetHead(channels[1],
|
| 67 |
|
| 68 |
def load(
|
| 69 |
self,
|
|
@@ -71,6 +57,6 @@ class Unet_TS_CT(network.Network):
|
|
| 71 |
init: bool = True,
|
| 72 |
ema: bool = False,
|
| 73 |
):
|
| 74 |
-
nb_class, in_channels = state_dict["Model"]["
|
| 75 |
self["Head"].add_module("Conv", torch.nn.Conv3d(in_channels = in_channels, out_channels = nb_class, kernel_size = 1, stride = 1, padding = 0))
|
| 76 |
super().load(state_dict, init, ema)
|
|
|
|
| 21 |
|
| 22 |
def __init__(self, channels, i : int = 0) -> None:
|
| 23 |
super().__init__()
|
| 24 |
+
self.add_module("DownConvBlock", ConvBlock(in_channels=channels[0], out_channels=channels[1], stride= ((1,2,2) if i > 4 else 2) if i>0 else 1))
|
| 25 |
|
| 26 |
if len(channels) > 2:
|
| 27 |
self.add_module("UNetBlock", UNetBlock(channels[1:], i+1))
|
| 28 |
self.add_module("UpConvBlock", ConvBlock(in_channels=channels[1]*2, out_channels=channels[1]))
|
| 29 |
|
| 30 |
if i > 0:
|
| 31 |
+
self.add_module("CONV_TRANSPOSE", torch.nn.ConvTranspose3d(in_channels = channels[1], out_channels = channels[0], kernel_size = (1,2,2) if i > 4 else 2, stride = (1,2,2) if i > 4 else 2, padding = 0))
|
| 32 |
self.add_module("SkipConnection", blocks.Concat(), in_branch=[0, 1])
|
| 33 |
|
| 34 |
+
class Unet_TS_MR(network.Network):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
def __init__(self,
|
| 37 |
optimizer: network.OptimizerLoader = network.OptimizerLoader(),
|
|
|
|
| 39 |
"default:ReduceLROnPlateau": network.LRSchedulersLoader(0)
|
| 40 |
},
|
| 41 |
outputs_criterions: dict[str, network.TargetCriterionsLoader] = {"default": network.TargetCriterionsLoader()},
|
| 42 |
+
channels: list[int] = [1, 32, 64, 128, 320]) -> None:
|
| 43 |
super().__init__(
|
| 44 |
in_channels=channels[0],
|
| 45 |
optimizer=optimizer,
|
|
|
|
| 48 |
patch=None,
|
| 49 |
dim=3,
|
| 50 |
)
|
|
|
|
| 51 |
self.add_module("UNetBlock", UNetBlock(channels))
|
| 52 |
+
self.add_module("Head", UNetHead(channels[1], 42))
|
| 53 |
|
| 54 |
def load(
|
| 55 |
self,
|
|
|
|
| 57 |
init: bool = True,
|
| 58 |
ema: bool = False,
|
| 59 |
):
|
| 60 |
+
nb_class, in_channels = state_dict["Model"]["Unet_TS_MR"]["Head.Conv.weight"].shape[:2]
|
| 61 |
self["Head"].add_module("Conv", torch.nn.Conv3d(in_channels = in_channels, out_channels = nb_class, kernel_size = 1, stride = 1, padding = 0))
|
| 62 |
super().load(state_dict, init, ema)
|
body/requirements.txt
CHANGED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
segmentation_models_pytorch
|
build.py
CHANGED
|
@@ -16,10 +16,7 @@ def convert_torchScript_full(model_name: str, model: torch.nn.Module, task: str,
|
|
| 16 |
with open("Destination_Unet_{}.txt".format(type)) as f2:
|
| 17 |
it = iter(state_dict.keys())
|
| 18 |
for l1 in f2:
|
| 19 |
-
print(l1)
|
| 20 |
-
|
| 21 |
key = next(it)
|
| 22 |
-
print(key)
|
| 23 |
while "decoder.seg_layers" in key:
|
| 24 |
if type == 1:
|
| 25 |
if "decoder.seg_layers.4" in key :
|
|
@@ -105,6 +102,7 @@ models = {
|
|
| 105 |
"M853" : (UnetCPP_3_MR(), False, 3, url+"v2.5.0-weights/Dataset853_TotalSegMRI_total_6mm_1088subj.zip"),
|
| 106 |
"M299" : (UnetCPP_1_CT(), "total", 1, False, url+"v2.0.0-weights/Dataset299_body_1559subj.zip"),
|
| 107 |
"M597" : (UnetCPP_1_MR(), "body", 1, True, url+"v2.5.0-weights/Dataset597_mri_body_139subj.zip"),
|
|
|
|
| 108 |
}
|
| 109 |
if __name__ == "__main__":
|
| 110 |
for name, model in models.items():
|
|
|
|
| 16 |
with open("Destination_Unet_{}.txt".format(type)) as f2:
|
| 17 |
it = iter(state_dict.keys())
|
| 18 |
for l1 in f2:
|
|
|
|
|
|
|
| 19 |
key = next(it)
|
|
|
|
| 20 |
while "decoder.seg_layers" in key:
|
| 21 |
if type == 1:
|
| 22 |
if "decoder.seg_layers.4" in key :
|
|
|
|
| 102 |
"M853" : (UnetCPP_3_MR(), False, 3, url+"v2.5.0-weights/Dataset853_TotalSegMRI_total_6mm_1088subj.zip"),
|
| 103 |
"M299" : (UnetCPP_1_CT(), "total", 1, False, url+"v2.0.0-weights/Dataset299_body_1559subj.zip"),
|
| 104 |
"M597" : (UnetCPP_1_MR(), "body", 1, True, url+"v2.5.0-weights/Dataset597_mri_body_139subj.zip"),
|
| 105 |
+
"M598" : (UnetCPP_3_MR(), "body", 3, True, url+"v2.5.0-weights/Dataset598_mri_body_6mm_139subj.zip"),
|
| 106 |
}
|
| 107 |
if __name__ == "__main__":
|
| 108 |
for name, model in models.items():
|
total_mr-3mm/Prediction.yml
CHANGED
|
@@ -10,7 +10,6 @@ Predictor:
|
|
| 10 |
- 128
|
| 11 |
- 256
|
| 12 |
- 320
|
| 13 |
-
mri: true
|
| 14 |
Dataset:
|
| 15 |
groups_src:
|
| 16 |
Volume_0:
|
|
@@ -74,7 +73,7 @@ Predictor:
|
|
| 74 |
TensorCast:
|
| 75 |
dtype: uint8
|
| 76 |
inverse: true
|
| 77 |
-
after_reduction_transforms:
|
| 78 |
Sum:
|
| 79 |
dim: 0
|
| 80 |
final_transforms: None
|
|
@@ -82,6 +81,7 @@ Predictor:
|
|
| 82 |
group: Output
|
| 83 |
same_as_group: Volume_0:Volume
|
| 84 |
patch_combine: Cosinus
|
|
|
|
| 85 |
reduction: Concat
|
| 86 |
train_name: TotalSegmentator
|
| 87 |
manual_seed: 32
|
|
|
|
| 10 |
- 128
|
| 11 |
- 256
|
| 12 |
- 320
|
|
|
|
| 13 |
Dataset:
|
| 14 |
groups_src:
|
| 15 |
Volume_0:
|
|
|
|
| 73 |
TensorCast:
|
| 74 |
dtype: uint8
|
| 75 |
inverse: true
|
| 76 |
+
after_reduction_transforms:
|
| 77 |
Sum:
|
| 78 |
dim: 0
|
| 79 |
final_transforms: None
|
|
|
|
| 81 |
group: Output
|
| 82 |
same_as_group: Volume_0:Volume
|
| 83 |
patch_combine: Cosinus
|
| 84 |
+
inverse_transform: true
|
| 85 |
reduction: Concat
|
| 86 |
train_name: TotalSegmentator
|
| 87 |
manual_seed: 32
|