Skip to content

About

Classification of historical page images using ViT and CNN - for ATRIUM project

Topics

Resources

Contributing

Stars

6 stars

Watchers

3 watching

Forks

Latest commit

 

History

614 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ATRIUM page-classification: scanned archive pages sorted into eleven page types

page-classification reads the image of a scanned archival page and says what kind of page it is. It chooses one of eleven categories, such as running text, a table or form, a drawing or a photograph, with handwritten, printed or typed text. The category tells which processing the page needs next, for example OCR or table extraction. Use it on scans of paper documents; the labels it gives born-digital pages have not been checked.

Releases · MIT licence · ATRIUM documentation · Models on Hugging Face

Inputs and outputs

Input Output
a page image (any format Pillow reads: PNG, JPEG, TIFF, …), a folder or a tree of them, named <document>-<page>.png per page, the best categories with their scores: a CSV (FILE, PAGE, CLASS-1…N, SCORE-1…N; at -tn 1 also CATEGORY, a copy of CLASS-1: outputs), or JSON from the service
a PDF, recognised by its content: every page, or a pages selection, rendered at 300 dpi optionally all eleven scores (--raw, or topn=11) and each model's own vote (--best --save-intermediates, or per_model=true)
optionally, an ATRIUM document record to add to the record with its page_categories block and each page's category and category_confidence; the run's paradata

The tool reads the image only, so the language of the page does not matter. The command line and the service read the same inputs the same way; what differs, and why, is in docs/usage.md.

The eleven categories and their definitions: docs/reference/categories.md. The record follows the hub's document contract; page-classification is its first stage, so it creates the record as often as it adds to one.

Quick start

What you need: Docker, or Python 3.11 and a checkout of this repository. Network access to huggingface.co on the first start, to download the models (about 2.44 GB for the five of the ensemble); the tool calls no other host. Memory for the models. A GPU is optional: a CPU works, more slowly.

The service, from the published image, on a sample page of this repository:

docker run --rm -p 8000:8000 -v hf-cache:/cache/huggingface \
  ghcr.io/ufal/atrium-page-classification-api:<version>     # the release without its v, e.g. 1.14.2-beta
curl -s localhost:8000/ready                                 # fails until the five models are loaded, then 200
curl --fail-with-body -sS -X POST localhost:8000/predict_image \
  -F "file=@small_data_samples/TEXT_T/pages_online_2.png" -F version=v4.4 -F topn=3

Expected result (abridged):

{"type": "image",
 "predictions": [{"label": "TEXT_T", "score": 0.9}, {"label": "TEXT", "score": 0.099}, {"label": "TEXT_P", "score": 0.001}],
 "models_used": ["v4.4"], "limits_applied": [], "document_json": null,
 "paradata": {"@type": "CreateAction", "…": "…"}}

The scores are those v4.4 gave this page in the stored run result/tables/20261022-1218_v44_TOP-3.csv, rounded. Without version the service uses the ensemble (all), and models_used lists the five revisions that answered. The image holds no weights. On its first start it downloads the five models from the Hugging Face Hub into the hf-cache volume. /health answers at once; /ready returns 200 once the models are loaded. Every endpoint, limit and error: service/README.md.

The same page on the command line, from a checkout with its setup done:

python3 run.py --hf -rev v4.4 -f small_data_samples/TEXT_T/pages_online_2.png

After the argument list and the download messages it prints:

File small_data_samples/TEXT_T/pages_online_2.png predicted:
	TEXT_T:  90.0%
	TEXT:  9.9%
	TEXT_P:  0.1%
Results for TOP-3 predictions are recorded into ./result/tables/<date-time>_model_v44_TOP-3.csv

How it works

The classifiers are fine-tuned Vision Transformer, RegNetY and EfficientNetV2 models, published as revisions of ufal/vit-historical-page. They were trained on annotated pages of archaeological reports from Czech archives, 1920–2020, published as a dataset on LINDAT. One revision can run alone, or the five vX.4 revisions run as an ensemble that averages their scores; the ensemble is the default of the HTTP service.

Each page image is resized to the model's square input (224 or 384 pixels) and scored for all eleven categories; the scores become probabilities, and the best ones are kept, best first. With --best (or version=all) five models score every page and their probabilities are averaged, so a page on which they disagree gets a lower top score. The command line writes CSV tables and a paradata log; the service answers in JSON. More, with the diagrams: docs/how-it-works.md.

Where it fits in ATRIUM

page-classification is the first stage of the route for scanned documents. Its categories inform a routing decision, taken by a person or a script reading the results: which pages go to OCR, to handwriting recognition, to table extraction or to image extraction. The next stage, ocr-postprocess, works from the OCR output and does not read the categories. On the born-digital route, digital-convert's /describe asks /predict_document about the pages that have no usable text layer. The whole chain: the hub's workflow page.

