r/computervision
•
u/Miserable_Extent8845
•
14h ago
Showcase I built a 2.17M-parameter OCR engine that runs on CPU in ~14 ms per line.
Most OCR libraries work great until you start asking uncomfortable questions:
Does import trigger a network request? Where are the model weights stored? Why does a simple OCR task need hundreds of megabytes of dependencies?
I wanted something different, so I built wormOCR - a lightweight, fully local OCR engine for printed and handwritten English.
The goal was simple: make OCR small, fast, predictable, and genuinely offline.
What makes it different?
No surprise downloads:
import wormocrnever triggers a network request.Explicit model downloads: Run
wormocr downloadonce to get the weights.Verified weights: Downloaded from a pinned GitHub release and checked using SHA-256.
Fully local inference: No cloud APIs, telemetry, or network dependency.
MIT licensed: Open source and free to use.
Two models, different trade-offs
| wormocr-2M | wormocr-9M |
|---|---|
| Parameters | 2.17M |
| Weights | 8.7 MB |
| Best for | Fast, everyday OCR |
How fast is it?
Measured on my laptop:
Single-line inference (wormocr-2M):
CPU: ~14 ms end-to-end.
Full-page inference (same 3 digital pages):
| Engine | Hardware | Time per page |
|---|---|---|
| wormOCR | CPU | ~0.60 s |
| wormOCR | RTX 5060 Laptop GPU | ~0.22 s |
| PP-OCRv6 medium | CPU | ~16 s |
The model weights range from 8.7 MB to 33.5 MB, compared with approximately 132 MB for the PaddleOCR medium stack in my comparison.
These are my own measurements on a small test set, not a comprehensive benchmark. Hardware, configuration, and preprocessing matter.
Try it yourself
pip install wormocr
wormocr download
from wormocr import OCR
ocr = OCR()
result = ocr.predict("invoice_line.png")
print(result.text)Where it stands today.
Clean printed text and receipts are strong. Messy notes and historical handwriting are usable, but still challenging.
Currently:
English printable ASCII only.
Classical page-layout detection using projection profiles, rather than a large learned detector.
Two model sizes with different speed/accuracy trade-offs.
I'd rather be transparent about what doesn't work than market this as a universal OCR solution.
GitHub: https://github.com/arjun988/wormOCR
PyPI: https://pypi.org/project/wormocr/
I'm particularly interested in feedback from people working on OCR, computer vision, edge AI, and offline-first software.
If you find this interesting or think it could be useful, I'd really appreciate a ⭐ on GitHub. It helps the project get visibility and motivates me to keep improving it.
Feedback, issues, PRs, and stars are all very welcome!
Would you actually use an OCR engine this small in a production application? What would you want to see improved first?