Skip to main content

Multilingual handwritten OCR for student notes - production-grade text extraction

Project description

🖋️ HandScribe OCR

Production-grade multilingual handwritten OCR for student notes

CI License: MIT Python 3.9+ Docker


✨ Features

  • Three OCR Backends: EasyOCR, PaddleOCR, and TrOCR behind a unified interface
  • Multilingual Support: 80+ languages including English, Swahili, Arabic, Hindi, French
  • Advanced Preprocessing: Denoising, CLAHE contrast enhancement, adaptive binarization, deskew
  • CLI & REST API: Use from command line or integrate into any application
  • Docker Ready: One-command deployment, no Python environment needed
  • Batch Processing: Process hundreds of student notes automatically
  • Production-Grade: Tested, typed, CI/CD-enabled, PyPI-ready

🚀 Quick Start

Option 1: Docker (Recommended)

docker run -p 8000:8000 ronaldgosso/handscribe

# Test it
curl -X POST http://localhost:8000/ocr \
  -F "file=@my_notes.jpg" \
  -F "languages=en,sw"

Option 2: Python Package

pip install handscribe[easyocr]

# CLI
handscribe extract student_notes.jpg -b easyocr -l en,sw

# API server
uvicorn ocr_engine.api:api --host 0.0.0.0 --port 8000

Option 3: From Source

git clone https://github.com/ronaldgosso/handscribe.git
cd handscribe
pip install -e ".[easyocr]"
handscribe --help

📖 Usage

CLI

# Extract text
handscribe extract image.jpg -b easyocr -l en,sw

# Output as JSON
handscribe extract image.jpg --json

# Save to file
handscribe extract image.jpg -o output.txt -c 0.6

# Batch process a directory
handscribe batch ./student_notes/ -o ./results/

# Compare all backends on the same image
handscribe compare image.jpg -l en,sw

REST API

Start the server and open http://localhost:8000/docs for interactive docs.

# Extract text with bounding boxes
curl -X POST http://localhost:8000/ocr \
  -F "file=@notes.jpg" \
  -F "backend=easyocr" \
  -F "languages=en,sw" \
  -F "confidence=0.5"

# Plain text only
curl -X POST http://localhost:8000/ocr/text \
  -F "file=@notes.jpg"

# Batch (up to 10 files)
curl -X POST http://localhost:8000/ocr/batch \
  -F "files=@img1.jpg" -F "files=@img2.jpg"

Python API

from ocr_engine import OCREngine, OCRBackend

engine = OCREngine(
    backend=OCRBackend.EASYOCR,
    languages=["en", "sw"],
    confidence_threshold=0.5,
)

# With bounding boxes
results = engine.extract("student_notes.jpg")
for r in results:
    print(f"{r.text} (conf: {r.confidence:.2f})")

# Plain text
text = engine.extract_text("student_notes.jpg")

# Batch
batch = engine.extract_batch(["note1.jpg", "note2.jpg"])

🔧 OCR Backends Comparison

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

Tanzanian Context: For Swahili + English mixed notes, use -l en,sw with EasyOCR. The Latin script support handles most Swahili text well. For production-grade Swahili accuracy, fine-tuning TrOCR on a Swahili handwriting dataset is recommended.


🐳 Docker

# Run
docker run -p 8000:8000 ronaldgosso/handscribe

# Build from source
docker build -t handscribe .
docker run -p 8000:8000 handscribe

# Docker Compose
docker compose up -d

See CONTRIBUTING.md for full Docker setup instructions.


🏗️ Architecture

handscribe/
├── ocr_engine/
│   ├── __init__.py          # Package exports
│   ├── engine.py            # Core OCR engine (3 backends)
│   ├── preprocessing.py     # Advanced image preprocessing
│   ├── cli.py               # CLI interface (Typer)
│   └── api.py               # REST API (FastAPI)
├── tests/
│   └── test_engine.py       # Comprehensive test suite
├── pyproject.toml           # Package configuration
├── Dockerfile               # Multi-stage Docker build
├── docker-compose.yml       # Docker Compose setup
└── .github/workflows/ci.yml # CI/CD pipeline

🧪 Development

See CONTRIBUTING.md for the full developer guide, including:

  • Virtual environment setup
  • Running the CLI, API server, and Docker
  • Running tests with coverage
  • Linting with ruff, black, and mypy
  • Git workflow and PR submission
  • Adding new OCR backends

Quick start for developers:

git clone https://github.com/ronaldgosso/handscribe.git
cd handscribe
python -m venv .venv && source .venv/bin/activate  # or .venv\Scripts\Activate on Windows
pip install -e ".[all,dev]"
pytest tests/ -v

📝 Examples

Process Tanzanian Student Notes

handscribe extract notes.jpg -b easyocr -l en,sw -c 0.5
handscribe compare notes.jpg -l en,sw
handscribe batch ./semester_notes/ -l en,sw -o ./ocr_results/

API Integration (Python)

import requests

with open("student_notes.jpg", "rb") as f:
    response = requests.post(
        "http://localhost:8000/ocr",
        files={"file": f},
        data={"backend": "easyocr", "languages": "en,sw", "confidence": 0.5},
    )

print(response.json()["full_text"])

🙏 Acknowledgments

  • EasyOCR — Jaided AI for excellent multilingual OCR
  • PaddleOCR — PaddlePaddle team for fast OCR implementation
  • TrOCR — Microsoft for transformer-based handwriting OCR
  • Tanzanian Students — Inspiring this tool for real-world impact

📧 Contact

Ronald Gossoronaldgosso@gmail.com

Project Link: https://github.com/ronaldgosso/handscribe


Made with ❤️ for students everywhere

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

handscribe-0.1.0.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

handscribe-0.1.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file handscribe-0.1.0.tar.gz.

File metadata

  • Download URL: handscribe-0.1.0.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for handscribe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5e9689294729c40fcee275f8b16e178567ab7014a1077e8243e1531104c997d8
MD5 07ffe1783201f5a7b279176564ea02fa
BLAKE2b-256 7dbce8b38f435a373d20a7ebe2ea6d4ac244272761845f7b6aec3e76cf0a2e50

See more details on using hashes here.

Provenance

The following attestation bundles were made for handscribe-0.1.0.tar.gz:

Publisher: publish.yml on ronaldgosso/handscribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file handscribe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: handscribe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for handscribe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8057f3bd62779735b82358108be6bd6fbe9e3fcafe63990cc364c72a003e2190
MD5 4ae84d55988d9e9044ab69352e175507
BLAKE2b-256 39b76c54576c72c801b302658c771eabc0d10de9163e9a656221ebecb622234c

See more details on using hashes here.

Provenance

The following attestation bundles were made for handscribe-0.1.0-py3-none-any.whl:

Publisher: publish.yml on ronaldgosso/handscribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page