File size: 7,312 Bytes
b64c182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
---

license: cc-by-nc-sa-4.0
library_name: nnunetv2
pipeline_tag: image-segmentation
tags:
  - biology
  - microscopy
  - cell-segmentation
  - microridge
  - nnunet
  - zebrafish
---


# MicroridgeVectorAI β€” v3

A 2D nnU-Net that segments **actin microridges**, **cell regions** and **cell

membranes** in projected single-channel microscopy of epithelial tissue.

Companion application: <https://github.com/LBK888/MicroridgeVectorAI> (CellVector,
AGPL-3.0). The model runs standalone with nnU-Net v2 alone β€” CellVector is not
required.

| | |
|---|---|
| Model id | `a619b15c-e00f-489b-887c-6386e3836c11` |
| Task | 2D semantic segmentation, 4 classes |
| Architecture | nnU-Net v2 PlainConvUNet, 8 stages, patch 512x512 |
| Trainer / folds | `nnUNetTrainer_100epochs`, fold 0 |
| Input | single-channel 2D image, any size |
| Snapshot hash | `dbe134f83c52b8ecae6cb62182310205496497ec297406ed8a2c912b60ba8cc9` |
| Label policy | `membrane-first-v2`, membrane 3 px, microridge 5 px |

Labels: `0` background, `1` cell_region, `2` cell_membrane, `3` microridge.

## Scores

Frozen test β€” 36 tiles from **3 fields the model never saw**. Splits are grouped
by source field, so no tile of a training field appears in the test set.

| Metric | Value | v2 |
|---|---|---|
| cell_region Dice | 0.943 | 0.944 |

| cell_membrane Dice | **0.707** | 0.471 |
| cell_membrane boundary F1 (1 px tolerance) | **0.874** | 0.659 |

| microridge Dice | 0.852 | 0.877 |

| microridge precision / recall | 0.899 / 0.822 | 0.911 / 0.855 |

| microridge skeleton length error | 0.105 | 0.100 |



nnU-Net's own fold-0 validation (89 tiles): cell_region 0.964, cell_membrane

0.696, microridge 0.886.



v2 was trained on labels in which the microridge class had erased 69.6% of the

membrane: classes are mutually exclusive and microridges were stroked last, so a

ridge running beside a cell edge overwrote it. v3 reverses that contest. The

membrane keeps all of its pixels and the microridge class yields 7.2% of its

own, which it can afford at a quarter of the frame. Nothing else changed β€” same

data, same architecture, same 100 epochs.



**Reading the membrane number.** Dice on a 3-pixel line covering under 3% of the

frame collapses when a prediction is offset by a pixel even where it follows the

right path, so it understates a thin structure. The boundary F1 of 0.874, which

allows one pixel of tolerance, is the more informative figure; the gap between

0.707 and 0.874 is the residual sub-pixel offset, not missing membrane.



## Limitations



- **Cell instances are approximate.** Cells are recovered as connected

  components separated by the predicted membrane. On a frozen-test tile holding

  10 cells this returns 9, against 1 for v2, whose membrane was too broken to

  separate anything. Expect near-misses where the membrane is faint, not exact

  instance segmentation.

- **The ground truth was not human-reviewed.** Labels were imported from

  published raster masks and corrected only for import artifacts, not by an

  expert. Treat this model as a proposal generator to be corrected, which is how

  the companion application uses it.

- **Trained on 13 fields.** Train and validation loss diverge (-0.782 vs

  -0.636), which is what a small number of independent acquisitions looks like.

  More fields will help more than more epochs.

- **One fold, not an ensemble.** Only fold 0 was trained.

- Validated on zebrafish periderm-style epithelial microridge imagery. Behaviour

  on other tissue, magnification or modality is unknown.



## Training data



Wide-field frames cut into 477 tiles of at most 512x512 from 19 fields, keeping

only regions whose raster truth is trustworthy. Uneven illumination leaves part

of such a frame too dark for the upstream segmentation to resolve anything, and

that failure is silent β€” the skeleton mask is empty while the cell mask still

looks complete. Blocks were kept only where skeleton density cleared both an

absolute floor and a share of the frame's own 90th percentile, **and** at least

95% of the block was attributed to a cell. 68.3% of the field pixels survived.



Labels were rasterized from vector geometry with a 3 px membrane and a 5 px

microridge stroke.



## Files



```text

registry.json                                   provenance record, metrics, checksums

nnUNet_results/Dataset503_MicroridgeMembraneFirst/

└─ nnUNetTrainer_100epochs__nnUNetPlans__2d/
   β”œβ”€ dataset.json                              channel names and label map
   β”œβ”€ plans.json                                preprocessing and architecture
   └─ fold_0/checkpoint_final.pth               weights
```



Those three files under the trainer folder are the complete inference set. The

directory names encode the configuration β€” nnU-Net parses

`Dataset<ID>_<name>/<trainer>__<plans>__<configuration>` β€” so do not rename them.



The checkpoint is shipped unmodified so the `checkpoint_sha256` in

`registry.json` verifies. About half of it is optimizer state; stripping to

`network_weights`, `init_args`, `trainer_name` and

`inference_allowed_mirroring_axes` halves the size but invalidates that

checksum.



## Usage



```bash

pip install nnunetv2 huggingface_hub

hf download leobk/MicroridgeVectorAI --local-dir microridge-model

```

```python

import torch, numpy as np, tifffile

from nnunetv2.inference.predict_from_raw_data import nnUNetPredictor



MODEL = ("microridge-model/nnUNet_results/Dataset503_MicroridgeMembraneFirst"

         "/nnUNetTrainer_100epochs__nnUNetPlans__2d")



predictor = nnUNetPredictor(device=torch.device("cuda"))

predictor.initialize_from_trained_model_folder(

    MODEL, use_folds=(0,), checkpoint_name="checkpoint_final.pth"

)



image = tifffile.imread("frame.tif").astype("float32")

segmentation = predictor.predict_single_npy_array(

    image[None, None], {"spacing": (999.0, 1.0, 1.0)}, None, None, False

)

```

No nnU-Net environment variables are needed for this path. Roughly 13 s for a
512x512 tile on an RTX 4080 SUPER.

### Reimplementing the pipeline

The network takes `(1, 1, H, W)` and returns 4 logit channels, and exports to
TorchScript. If you drive it yourself, reproduce all of:

- **Normalization** β€” z-score using *each image's own* mean and standard
  deviation (`use_mask_for_norm=False`). No dataset statistics;
  `foreground_intensity_properties_per_channel` in `plans.json` is for CT
  normalization and unused here.
- **Sliding window** β€” 512x512 patches, step 0.5, Gaussian-weighted overlap.
- **Test-time augmentation** β€” mirroring over axes `(0, 1)`.
- **Output** β€” argmax over the 4 channels.

Skipping the normalization or the Gaussian window degrades results noticeably
and without any error.

## Licensing note

These weights are released under **CC BY-NC-SA 4.0**: attribution required,
**non-commercial use only**, derivatives under the same terms. Note that this
differs from the companion application's code licence (AGPL-3.0) β€” the code and
the weights are covered separately.

The weights were trained on third-party imagery; if that source data carries its
own terms, they may constrain redistribution of this model independently of this
label.