Vesuvius Challenge · research notes · October 2026

Mesh-Free Ink Search

Automatic surface volumes from the published surface predictions, checked against hand-traced segments, a label-free test for lines of writing, and what they found on two unread scrolls.

Summary

1 · MethodSurface volumes from the surface prediction

Only one of the 21 scrolls on the challenge's unread list (PHerc0800) has published segments. Eleven of them have the organisers' m7 surface prediction on the same grid as the scan. Inside a block a few millimetres across, sheets are close to parallel, so a height field is enough:

On an M1 Pro laptop a 1.5 cm field takes about 8 minutes to grow at 9.6 µm; ink inference runs on the Apple GPU.

Check 1: 9 µm, PHerc0139 w043 (known text)

Ink predictions at 9 µm: published segment versus mesh-free surface
PHerc0139 w043, same 7.2 mm window. Left: ink_9um on the published, hand-traced segment. Middle: this pipeline's sampler run along the published mesh (r = 0.57 with the left map). Right: the same with the depth order reversed (r = 0.13). The fully mesh-free surface from the tracker gives r = 0.55.

Check 2: 2.4 µm, PHerc0841 w00 (known text, held out for ink_9um)

CT renders and 2 µm ink predictions, published versus mesh-free
PHerc0841 w00, 4.9 mm window. Top: CT at the recto surface, published segment (left) and mesh-free surface (right). Bottom: ink_canonical_2um on each. After the −16° rotation between the two frames, r = 0.72 (other rotations 0.08 to 0.23).

2 · OrientationWhat the ink models are sensitive to

Ink_9um (seed42 step-040000) on PHerc0841 w00, a 9.8 mm crop of the published 2.4 µm surface volume pooled 4×4×4 to the model's 9.6 µm grid, run on every in-plane rotation and flip, each prediction mapped back and scored against the organisers' labels inside the supervision mask.

depth orderrot0rot0+fliprot90rot90+fliprot180rot180+fliprot270rot270+flip
as-published0.8160.8030.7850.8450.8320.8420.8010.845
depth-reversed0.5440.5420.5860.5380.6430.6520.4890.551

Averaging all 8 orientations gives AUC 0.849, the same as the 4 mirror variants that --tta-mirror already averages (0.849), and 0.033 above a single pass. The 2 µm model scored 0.988 to 0.990 in the four orientations run.

Across all published segments (908 meshes on 308 segments, scripts/experiments/audit_orientation.py), 500 meshes run the scroll axis down the rows and 408 up: all of Paris 4 and PHerc0172, half of PHerc1667. Given the table above this does not matter for ink_9um; it matters for pixel-level comparisons between renders.

3 · Text testA label-free score for lines of writing

In a published-layout render, lines of text are horizontal and repeat vertically, 6.55 mm apart (median of 73 measurements on 13 labelled segments; middle 80% 5.65–7.27 mm). The first version (v1, "peakness") compared spectral power in that band with its neighbours, vertical against horizontal. Unit tests showed both v1 and a red-noise variant (v2) are too noisy on a 20 mm tile, which holds only about three line periods. The primary score (v3) averages each row across the tile first (lines span the tile, so this suppresses noise), at tilts of −6° to +6°, and compares the fraction of row-profile power in the band with the same for columns.

Two guards reject geometry: the same score computed on the field's own hole and outline map (mask peak ≤ 1), and coverage ≥ 0.6 with holes ≤ 12% of the outline. The early calibration below (v1) looked convincing; the benchmark in section 5 shows it does not hold on 9 µm outputs.

Line-periodicity score over a published ink map
Line-periodicity score on the published 2.4 µm prediction of PHerc. Paris 4 segment 20231005123336, 20 mm tiles every 5 mm. Red marks high scores: the text columns light up and the blank margin between them stays dark.
MapPeakness
Known text, mesh-free surface (w043, 9 µm)+1.79
Known text, published segment (w043, 9 µm)+1.60
Published 2.4 µm predictions, 20 mm tiles, median (Paris 4, PHerc0139, PHerc0841)+1.5 to +1.9
PHerc0800 published segments (presumed blank)−0.90 to +0.35

4 · SearchPHerc1203 and PHerc0846A

Both scrolls are unread and have 2.4 µm scans with a surface prediction. Neither has published segments; PHerc1203 has 22 raw auto-grown meshes (about 130 cm²), PHerc0846A has none. Seeds were placed automatically on surface-prediction sheets at several heights; each 1.5 cm field was grown at 9.6 µm, run through ink_9um (two checkpoints) and scored.