Limits and maturity

  • Accuracy is measured for single models, not for the ensemble. Each vX.4 model scored 94.64–95.87 % top-1 and 99.75–99.90 % top-3 on about 4,800 held-out pages of the fold it was trained on. The split is by page, so about a quarter of those pages come from documents with other pages in training; on pages of unseen documents top-1 is 93.87–95.60 %. The ensemble has no held-out figure, because its members were trained on different folds (docs/evaluation/results.md).
  • Some pages were not measured. Born-digital pages, pages unlike the archaeological reports of the training data, and the optional YOLO backend have no held-out figure, so treat their labels as unchecked. The 2025 sweep's 98–99 % were measured mostly on training pages and are not held-out accuracy (the sweep). The test suite checks that the code does what it says; it does not measure accuracy.
  • Neighbouring categories are the hard cases. TEXT_T is most often taken for TEXT (recall 87–92 %), and LINE_HW for LINE_T, and one category is given per page. A low top score with a close second marks a page worth a look (reading the output).
  • Name a revision. The Hub's main revision still resolves to v4.3, the generation before vX.4, so pass -rev v4.4 (or --best) rather than relying on it. setup/config.txt has [HF] revision = main, and the batch image's default command runs -rev v4.3 (models).
  • PDFs are rendered with pypdfium2 at 300 dpi, by the service and by the command line, while the training pages were made with pdftoppm (the service's known limits).
  • One service request is limited in size. It classifies at most MAX_PDF_PAGES pages (50 by default; a deployment can change it) and takes at most 10 MB (MAX_UPLOAD_MB). Send a longer PDF in parts with pages. The command line has no such limit (Limits).
  • The ensemble can answer with fewer models when one fails to load, so check that models_used lists five (Partial results).
  • The service answers nothing while it loads its models. The first start downloads about 2.44 GB. Until then both /health and /ready refuse the connection, so wait for /ready to return 200 (Known limits).

Documentation

For To Read
using it see one result at once the Quick start above
learn what the eleven labels mean docs/reference/categories.md
classify your own pages, a folder at a time, and read the result tables docs/usage.md
look up models, flags, outputs, paradata and licences models, flags, outputs, paradata, licences
set every option of setup/config.txt docs/configuration.md
running the service deploy and operate it, and read its limits and errors service/README.md
see the API contract service/openapi.json
judging the results decide how far to rely on them Limits and maturity above
see what was measured, and on which data results, data, the 2025 sweep
changing the code understand how a page is classified and how the ensemble runs docs/how-it-works.md
set up, test, release; find the history docs/development.md, CONTRIBUTING.md (its Release History is the changelog)
read why it is built this way docs/decisions/history.md
turn PDFs into an annotated training set docs/data-preparation.md
train, retrain on the published folds, evaluate docs/training.md
run the decision-model experiment decide_pages.py; not in the service docs/reference/cli.md

Terms used across the tools are explained in the ATRIUM glossary. The documentation follows the ATRIUM documentation style.

Licence, citation and acknowledgements

The code is MIT (LICENSE). The fine-tuned models, the LINDAT training dataset they were trained on and the sample pages in small_data_samples are CC BY-NC 4.0, the optional YOLO backend (Ultralytics) is AGPL-3.0, and the service renders PDFs with pypdfium2 (Apache-2.0 or BSD-3-Clause). Each component, with its licence and where that is stated: docs/reference/licences.md. The paradata of a run lists the components it used; it does not set the rights in what the run produces, which depend first on the source document (Licences and paradata).

Cite the method with the preprints Page image classifier fine-tuned on century-spanning archives of scanned documents for further content-specific processing (arXiv 2606.07558, 2026) and Page image classification for content-specific data processing (arXiv 2507.21114, 2025), the models with their Hugging Face repository and revision, the data with its LINDAT record, and the software with CITATION.cff, which lists the authors with their ORCIDs. The tool is listed in the SSH Open Marketplace as Historical documents page classifier - ATRIUM.

Developed by ÚFAL, Charles University, with AMČR (the Archaeological Map of the Czech Republic) as the pipeline partner. Funded by ATRIUM (GA 101132163), with the support of the LINDAT/CLARIAH-CZ research infrastructure and the AIS CR infrastructure (LM2023031). Contact: lutsai@ufal.mff.cuni.cz, or the issue tracker.

© 2026 ÚFAL & ATRIUM

About

Classification of historical page images using ViT and CNN - for ATRIUM project

Topics

Resources

Contributing

Stars

6 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages