🖋️ HandScribe OCR
Production-grade multilingual handwritten OCR for student notes
What is HandScribe?
HandScribe extracts text from handwritten student notes in 80+ languages. It wraps three OCR engines — EasyOCR, PaddleOCR, and TrOCR — behind a single interface with advanced image preprocessing, a CLI, a REST API, and one-command Docker deployment.
Built for Tanzanian students. Designed for everyone.
Quick Start
| Method | Command |
|---|---|
| Docker (zero setup) | docker run -p 8000:8000 ronaldgosso/handscribe |
| pip install | pip install handscribe |
| From source | git clone https://github.com/ronaldgosso/handscribe.git && cd handscribe && pip install -e . |
Usage
CLI
handscribe extract notes.jpg -b easyocr -l en,sw # extract text
handscribe extract notes.jpg --json # output as JSON
handscribe extract notes.jpg -o output.txt -c 0.6 # save to file
handscribe batch ./images/ -o ./results/ # batch process
handscribe compare notes.jpg -l en,sw # compare all backends
REST API
uvicorn ocr_engine.api:api --port 8000
# Interactive docs → http://localhost:8000/docs
curl -X POST http://localhost:8000/ocr \
-F "file=@notes.jpg" -F "backend=easyocr" -F "languages=en,sw"
Python
from ocr_engine import OCREngine, OCRBackend
engine = OCREngine(backend=OCRBackend.EASYOCR, languages=["en", "sw"])
text = engine.extract_text("student_notes.jpg")
OCR Backends
| Backend | Best For | Languages | Speed | Accuracy |
|---|---|---|---|---|
| EasyOCR | Quick setup, mixed scripts | 80+ | ⚡⚡⚡ | ⭐⭐⭐⭐ |
| PaddleOCR | Fast processing, documents | 80+ | ⚡⚡⚡⚡ | ⭐⭐⭐⭐ |
| TrOCR | Handwriting accuracy | English* | ⚡⚡ | ⭐⭐⭐⭐⭐ |
*TrOCR can be fine-tuned for other languages.
Language Codes
| Language | EasyOCR | PaddleOCR |
|---|---|---|
| English | en |
en |
| Swahili | sw |
en (Latin script) |
| Arabic | ar |
arabic |
| Hindi | hi |
hi |
| French | fr |
french |
CI/CD Pipeline
HandScribe uses two separate GitHub Actions workflows:
| Workflow | File | Triggers | What It Does |
|---|---|---|---|
| CI | ci.yml |
Push, PR | Lint → Test → Build & push Docker image |
| Publish | publish.yml |
Tag push (v*), Release, Manual |
Build & publish to PyPI |
| Pages | pages.yml |
Push to main (docs/) |
Deploy landing page to GitHub Pages |
How It Works
push / PR
│
├── lint ─── ruff ─ black ─ mypy
│
└── test ─── pytest (41 tests, 60% coverage)
│
└── on main ── build & push Docker image to Docker Hub
push tag v0.1.0
│
└── publish ─── build ─── twine check ─── upload to PyPI
Status Badges
| Badge | Status |
|---|---|
| CI Build | |
| PyPI Publish |
Publishing a Release
# 1. Bump version in pyproject.toml
# 2. Tag and push
git tag v0.1.0
git push origin v0.1.0
# → GitHub Actions auto-publishes to PyPI
Docker
docker run -p 8000:8000 ronaldgosso/handscribe # run
docker build -t handscribe . # build
docker compose up -d # compose
Full instructions in CONTRIBUTING.md.
Architecture
handscribe/
├── ocr_engine/
│ ├── engine.py # Core OCR engine (3 backends)
│ ├── preprocessing.py # Denoise, CLAHE, binarize, deskew
│ ├── cli.py # CLI (Typer) — extract, batch, compare, info
│ └── api.py # REST API (FastAPI) — /ocr, /ocr/text, /ocr/batch
├── tests/
│ └── test_engine.py # 41 tests
├── .github/workflows/
│ ├── ci.yml # Lint → Test → Docker
│ └── publish.yml # Build → PyPI
├── Dockerfile # Optimized single-stage build
├── docker-compose.yml
└── pyproject.toml
🔧 Add Other OCR Backends
EasyOCR is included by default. Add PaddleOCR or TrOCR as optional extras:
pip install handscribe[paddle] # PaddleOCR — faster, document-style
pip install handscribe[trocr] # TrOCR — highest handwriting accuracy
pip install handscribe[all] # Both PaddleOCR + TrOCR
from ocr_engine import OCREngine, OCRBackend
# Switch backend at runtime
engine = OCREngine(backend=OCRBackend.PADDLE, languages=["en"])
engine = OCREngine(backend=OCRBackend.TROCR)
🧪 Development
git clone https://github.com/ronaldgosso/handscribe.git
cd handscribe
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[all,dev]"
pytest tests/ -v
Full guide → CONTRIBUTING.md
Acknowledgments
- EasyOCR — Jaided AI
- PaddleOCR — PaddlePaddle
- TrOCR — Microsoft
- Tanzanian Students — the inspiration
Ronald Gosso — ronaldgosso@gmail.com · GitHub
Made with ❤️ for students everywhere
Metadata
Release files for handscribe 0.1.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 | |
|---|---|---|---|
| handscribe-0.1.2.tar.gz | 29.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| handscribe-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.1 kB
Release files / handscribe-0.1.2.tar.gz
| Download URL | handscribe-0.1.2.tar.gz |
|---|---|
| Size | 29.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81a355d302e843141ccf8a161c820525a5d214263a0015229d565531a3d3bcd9
|
|
BLAKE2b-256 checksum How to use checksums |
bca6c50cad774c19f0d3b466c2bf793d67b86db1099d4d3b716fcbe911bc0599
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.
Transparency logRelease files / handscribe-0.1.2-py3-none-any.whl
| Download URL | handscribe-0.1.2-py3-none-any.whl |
|---|---|
| Size | 27.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e729609a58297a994198c31973e1067a90c3b751b11e0fd29a33f12c917630b9
|
|
BLAKE2b-256 checksum How to use checksums |
16704f4e4283dd8d2a06220fe8946079f5f598c538e8266ecf18cfb883b8d185
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.
Transparency log