presumed blankknown text-2-1+0+1+2peakness score (20 mm field, 9.6 µm)PHerc1203PHerc1203 peak +0.82 (fails a geometry guard)PHerc1203 peak +0.68PHerc1203 peak +1.74 (fails a geometry guard)PHerc1203 peak -2.02 (fails a geometry guard)PHerc1203 peak -1.04 (fails a geometry guard)PHerc1203 peak +0.47PHerc1203 peak +0.18 (fails a geometry guard)PHerc1203 peak +0.50 (fails a geometry guard)PHerc1203 peak +1.16PHerc1203 peak +1.21PHerc1203 peak +0.53PHerc1203 peak +0.84PHerc1203 peak -0.04PHerc1203 peak -0.15PHerc1203 peak +0.24 (fails a geometry guard)PHerc1203 peak +1.81 (fails a geometry guard)PHerc1203 peak +1.22PHerc0846APHerc0846A peak +1.11 (fails a geometry guard)PHerc0846A peak +0.51 (fails a geometry guard)PHerc0846A peak -1.64 (fails a geometry guard)PHerc0846A peak -0.66 (fails a geometry guard)PHerc0846A peak -0.75 (fails a geometry guard)PHerc0846A peak -0.45PHerc0846A peak -0.42 (fails a geometry guard)PHerc0846A peak -0.26PHerc0846A peak +1.56 (fails a geometry guard)PHerc0846A peak +0.72PHerc0846A peak +0.39 (fails a geometry guard)PHerc0846A peak +0.88 (fails a geometry guard)PHerc0846A peak +1.52 (fails a geometry guard)PHerc0846A peak -0.53 (fails a geometry guard)PHerc0846A peak +1.96 (fails a geometry guard)PHerc0846A peak -0.62 (fails a geometry guard)
passes the geometry guardsfails a guard (coverage, holes or mask peak)

33 fields were scored with v1; 12 pass the guards and 3 of those reach a peakness of 1.0. Of the 5 fields in the known-text range, 0 pass the guards. Two of the rejected ones are below. Section 5 shows that at 9 µm these scores do not separate text from no text, so this ranking only chose where to look at 2.4 µm.

Torn PHerc1203 field with a high score
A rejected hit (PHerc1203, peak +1.82). CT at the surface, 9 µm ink, and the row profile. The surface is torn; the model fires on frayed fragment edges. Coverage 0.58 fails the 0.6 guard.
PHerc0846A field whose outline drives the score
A rejected hit (PHerc0846A, peak +1.56). The field's own hole and outline map scores +2.34, so the periodicity comes from geometry. Its 1 cm read at 2.4 µm has 6% sparse ink blobs, several beside holes.

Earlier 2.4 µm reads of the best-looking patches (5 mm and 1 cm, 2 µm ResNet-152 model) also showed no strokes: on PHerc0846A the model fires over broad saturated regions (46% of a 1 cm field) with tile-shaped edges, which is over-response on that papyrus, not writing.

Negative within limits: 33 fields of 1.5 cm cover a few percent of each scroll's scanned band, and on scrolls the models did not train on even correct predictions are weak (villa #1867). This is evidence that these two scrolls do not show text to the current public models in the sampled areas, not that they carry none.

5 · BenchmarkDoes the text score work? A pre-registered test

Plan and thresholds were committed before the runs (PREREG.md, with every later change listed as a dated deviation). Negatives come from the same surfaces: running ink_9um with the depth order reversed removes the ink signal (AUC near 0.5) but keeps every crack, tear and fibre. Positives are the same maps in the direction the labels confirm.

B1 used 14 labelled segments; 14 had a clear text direction (AUC gap ≥ 0.05 and best AUC ≥ 0.60). Line band 5.65–7.27 mm, measured from the labels.

