ailiteracynepal 🇳🇵
Text size

Chapter 05 · Section III · 26 min read

A tiny Devanagari OCR demo

A pre-trained model running on your laptop. Point it at a photo of Nepali text, and it gives you the text back. Fifteen lines of code, no internet, no API bill.

Section 2 sent text to a model running on someone else’s servers. This section runs a model on your laptop. The task is OCR — Optical Character Recognition — turning a photograph of text into actual text characters. Specifically, Nepali text written in Devanagari script. Twenty years ago this required a research lab. Today it is fifteen lines of Python and a free download.

What we will build

A small program that takes the path to an image — a photo of a signboard, a screenshot of a Nepali article, a snap of a handwritten note — and prints the Devanagari text it contains.

Input:  photo of a sign reading "खाजा घर"
Output: "खाजा घर"

That is it. From there, the obvious next steps — translate the output, summarise a Nepali document, search across a folder of scanned bills — are small extensions you can build on a weekend.

The tool: Tesseract

We will use Tesseract, an old, well-maintained, free OCR engine originally built by HP, then by Google, and now by a community of open-source maintainers. It has full Devanagari support, runs comfortably on a modest laptop, and has a clean Python wrapper.

There are newer, transformer-based OCR systems — Microsoft’s TrOCR, Meta’s Nougat, Google’s Cloud Vision API, Anthropic’s vision-capable Claude — and for production-grade Nepali OCR in 2026, one of those will usually beat Tesseract. We are using Tesseract because it is free, runs offline, and is genuinely simple to set up. The principles transfer.

Installation, in two parts

Tesseract has two pieces:

The engine itself — a system program, not a Python package.

  • macOS: brew install tesseract
  • Windows: download the installer from github.com/UB-Mannheim/tesseract/wiki. During install, on the language-selection screen, make sure Nepali (Devanagari) is checked. If you miss it, you can re-run the installer later.
  • Linux: sudo apt install tesseract-ocr tesseract-ocr-nep (the -nep package adds Nepali language data).

Verify in a terminal:

tesseract --version
tesseract --list-langs

The second command should show nep (Nepali) and eng (English) among the available languages. If nep is missing, the Nepali data file is not installed — that is the most common error here.

The Python wrapper — in your activated virtual environment:

pip install pytesseract Pillow

pytesseract is the wrapper around Tesseract. Pillow is Python’s standard image-handling library; we use it to load the image file.

The whole program

from PIL import Image
import pytesseract

image_path = "data/signboard.jpg"
img = Image.open(image_path)

text = pytesseract.image_to_string(img, lang="nep")

print(text.strip())

Five real lines. Read them slowly:

  • Image.open(...) loads the image file from disk.
  • pytesseract.image_to_string(...) is the call — it sends the image into Tesseract and returns the recognised text.
  • lang="nep" tells Tesseract to use the Nepali language pack. The default would be English, and it would do badly on Devanagari.
  • text.strip() trims trailing whitespace from the result.

Put a clean photo of a Devanagari sign at data/signboard.jpg and run it. The first time it works, it feels like magic. It is not. It is a model someone else trained, loaded by a library someone else wrote, called by five lines you wrote yourself. That is exactly the shape of the work.

A more useful version

The raw output is fine. A small program that handles common things — file not found, missing language pack — is better:

import sys
from pathlib import Path
from PIL import Image
import pytesseract


def read_devanagari(image_path: str) -> str:
    path = Path(image_path)
    if not path.exists():
        raise FileNotFoundError(f"No image at {image_path}")

    img = Image.open(path)
    text = pytesseract.image_to_string(img, lang="nep")
    return text.strip()


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python ocr.py <path-to-image>")
        sys.exit(1)

    print(read_devanagari(sys.argv[1]))

Save as ocr.py. Run from the terminal:

python ocr.py data/signboard.jpg

You now have a small command-line tool. Give the script to a friend, and they can OCR images from their own terminal — assuming they install Tesseract. Wrap it in a web page in Course 05, and anyone with a browser can do the same.

When OCR fails (and it will)

A short field guide to the most common disappointments:

  • Blurry or skewed photos. Tesseract is fragile to bad input. Crop tightly to the text, hold the camera level, take it in good light. Preprocessing — converting to grayscale, increasing contrast, deskewing — can rescue a lot. The Pillow library can do all of these in three lines each, and we will revisit this in Course 02.
  • Handwriting. Tesseract is built primarily for printed text. Handwriting is much harder. For handwritten Devanagari, you will get usable but messy output — and a transformer-based vision model (e.g. asking Claude with a vision-capable model to read the image directly) often does better.
  • Mixed scripts. A page that mixes Nepali and English confuses Tesseract if you only ask for nep. Pass lang="nep+eng" and it will try both.
  • Wrong language pack. If the output looks like nonsense Devanagari, you might be running Tesseract with lang="eng" on a Nepali image, or with the nep data missing. Re-check with tesseract --list-langs.

A comparison: local versus hosted, side by side

You have now done both ends of the spectrum:

Hosted API (Claude)Local model (Tesseract)
SetupAPI key, one pip installSystem install, language pack, Python wrapper
CostCents per callFree, after install
Speed1-3 seconds (network round trip)Milliseconds, on your hardware
PrivacyData leaves your machineData stays on your machine
QualityState of the artSolid for the era and the task
Internet requiredYesNo

There is no winner. There is a choice you make per problem. A NEPSE summary tool: hosted, because the data is public and you want fluency. A medical-record OCR system: local, because data privacy is non-negotiable.

The mental shape of “AI builder” is the person who fluently picks between these two for each new problem — and who can move data from one to the other when the choice changes.

Check your understanding

Quick check

You run `pytesseract.image_to_string(img, lang='nep')` on a clear photo of Devanagari text but get back English-looking gibberish — Latin letters with no clear words. What is the most likely cause?

Quick check

A clinic in Tikapur asks for help building a system that extracts patient names from photographed prescription notes — almost all handwritten in Devanagari. Which deployment choice from this section best fits their constraints?

What comes next

You have called a hosted model and run a local model. You can hold data, move it, plot it, share it, and debug it. The toolkit is complete. Chapter 6 asks you to do the final, hardest, most underrated thing in this entire track: take one small idea — the problem you wrote down in Chapter 1, Section 1 — and finish it. Build it end to end. Write it up. Share it. The first finished project is more valuable than the next ten unfinished ones.