ibteda.pt: the deployed geometry model, with its card
Browse files
README.md
CHANGED
|
@@ -47,122 +47,141 @@ audit regenerates this card and fails on any difference. -->
|
|
| 47 |
|
| 48 |
# Model card — pageimprover geometry model
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
## What it
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
is
|
| 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 |
-
0.
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
34.5%<!--claim:route_sweep_930_sealed--> review on sealed and 30.5%<!--claim:route_sweep_930_conf--> on
|
| 118 |
-
confirmation.
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
## Training data and attribution
|
| 122 |
|
| 123 |
-
The model was trained on completed page crops from the **Ibteda corpus**
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
|
| 128 |
That convention is narrow and measured as such: 98.7%<!--claim:canvas_share--> of finished pages used a single
|
| 129 |
-
2048×2897 Photoshop template
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
quality.
|
| 133 |
-
|
| 134 |
-
## Known failure modes — read before deploying off-corpus
|
| 135 |
-
|
| 136 |
-
**The disagreement score's level does not transfer.** Off-distribution, the flip-consistency gap is large,
|
| 137 |
-
signed and material-dependent: on foreign captures it has overstated a small error by more than an order of
|
| 138 |
-
magnitude on one book and tracked a large median on another. `review.score.disagreement_px` is a routing signal,
|
| 139 |
-
not a page error, and off-corpus it must not be read as one in either direction. Its *ordering* was thought to
|
| 140 |
-
survive even where its level did not — until a fourth book gave essentially zero rank correlation and routed its
|
| 141 |
-
two most nearly perfect sides last. Ranking isolates a single-page outlier; it cannot see a systematic per-side
|
| 142 |
-
bias. Do not size a foreign operator budget from this score; ADR 0011 records the figures and the reasoning.
|
| 143 |
-
|
| 144 |
-
**A documented manuscript blind spot.** The deployed model reads printed material well at correct framing and
|
| 145 |
-
reads handwritten manuscript pages badly: 0.0727<!--claim:manuscript_blindspot--> calibrated pass@80 on the
|
| 146 |
-
manuscript sides evaluated, with the routing signal actively anti-ranked rather than merely uninformative. A
|
| 147 |
-
composition-swap model built to fix this was measured and refused — it learned its manuscripts almost perfectly
|
| 148 |
-
and still failed both foreign reads — so the bridge model ships with the blind spot named rather than papered
|
| 149 |
-
over. Anything quoting this model as adequate for manuscript work should quote that number instead (ADR 0012).
|
| 150 |
-
|
| 151 |
-
**Framing is the input the model never sees corrected.** For a capture from outside the archive, the paper block
|
| 152 |
-
must be located and centred at the corpus area fraction before the model has a fair chance; the release measures
|
| 153 |
-
and reports this but applies no such transform on the ordinary path, and whether letterboxing or centring is
|
| 154 |
-
better for a frame with no surround is unmeasured (ADR 0011).
|
| 155 |
|
| 156 |
## Intended use, and what would be misuse
|
| 157 |
|
| 158 |
-
Intended: locating and cropping page geometry for photographed spreads
|
| 159 |
-
as the first stage of
|
| 160 |
-
review of the routed sides.
|
| 161 |
|
| 162 |
-
Misuse: quoting any single number here as "accuracy";
|
| 163 |
-
re-measuring against a local operator's crops;
|
| 164 |
-
score as a per-page error. The model does not finish a page on its
|
| 165 |
-
it is read as a claim that it does.
|
| 166 |
|
| 167 |
## Licence and authorization
|
| 168 |
|
|
|
|
| 47 |
|
| 48 |
# Model card — pageimprover geometry model
|
| 49 |
|
| 50 |
+
A ResNet-34 regression model that predicts the two page crops of a photographed two-page spread. It is the first of
|
| 51 |
+
three stages: the model proposes the crops, a per-book calibration of five spreads corrects them to the book's own
|
| 52 |
+
margins, and a review queue sends the least trustworthy page sides to a person. It was trained and measured on one
|
| 53 |
+
archive's books and is built to be pointed at anyone's; the calibration is what carries it to a book it has never
|
| 54 |
+
seen. On its own it does not produce a finished page, and the figures below only mean anything as a trio.
|
| 55 |
+
|
| 56 |
+
Every performance number here is a row in [`docs/claims.md`](https://github.com/ibteda-org/pageimprover/blob/main/docs/claims.md), which names the cohort, the
|
| 57 |
+
calibration state and the evidence behind it. A build gate refuses any figure that drifts from that ledger.
|
| 58 |
+
|
| 59 |
+
## What it takes as input
|
| 60 |
+
|
| 61 |
+
| | works | does not work |
|
| 62 |
+
|---|---|---|
|
| 63 |
+
| Capture | one photograph per spread, both facing pages in the frame | one page per photograph: the model predicts two crops per image and has nothing to predict on a single leaf |
|
| 64 |
+
| Material | printed books | handwritten manuscripts, a documented blind spot: 0.0727<!--claim:manuscript_blindspot--> calibrated pass@80 |
|
| 65 |
+
| Framing | the paper filling most of the frame, roughly centred, as in the training captures | a small paper block in a wide surround, which the release measures and reports but does not correct |
|
| 66 |
+
| Image size and format | any size; the package letterboxes the image to the model's 704<!--claim:model_input--> px tile itself; JPEG, PNG, TIFF and WebP | |
|
| 67 |
+
|
| 68 |
+
Closed covers are recognised by the framing check and cropped from the detected paper block as single pages; the
|
| 69 |
+
model is not asked about them.
|
| 70 |
+
|
| 71 |
+
## Getting the model
|
| 72 |
+
|
| 73 |
+
Install `pageimprover` and run `pageimprover fetch model`. It downloads `ibteda.pt`, checks the bytes against the
|
| 74 |
+
pinned digest and refuses any others. Nothing downloads on its own, and the model is loaded only through the
|
| 75 |
+
package: it is a TorchScript archive carrying its own preprocessing contract, not a state dict.
|
| 76 |
+
|
| 77 |
+
## How the three stages work
|
| 78 |
+
|
| 79 |
+
**1. The model.** Given one spread, it predicts the left and right page rectangles as a single fixed-length
|
| 80 |
+
vector. Geometric regression, not detection: no anchors, no proposals, no class labels. The 704 px input was chosen
|
| 81 |
+
to fit a T4's memory, not for accuracy, and has never been tuned against the acceptance bar; a larger input is an
|
| 82 |
+
untested lever, not a rejected one.
|
| 83 |
+
|
| 84 |
+
A prediction is scored by its **worst corner**. A page side passes when the worst of its four corners lands within
|
| 85 |
+
80<!--claim:pass_bar--> px of the operator's crop, measured in the fixed 2048×2897 finishing frame. This is
|
| 86 |
+
`metrics.PASS_PX`, a geometry rule and nothing more: not an OCR score, not an aesthetic judgement, and not
|
| 87 |
+
"accuracy" in any sense a reader should generalise.
|
| 88 |
+
|
| 89 |
+
**2. Per-book calibration.** The dominant residual is a per-book size constant: the margins a book was finished at
|
| 90 |
+
leave no trace in a single image, so no model recovers them at any capacity. Ten operator crops do. Five spreads
|
| 91 |
+
(k=5<!--claim:k_default-->), both sides, 10<!--claim:cal_crops--> crops per book, pooled into one offset
|
| 92 |
+
(`calibrate/pooled_median.py`). The offset is applied only when its magnitude reaches 40<!--claim:cal_gate-->
|
| 93 |
+
canonical px (`refusals.CALIBRATION_GATE_PX`); below that it is indistinguishable from an operator's own
|
| 94 |
+
self-consistency and can only add noise.
|
| 95 |
+
|
| 96 |
+
Two design choices are recorded as costs, not victories. Pooled, not per-side: splitting the same ten crops by page
|
| 97 |
+
side harmed 8<!--claim:cal_harm_perside--> held-out books; pooling them harmed 2<!--claim:cal_harm_pooled-->, same
|
| 98 |
+
crops, estimator the only difference. Five spreads, not seven: seven beat five by +0.0104<!--claim:k7_delta-->
|
| 99 |
+
pass@80, decisively (p<0.0001), and was declined because at corpus scale that point costs thousands of extra
|
| 100 |
+
operator pages.
|
| 101 |
+
|
| 102 |
+
**3. Review routing.** A flip-consistency check runs the model on the spread and on its horizontally flipped copy
|
| 103 |
+
and flags a side when the two disagree by more than 87<!--claim:route_threshold--> canonical px
|
| 104 |
+
(`review.absolute`). Those sides go to a person; the rest ship.
|
| 105 |
+
|
| 106 |
+
## Measured performance
|
| 107 |
+
|
| 108 |
+
Two held-out cohorts, both inside the training archive. "Sealed" is a 54-book sensitivity test held back from every
|
| 109 |
+
design decision; "confirmation" is a 192-book cohort unexposed during development. All figures are pass@80.
|
| 110 |
+
|
| 111 |
+
| stage | sealed cohort | confirmation cohort |
|
| 112 |
+
|---|---|---|
|
| 113 |
+
| model alone | 0.6770<!--claim:geo_raw_sealed--> | — |
|
| 114 |
+
| + per-book calibration | 0.8278<!--claim:route_sealed_baseline--> | 0.8334<!--claim:route_conf_baseline--> |
|
| 115 |
+
| + review of the routed sides | 0.9151<!--claim:route_sealed_routed--> | 0.9248<!--claim:route_conf_routed-->, with 28.5%<!--claim:route_conf_share--> of page sides sent to a person |
|
| 116 |
+
|
| 117 |
+
The calibration gain was measured on its own, larger confirmation cohort: held-out pass@80 rose from
|
| 118 |
+
0.7107<!--claim:cal_baseline--> uncalibrated to 0.8271<!--claim:cal_pooled--> with the single pooled offset, a gain
|
| 119 |
+
bought with five spreads of operator work per book.
|
| 120 |
+
|
| 121 |
+
The review share is an in-archive operating point, not a portable promise; a different collection's distribution
|
| 122 |
+
moves it. Reaching a higher 0.930 target under a coverage *sweep*, which is explicitly not the deployed rule, needs
|
| 123 |
34.5%<!--claim:route_sweep_930_sealed--> review on sealed and 30.5%<!--claim:route_sweep_930_conf--> on
|
| 124 |
+
confirmation. A sweep point and the deployed point answer different questions, and the two were once mixed to
|
| 125 |
+
produce a claim that had to be withdrawn.
|
| 126 |
+
|
| 127 |
+
## Using it on another collection
|
| 128 |
+
|
| 129 |
+
The model works on printed-book spreads from other scanning setups, on three conditions.
|
| 130 |
+
|
| 131 |
+
- **Calibrate every book.** Five spreads, ten crops, as above. This is not optional away from the training archive:
|
| 132 |
+
the calibration is what adapts the model to a binding and a finishing convention it has never seen. On a public
|
| 133 |
+
seventeenth-century atlas photographed by another collection, the model located the text block on every spread
|
| 134 |
+
and the remaining error was one consistent margin offset, exactly what the ten crops remove. That run is a worked
|
| 135 |
+
example, not a measurement: no accuracy figure is claimed for other collections, and any figure you need must be
|
| 136 |
+
measured against a local operator's crops.
|
| 137 |
+
- **Frame the paper as the training captures did.** The paper should fill most of the frame, roughly centred. The
|
| 138 |
+
release measures the framing of every frame and reports it, but applies no correction, so a capture with a wide
|
| 139 |
+
surround needs cropping upstream. Whether letterboxing or centring is better for a frame with no surround is
|
| 140 |
+
unmeasured.
|
| 141 |
+
- **Do not carry the review numbers across.** The disagreement score's level does not transfer, its ordering was
|
| 142 |
+
found not to either, and the deployed threshold and review share describe one archive. Read the routed queue as
|
| 143 |
+
a list of sides to look at, not as a forecast of operator workload.
|
| 144 |
+
|
| 145 |
+
## Known failure modes
|
| 146 |
+
|
| 147 |
+
**Handwritten manuscripts.** The deployed model reads printed material well at correct framing and reads
|
| 148 |
+
handwritten pages badly: 0.0727<!--claim:manuscript_blindspot--> calibrated pass@80 on the manuscript sides
|
| 149 |
+
evaluated, with the routing signal actively anti-ranked rather than merely uninformative. A model built to fix this
|
| 150 |
+
was measured and refused: it learned its manuscripts almost perfectly and still failed both foreign reads, so this
|
| 151 |
+
model ships with the blind spot named rather than papered over. Anything quoting this model as adequate for
|
| 152 |
+
manuscript work should quote that number instead.
|
| 153 |
+
|
| 154 |
+
**The disagreement score away from the archive.** On foreign captures the flip-consistency gap is large, signed
|
| 155 |
+
and material-dependent: it has overstated a small error by more than an order of magnitude on one book and tracked
|
| 156 |
+
a large median on another, and on a fourth book its ranking put the two most nearly perfect sides last.
|
| 157 |
+
`review.score.disagreement_px` is a routing signal, not a page error, and away from the archive it must not be read
|
| 158 |
+
as one in either direction.
|
| 159 |
+
|
| 160 |
+
**Framing is never corrected.** The paper block must sit at roughly the training framing before the model has a
|
| 161 |
+
fair chance. The release reports framing; it does not fix it.
|
| 162 |
|
| 163 |
## Training data and attribution
|
| 164 |
|
| 165 |
+
The model was trained on completed page crops from the **Ibteda corpus**: books finished by hand by the archive's
|
| 166 |
+
operators, whose crops are the target the model regresses toward. That labour is the ground truth here; the model
|
| 167 |
+
reproduces a finishing convention, it does not invent one. Any use of this model should credit the Ibteda corpus
|
| 168 |
+
and its operators as the source of the training crops.
|
| 169 |
|
| 170 |
That convention is narrow and measured as such: 98.7%<!--claim:canvas_share--> of finished pages used a single
|
| 171 |
+
2048×2897 Photoshop template, and the export round-trip reconstructs that historical output to a median residual
|
| 172 |
+
of 3.0<!--claim:canvas_residual--> px. The high share is a fact about one archive's finishing habit, not a universal
|
| 173 |
+
page ratio, and the residual describes the convention's reproducibility, not the model's quality.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
## Intended use, and what would be misuse
|
| 176 |
|
| 177 |
+
Intended: locating and cropping page geometry for photographed two-page spreads of printed books, from the archive
|
| 178 |
+
it was trained on or from any other scanning setup, as the first stage of the three-stage loop whose other two
|
| 179 |
+
stages are a person's calibration crops and a person's review of the routed sides.
|
| 180 |
|
| 181 |
+
Misuse: quoting any single number here as "accuracy"; treating the figures as a promise about another collection
|
| 182 |
+
without re-measuring against a local operator's crops; deploying on handwritten manuscript pages; citing a review
|
| 183 |
+
share as portable; or reading the disagreement score as a per-page error. The model does not finish a page on its
|
| 184 |
+
own, and this card exists so that no figure in it is read as a claim that it does.
|
| 185 |
|
| 186 |
## Licence and authorization
|
| 187 |
|