segmentAUC forwardAUC reversetext direction
PHerc0009B_20250919125754-auto_grown_2025091900.8060.552forward
PHerc0139_20250108000005-w030_20250108180.9360.530forward
PHerc0139_20250831000000-w040_20250831020.9970.496forward
PHerc0139_20260108000000-w041_20260108161.0000.530forward
PHerc0139_20260112000000-w043_20260112170.8530.575forward
PHerc0139_20260115000000-w044_20260115220.9780.546forward
PHerc0139_20260126000000-w045_20260126190.8810.454forward
PHerc0139_20260302000000-w039_20260302100.9990.450forward
PHerc0139_20260317000000-w035_20260317180.9990.512forward
PHerc0500P2_20250825181859--10.7450.533forward
PHerc0814_20260226000000-46527_2um_try20.8930.443forward
PHerc0841_20260220213127-w000.7530.499forward
PHerc0841_20260220214732-auto_grown_20260220140.7210.579forward
PHerc0841_20260221022814-auto_grown_20260220170.7510.601forward
scoreP1 direction correctP2 tile AUCP4 held-out FPRheld-out TPR
v3 row-profile (primary)6/140.5020.0370.056
v2 red-noise7/140.5380.0600.102
v1 peakness9/140.5650.0600.148
anisotropy13/140.6740.0320.153
mean ink12/140.8370.0970.426
fraction > 0.512/140.8920.0690.741
separation (#1867)14/140.8560.7410.824

P3. Published 2.4 µm prediction tiles versus their 90°-rotated copies: AUC 0.916 over 1701 tiles; 0.973 over the 535 tiles where labels confirm ink.

P5. Synthetic Greek text added to wrong-direction maps, detection rate at the calibrated threshold (1.19) by added amplitude: 0: 5% · 0.02: 6% · 0.05: 8% · 0.1: 17% · 0.2: 27% · 0.4: 31%. Real text contrast in the text-direction maps (labelled ink minus supervised non-ink): median 0.281.

P6. Of 12 clean search fields on PHerc1203 and PHerc0846A, 0 pass the calibrated test after Benjamini–Hochberg at q = 0.10.

Exploratory, not pre-registered. Labels cover only 1–13% of each segment, so most "text-direction" tiles hold no text. Restricted to the 56 tiles where labels confirm ink, v3 still reaches only AUC 0.568 against all 216 wrong-direction tiles, and flags 5% of them at a 5% false-positive rate. Injection agrees: synthetic lines on top of real 9 µm output are detected only when they are stronger than real ink. The most line-like wrong-direction tiles are plain blob noise, not text from the next winding.

Reading the result. The score recognises lines in crisp maps (P3) but not in 9 µm outputs, where ink comes out as millimetre blobs. Any label-free text test on 9 µm maps needs more than three line periods per tile, or a sharper ink model. For choosing the depth direction, use the separation rule: it was right on every segment here.

6 · PilotCan the text score rank checkpoints without labels?

Villa #1867 found that in-distribution validation does not rank ink_9um checkpoints on a held-out scroll. If a label-free score did, it would help choose a checkpoint for an unread scroll. Test: all 14 ink_9um checkpoints, both depth directions, on the 9.366 µm volume of PHerc0841 w00 (40 × 45 mm), scored against the organisers' labels.

Across 14 checkpoints (forward direction, AUC 0.703 to 0.822), the rank correlation with label AUC is +0.00 for the text score and +0.01 for the separation rule from villa #1867. Picking the depth direction: text score right in 11 of 14 checkpoints, separation rule in 14 of 14.

checkpointAUC (labels)text scoreseparation
seed43/step-0500000.822+0.480.277
seed43/step-0200000.779+0.360.264
seed43/step-0750000.773+0.510.299
seed42/step-0300000.771+0.970.236
seed42/step-0100000.767+0.710.201
seed42/step-0200000.766+0.160.251
seed42/step-0400000.762+0.070.263
seed42/step-0600000.759+0.230.290
seed42/step-0750000.748+0.160.297
seed42/step-0500000.747-0.070.284
seed43/step-0600000.740+0.390.280
seed43/step-0400000.718+0.640.280
seed43/step-0100000.717+0.410.202
seed43/step-0300000.703+0.980.259

7 · ReuseWhat is in the repository

Clone github.com/mletic/vesuvius-meshfree-ink, run make env once (pinned model environment and weights), then make benchmark and make report. The plan and every deviation are in PREREG.md; raw scores in results/.

uv run python -m vesuvius_sweep.grow PHerc0841 1984 3997 3553 --size 512 --hires --layers 65   # 2.4 µm surface volume, no mesh
uv run python scripts/search/triage.py PHerc0846A --n-z 9 --spacing 550 --max 40                   # seed, grow, ink, score, guard
uv run python scripts/text_line_score.py INK.tif --um 2.4 --out heat.png                    # text score on any ink map
uv run python scripts/experiments/orientation_sensitivity.py 9um                                        # 8 orientations × 2 depth orders vs labels
uv run python scripts/experiments/audit_orientation.py                                                  # scroll-axis direction of every mesh
uv run python scripts/benchmark/ckpt_rank.py                                                          # checkpoint-ranking pilot