Skip to content
adrianiftodePublic

About

Turn **photos of homework / test pages** into clean, grouped, **print-ready A4 documents**. Built for the recurring "my kid's homework was shared as WhatsApp photos" workflow — especially Romanian 4th-grade material.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

21 Commits

Folders and files

Repository files navigation

homeworks-ocr

Turn photos of homework / test pages into clean, grouped, print-ready A4 documents. Built for the recurring "my kid's homework was shared as WhatsApp photos" workflow — especially Romanian 4th-grade material.

It leans on the OCR engine that already ships with Windows (Windows.Media.Ocr via winsdk), so there is no Tesseract / external binary to install. On top of that it adds deskewing, upscaled region re-OCR and an A4 print builder (markdown → HTML → PDF via headless Edge/Chrome).

Why this exists: the AI assistant that drove this work cannot view images. Reading the photos therefore had to go through an OS OCR step. This repo keeps that whole pipeline reusable.

Why it looks the way it does

  • Windows OCR, not Tesseract. winsdk gives ro-RO and en-US recognisers out of the box. owl/tesseract installs on Windows are a pain; this just works.
  • Deskew first. Phone photos are rotated a few degrees; Hough-line deskew markedly improves line reconstruction.
  • Region re-OCR. When an option/answer isn't read, crop that fraction of the page and try 4 preprocessing variants × 2 languages.
  • One file per test, then one combined print file. Markdown is the source of truth; the HTML/PDF are generated.
  • Print is the easy path; handwriting needs a fallback. Windows.Media.Ocr recognizes print only, and the offline handwriting options tried (TrOCR, EasyOCR) were not good enough on cursive. hwocr hwr is the escape hatch: it sends a cropped, upscaled photo to a cloud vision model (OpenRouter) and asks for a verbatim transcript. It is optional — it needs network + a key. When a single zoom level comes back empty, pass --zooms <px...> (and optionally --models <ids...>) to walk a zoom ladder and stop at the first non-empty transcript.

Requirements

  • Windows 10/11
  • Python 3.9–3.12 (tested on 3.11)
  • The Romanian language pack (for ro-RO OCR). If missing: Settings → Time & Language → Language & region → add Română → Language options → Optical character recognition.
  • Optional, for handwriting (hwocr hwr): an internet connection and an OpenRouter API key. No extra Python dependency — it uses urllib.

Install

python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
pip install -e .
# or, to get the `hwocr` command on PATH:
pip install -e .
# If you're in Git Bash/cmder (bash), you can also use the launcher:
./scripts/hwocr.sh --help

Usage

# 0) what OCR languages does this machine have?
python -m hwocr langs

# 1) OCR a whole folder (deskew + upscale), save one .txt per photo
python -m hwocr ocr "D:\poze\tema" --out "D:\poze\tema\_ocr"

# same, with coordinates and layout JSON (helps locate a bad line)
python -m hwocr ocr "D:\poze\tema" --out "D:\poze\tema\_ocr" --boxes --json

# 2) re-read one stubborn region (fractions of the page: left top right bottom)
python -m hwocr region "D:\poze\tema\pag63.jpg" -r 0.05 0.20 0.60 0.30 --factor 5

# 2b) embed the exact unreadable regions as images (from a crops.json map)
python -m hwocr crops "D:\poze\tema\crops.json" --out "D:\poze\tema"

# 2c) HANDWRITING? Windows OCR is print-only -> use a (free) vision model.
#     crop to the ink first, then rotate/upscale as needed
python -m hwocr hwr "D:\poze\tema\manuscris.jpg" --rotate 90 --out "D:\poze\tema\_hwr"
python -m hwocr hwr --list-models   # current free vision models (no key needed)
#     retry at increasing zoom until the model returns text (first non-empty wins):
python -m hwocr hwr "D:\poze\tema\tabla.jpg" --zooms 1400 2000 2600 3400
#     ... or try several models in order:          --models idA idB ...

# (Bash/Git Bash/cmder) equivalent:
# ./scripts/hwocr.sh hwr "D:/poze/tema/manuscris.jpg" --rotate 90 --out "D:/poze/tema/_hwr"

# 3) build the printable bundle from the hand-cleaned markdown
python -m hwocr build TEST_1.md TEST_2.md TEST_3.md --out TOATE_TESTELE_print
#   -> TOATE_TESTELE_print.md / .html / .pdf  (A4, one test per page)
#   (if none of --md/--html/--pdf are given, all three are written by default)

build defaults to writing markdown + HTML + PDF. Add --md, --html and/or --pdf to pick specific outputs. The PDF export reuses Edge or Chrome in headless mode and stamps "Pagina X din Y" at the bottom of every page (pass --no-page-numbers to skip that).

The recommended end-to-end process

  1. hwocr ocr <photos> --out <dir> — get a first raw pass.
  2. Read the .txts, fix the obvious character errors, group them by test (not by photo), and write one clean TEST_*.md per test.
  3. For anything unreadable, hwocr region ... on that fraction of the page.
  4. hwocr crops crops.json --out . — cut the unreadable strips into crops/*.png and reference them from the md (![...](crops/x.png)) next to the warning text.
  5. hwocr build ... — one combined A4 PDF to print.

See docs/WORKFLOW.md for the field notes and the exact conventions that worked, and examples/ for a skeleton.

Project layout

hwocr/
  engine.py      # Windows.Media.Ocr + deskew + region re-OCR (print)
  handwriting.py # `hwr`: handwriting via an optional cloud vision model
  build.py       # markdown -> A4 markdown/html/pdf
  crops.py       # `crops`: cut unreadable regions from a JSON map
  cli.py         # `hwocr` command line
docs/
  WORKFLOW.md    # how to actually do a session, plus gotchas
  HANDWRITING.md # handwriting findings + the OCR experiments behind them

Notes & limitations

  • OCR is not perfect on perspective-distorted or low-light photos. Anything uncertain should be flagged in the output (the generated sheets use an asterisk * + a legend rather than silently guessing), and such warnings are rendered at 1.25× size, bold + red so they are easy to spot and correct. The unreadable photo strip itself can be embedded next to the warning as an image via hwocr crops + a ![alt](crops/x.png) line in the markdown.
  • Handwriting goes to the cloud. hwocr hwr uploads the (cropped) image to OpenRouter, so don't use it on material you may not send off — and keep the API key out of the repo (see docs/HANDWRITING.md).
  • Only the tooling is meant to be committed here. Do not commit copyrighted textbook/homework content — keep generated sheets out of the repo (see .gitignore).

License

MIT — see LICENSE.

About

Turn **photos of homework / test pages** into clean, grouped, **print-ready A4 documents**. Built for the recurring "my kid's homework was shared as WhatsApp photos" workflow — especially Romanian 4th-grade material.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages