🆕 Add Cerberus#1060
Conversation
for more information, see https://pre-commit.ci
- Drop Python 3.10 support - Add Python 3.14 support
for more information, see https://pre-commit.ci
…remove-python3.10
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #1060 +/- ##
===========================================
- Coverage 99.88% 99.63% -0.25%
===========================================
Files 85 93 +8
Lines 11623 12166 +543
Branches 1524 1598 +74
===========================================
+ Hits 11610 12122 +512
- Misses 7 20 +13
- Partials 6 24 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
|
||
|
|
||
| class Cerberus(ModelABC, NetDesc): | ||
| """Cerberus multi-task model for glands, lumen, nuclei, and patch class.""" |
There was a problem hiding this comment.
Can you expand the description and add some metrics reported in the paper as in the link below?
https://tia-toolbox.readthedocs.io/en/latest/_autosummary/tiatoolbox.models.architecture.kongnet.KongNet.html
| def __init__( | ||
| self, | ||
| patch_output_shape: tuple[int, int] = (144, 144), | ||
| nuclei_type_dict: dict | None = None, | ||
| gland_type_dict: dict | None = None, | ||
| lumen_type_dict: dict | None = None, | ||
| ) -> None: |
There was a problem hiding this comment.
Pull request overview
This PR introduces the Cerberus multi-task (gland/lumen/nuclei + patch-class) architecture and wires it into TIAToolbox’s pretrained-model registry, alongside engine improvements to support halo-based tile post-processing and some utility additions.
Changes:
- Added Cerberus architecture (network, backbone, post-processing) + registry entry and unit tests.
- Enhanced
MultiTaskSegmentortile-mode post-processing with an optionalpostproc_haloto improve boundary handling and object ownership across tiles. - Added an annotation-store utility (
combine_annotation_stores) with tests, and improved weight-loading compatibility for checkpoints wrapped under"desc"/DataParallelprefixes.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tiatoolbox/wsicore/wsireader.py |
Adjusts tissue masking to neutralize pure-black pixels in thumbnails before masking. |
tiatoolbox/models/models_abc.py |
Makes load_torch_model robust to "desc"-wrapped checkpoints and module.-prefixed keys. |
tiatoolbox/models/engine/multi_task_segmentor.py |
Adds postproc_halo support for tile post-processing + improves tile merging/spill-to-zarr behavior. |
tiatoolbox/models/engine/io_config.py |
Extends IO config schema/docs to carry postproc_halo. |
tiatoolbox/models/architecture/cerberus/** |
Adds Cerberus model definition, minimal ResNet-34 encoder, decoder utilities, and post-processing. |
tiatoolbox/models/__init__.py |
Exposes Cerberus at tiatoolbox.models.Cerberus. |
tiatoolbox/data/pretrained_model.yaml |
Registers cerberus-resnet34 pretrained entry (HF repo + IO config). |
tiatoolbox/annotation/utils.py |
Adds combine_annotation_stores helper. |
tiatoolbox/annotation/__init__.py |
Re-exports combine_annotation_stores. |
tests/test_annotation_utils.py |
Tests for combine_annotation_stores. |
tests/models/test_arch_cerberus.py |
Unit tests for Cerberus model, postproc, and pretrained registry wiring. |
tests/engines/test_multi_task_segmentor.py |
Tests for halo post-processing and vertical merge after Zarr spill. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # set any black pixels to white to avoid them being included in the tissue mask | ||
| thumbnail[thumbnail.sum(axis=2) == 0] = 255 |
| labels_ = _normalise_labels(input_path_objs, labels) | ||
| combined_store = SQLiteStore(auto_commit=False) | ||
|
|
||
| for source_path in input_path_objs: | ||
| source_store = SQLiteStore.open(source_path) | ||
| source_label = labels_[source_path] | ||
| annotations = [] | ||
| keys = [] | ||
| for key, annotation in source_store.items(): | ||
| properties = dict(annotation.properties) | ||
| properties[label_property] = source_label | ||
| annotations.append(Annotation(annotation.geometry, properties)) | ||
| keys.append(f"{source_label}:{key}") | ||
| if annotations: | ||
| combined_store.append_many(annotations, keys) | ||
|
|
||
| combined_store.commit() | ||
| combined_store.dump(output_path) | ||
| return output_path |
| def _dilate_labelled_instances(inst_fg: np.ndarray, k_disk: np.ndarray) -> np.ndarray: | ||
| """Label foreground instances, dilate each object, and fill holes.""" | ||
| inst_lab = label(inst_fg)[0] | ||
| output_map = np.zeros(inst_lab.shape) | ||
| for inst_id in np.unique(inst_lab).tolist()[1:]: | ||
| inst_map = np.array(inst_lab == inst_id, dtype=np.uint8) | ||
| y1, y2, x1, x2 = get_bounding_box(inst_map) | ||
| pad = k_disk.shape[0] * 2 | ||
| y1 = max(y1 - pad, 0) | ||
| x1 = max(x1 - pad, 0) | ||
| x2 = min(x2 + pad, inst_map.shape[1] - 1) | ||
| y2 = min(y2 + pad, inst_map.shape[0] - 1) | ||
| inst_map_crop = inst_map[y1:y2, x1:x2] | ||
| inst_map_crop = cv2.dilate(inst_map_crop, k_disk, iterations=1) | ||
| inst_map_crop = binary_fill_holes(inst_map_crop) | ||
| output_region = output_map[y1:y2, x1:x2] | ||
| output_region[inst_map_crop > 0] = inst_id | ||
| return output_map |
This PR adds Cerberus model architecture and pretrained models, so it can be used within the newly-efficient tiatoolbox engines.
Still a draft as needs tidying up a bit and uploading weights to huggingface.
Example output:
