Quadra core
Reads a supermarket till receipt from a photo. No ML model, no network calls: Tesseract does the OCR, then geometry and arithmetic do the rest.
from pathlib import Path
from quadra_core import parse_image
document, status = parse_image(Path("receipt.jpg"), profile_id="esselunga")
status is ok, partial or failed. It never raises just because a receipt was hard to read: you get a document back either way, with whatever went wrong listed in validation.warnings.
pip install quadra-core
sudo apt install tesseract-ocr tesseract-ocr-ita # for images
How it works
The line totals plus any discounts have to equal the printed total, so the parser can check its own work.
When the sums don't match it crops out the price column and OCRs that on its own, which gives a second independent reading of every price. Where the two readings disagree it keeps both and picks the combination that hits the printed total. That also recovers lines whose price was unreadable the first time. If two different combinations both add up it changes nothing and flags the receipt.
Adding a shop
Everything shop-specific is a TOML profile in src/quadra_core/profiles/. The code knows how to find a price column, the profile says what a price looks like.
Start with a stub, since calibrate.py needs a profile to report against:
# src/quadra_core/profiles/myshop.toml
[profile]
id = "myshop"
version = 1
calibrated = false
[format]
money = '\d{1,3},\d{2}'
Then point it at a photo:
python tools/calibrate.py receipt.jpg --profile myshop
It prints what Tesseract read, where the price column landed, which rule matched each line, and whether the totals add up. Add [[rules]] and [regions] anchors until the lines stop coming back as unknown. Rules are tried in order and the first match wins, so put the specific ones first.
Add [fingerprint] anchors so the shop is recognised without --profile. A VAT number is more stable than a branch address. Save the OCR as a fixture with --save-fixture NAME so later changes have something to regress against. Set calibrated = true once it balances, otherwise every parse carries a profile_not_calibrated warning.
Before committing a fixture, check it for personal data: the address, the loyalty card number, the points balance. tools/scrub.py covers the Esselunga ones.
Development
uv run pytest
Licence
This project is licensed under the MIT License. See the LICENSE file for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quadra_core-0.1.0.tar.gz.
File metadata
- Download URL: quadra_core-0.1.0.tar.gz
- Upload date:
- Size: 92.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
191afe52adc9e7bc8bebb357e10b07cbf8c175564ff4bd5f5e579e6aa5407446
|
|
| MD5 |
a7031177754d97bde614fbbb78ac0016
|
|
| BLAKE2b-256 |
da73a59b85048bc2f678c474d645fd532f5f73d294d66c71c00c67d451e7ce27
|
Provenance
The following attestation bundles were made for quadra_core-0.1.0.tar.gz:
Publisher:
publish.yml on SteMazzO/quadra-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quadra_core-0.1.0.tar.gz -
Subject digest:
191afe52adc9e7bc8bebb357e10b07cbf8c175564ff4bd5f5e579e6aa5407446 - Sigstore transparency entry: 2795573491
- Sigstore integration time:
-
Permalink:
SteMazzO/quadra-core@8e962eb3145c537d51b66ca1e0ccc098f8728624 -
Branch / Tag:
refs/tags/0.1 - Owner: https://github.com/SteMazzO
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8e962eb3145c537d51b66ca1e0ccc098f8728624 -
Trigger Event:
release
-
Statement type:
File details
Details for the file quadra_core-0.1.0-py3-none-any.whl.
File metadata
- Download URL: quadra_core-0.1.0-py3-none-any.whl
- Upload date:
- Size: 80.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd34afdbdac466633699c3a1d0222b453c5e7290c4679facb14970c3f818f800
|
|
| MD5 |
d7028915a7da10403296ed8cd4545e0b
|
|
| BLAKE2b-256 |
758f64f4efcf19430a535c4979694f5fbe906408551f6150e4953715cdfcfa7b
|
Provenance
The following attestation bundles were made for quadra_core-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on SteMazzO/quadra-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quadra_core-0.1.0-py3-none-any.whl -
Subject digest:
dd34afdbdac466633699c3a1d0222b453c5e7290c4679facb14970c3f818f800 - Sigstore transparency entry: 2795573636
- Sigstore integration time:
-
Permalink:
SteMazzO/quadra-core@8e962eb3145c537d51b66ca1e0ccc098f8728624 -
Branch / Tag:
refs/tags/0.1 - Owner: https://github.com/SteMazzO
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8e962eb3145c537d51b66ca1e0ccc098f8728624 -
Trigger Event:
release
-
Statement type: