scanmate-align
Put a scanned or photographed page back onto the original it came from: deskew, rescale and register, trying transform models until one is good enough.
A parallel port of @scanmate/align, not a replacement for it. The
TypeScript remains the reference, and the only useful definition of "correct"
for this package is that it produces the same numbers — bit for bit — as the
TypeScript it parallels.
pip install scanmate-align
from scanmate_align import align_scan
result = align_scan("page1.png", "returned.jpg")
print(result.confidence, result.diagnostics.selected_model, result.transform.rotation_deg)
result.raster sits on the original's canvas, at the original's width and
height, so every coordinate known from the PDF still means what it meant.
Why it exists
Two questions about a returned form are easy to answer once the scan sits exactly on top of the original, and near-impossible before:
- Was anything in the printed text changed? Run OCR on both and diff — which only works if the two are the same page at the same size.
- Was the box at
(x, y)signed? That is a question about a fixed rectangle, and a fixed rectangle only means something once both images agree on where(x, y)is.
How it works
decode → ink → coarse guess → rough warp → features →┬→ RANSAC(similarity) → score →┐
(scale/skew) (ORB) ├→ RANSAC(affine) → score →┼→ warp
└→ RANSAC(homography) → score →┘
The coarse guess exists to make the feature stage possible at all: binary descriptors compare fixed pixel offsets, so they only match between images at comparable scale — and nothing in a JPEG tells you what dpi it was scanned at.
Everything left of the fork happens once, and it is nearly all of the cost. The sweep tries models cheapest first, stops as soon as one is good enough, and a more complex model must earn its extra parameters by a margin: a homography fitted to a flat page bends slightly to follow the page's own noise and would otherwise win every time.
If no model finds a consensus — a nearly blank form has few corners to find —
the coarse estimate is returned on its own and method says so.
One difference from the TypeScript
alignScan is async; align_scan is not. That asynchrony is about libvips on
libuv's threadpool, not about the algorithm — between decode and encode the
TypeScript is as CPU-bound and single-threaded as this. Python's codec is Pillow
and synchronous, so an async def here would be a coroutine that never yields.
The departure is in the calling convention only. Every number is the TypeScript's, held there by goldens generated from the real build — including a byte-identical warped raster on every case.
Requirements
Python 3.11 or newer, and scanmate-ink. Fully typed (PEP 561), mypy --strict
clean.
Metadata
Release files for scanmate-align 0.24.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| scanmate_align-0.24.2.tar.gz | 66.5 kB | Without provenance | Details for scanmate_align-0.24.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| scanmate_align-0.24.2-py3-none-any.whl | Python 3 | none | any | Details for scanmate_align-0.24.2-py3-none-any.whl |
Total release size: 108.8 kB
Release files / scanmate_align-0.24.2.tar.gz
| Download URL | scanmate_align-0.24.2.tar.gz |
|---|---|
| Size | 66.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
521a4696ceeb18b36cb244c1ec8d17cefd9f282485e9b419af18a095dea4689b
|
|
BLAKE2b-256 checksum How to use checksums |
dce91b893b95c9d6a8a303b9f64d4c8a1c96f49c4d640c61a1f2950262a1d90a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / scanmate_align-0.24.2-py3-none-any.whl
| Download URL | scanmate_align-0.24.2-py3-none-any.whl |
|---|---|
| Size | 42.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cf3422a403dcf2a68fba801399a2857be737f9466e07f8041b7313fd8175d387
|
|
BLAKE2b-256 checksum How to use checksums |
384f1f8c29f49e935fef5c50452790893f4fe45eaa0ceea5b38adaff2f7e1706
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for scanmate-align 0.24.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.