9 µm ink detection

Ink-detection models for Herculaneum scroll surface volumes at ~9 µm isotropic resolution, trained on aligned labels across four scrolls. The labels live in the ink_9um dataset. Training and inference code: villa @ merge-ink-pipelines - see ink-detection/configs/README.md

Layout

hybrid_3d2d-seed42/   step-010000.pth ... step-075000.pth  (7 checkpoints)
hybrid_3d2d-seed43/   step-010000.pth ... step-075000.pth  (7 checkpoints)

Models

The whole recipe is one JSON config in the code branch, configs/aligned21_hybrid_3d2d.json. The model is a small local 3D stem feeding a 2D U-Net, trained on 128×128 patches sampled every 32 px. Every training batch draws a fixed number of patches from each scroll (29/22/11/2 of 64 across PHerc. 0139, Scroll 1667, PHerc. Paris 4, and PHerc. 0814), and the z window jitters over 17 of the 21 slices so the models don't lock onto one exact depth

We trained it twice, changing only the seed, and we're sharing both runs in full: hybrid_3d2d-seed42/ and hybrid_3d2d-seed43/, seven checkpoints each along the trajectory, named by training step (step-010000.pth up to step-075000.pth). Different steps behave a bit differently on different segments, so it's worth trying a few

Checkpoints embed their training config; inference rebuilds the model and its normalization from the checkpoint automatically

Quick start

Inference takes a surface volume and a checkpoint:

uv run python -m koine_machines.inference.infer <input.zarr> <checkpoint.pth> <output.tif>

The models expect ~9 µm isotropic surface volumes. Native ~9 µm renders work directly, local or by URL:

uv run python -m koine_machines.inference.infer \
  https://vesuvius-challenge-open-data.s3.amazonaws.com/PHerc0139/segments/20260112000000-w043_2026011217/surface-volumes/9.362um-1.2m-113keV-volume-20250728140407.zarr \
  <checkpoint.pth> w043.tif

For 2.4 µm surface volumes, first pool them to the ~9.6 µm isotropic representation the models were trained on (XY pyramid level 2, 4x z mean-pooling):

uv run python scripts/prepare_9um_isotropic_input.py <surface-volume-2p4um.zarr> <pooled.zarr>

Tips

  • If a checkpoint is not responding well on your data, it might just be a z layer offset; the models can be quite sensitive to it, and picking a different z window (--layer-start/--layer-end) can help. Averaging predictions over a few nearby z windows also works as a simple ensemble. Training on jittered 17-of-21 windows makes the models handle small offsets reasonably well, but larger ones can still throw them off
  • The models train with BCE label smoothing 0.5, so their most confident no-ink output sits near 0.25 rather than 0. For display, rescale with (p - 0.25) / 0.5; keep the raw TIFFs raw for anything quantitative

Training data

We trained on the public z-anisotropic 2.399 µm volumes downsampled to ~9.6 µm isotropic (level-2 XY, 4x z mean-pooling), with segments from PHerc. 0139 (9), Scroll 1667 (6), PHerc. Paris 4 (8), and PHerc. 0814 (1), plus 5 native 9.362 µm segments from PHerc. 0139

The labels, the per-segment source-volume tables, and how they plug into the training config all live in the ink_9um dataset

Train it yourself

One command:

uv run python -m koine_machines.training.train configs/aligned21_hybrid_3d2d.json

These models are far from optimized. Better augmentation, longer training, other architectures, ensembling, and more data are all open directions, and we still expect substantial gains to be made to the models

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support