Guidestutorial

Text detection in Python: EasyOCR, PaddleOCR, docTR and MMOCR compared

The same photograph through four toolkits, with the code, the output format, the detector each one runs, and when to pick which.

last verified 2026-09-05 · easyocr · paddleocr 3.x · python-doctr · mmocr 1.x

Four Python libraries cover almost all text detection done outside research code. They differ less in accuracy than in which detector they wrap, what shape their output has, and how much they pull in at install time.

Library Detector inside Detection-only call Output Licence
EasyOCR CRAFT reader.detect() boxes as [x_min, x_max, y_min, y_max] plus free-form polygons Apache-2.0
PaddleOCR PP-OCR (DB-family) TextDetection().predict() quadrilaterals per line Apache-2.0
docTR DBNet (db_resnet50) or LinkNet detection_predictor() relative boxes [xmin, ymin, xmax, ymax, score] Apache-2.0
MMOCR DBNet, DBNet++, PSENet, PANet, FCENet, TextSnake MMOCRInferencer(det=...) polygons Apache-2.0

All four run on CPU; all are faster with a CUDA GPU. Install them in separate virtual environments: PaddleOCR (PaddlePaddle) and MMOCR (PyTorch + MMCV) do not enjoy sharing one.

EasyOCR

pip install easyocr
import easyocr

reader = easyocr.Reader(["en"])           # downloads CRAFT + a recognizer on first run
horizontal, free = reader.detect("photo.jpg", min_size=20, text_threshold=0.7, low_text=0.4)

for x_min, x_max, y_min, y_max in horizontal[0]:
    print("box", x_min, y_min, x_max - x_min, y_max - y_min)
for polygon in free[0]:
    print("polygon", polygon)               # list of [x, y] points for curved text

detect() runs only CRAFT. reader.readtext("photo.jpg") runs detection and recognition and returns (box, text, confidence) triples. EasyOCR is the easiest install; it is also the slowest of the four on CPU because CRAFT’s post-processing is heavy.

PaddleOCR (3.x API)

pip install paddlepaddle paddleocr
from paddleocr import TextDetection

model = TextDetection(model_name="PP-OCRv5_mobile_det")
for result in model.predict("photo.jpg", batch_size=1):
    result.print()                       # dt_polys: one quadrilateral per text line, dt_scores
    result.save_to_img("out/")

PaddleOCR 3.x reorganised its API around pipeline and module classes; older tutorials that call PaddleOCR(...).ocr(img, rec=False) describe the 2.x interface. The mobile detector is the same family of model the detector on this site runs in the browser; the server detector is larger and more accurate. Both are DB-style networks.

docTR

pip install "python-doctr[torch]"
from doctr.io import DocumentFile
from doctr.models import detection_predictor

detector = detection_predictor(arch="db_resnet50", pretrained=True)
pages = DocumentFile.from_images("photo.jpg")
result = detector(pages)

for xmin, ymin, xmax, ymax, score in result[0]["words"]:   # relative coordinates, 0-1
    print(xmin, ymin, xmax, ymax, score)

docTR (Mindee) is the cleanest code base of the four and the best documented. It is document-first: its defaults assume straight text, and assume_straight_pages=False switches on rotated boxes. Choose it when your inputs are scans and forms rather than street scenes.

MMOCR

pip install -U openmim && mim install mmengine "mmcv>=2.0.0" mmdet && pip install mmocr
from mmocr.apis import MMOCRInferencer

inferencer = MMOCRInferencer(det="DBNet")          # or "DBNetpp", "PSENet", "PANet", "FCENet", "TextSnake"
result = inferencer("photo.jpg", return_vis=False)
polygons = result["predictions"][0]["det_polygons"]
scores = result["predictions"][0]["det_scores"]

MMOCR is the research toolbox: many detectors behind one interface, training configs for every benchmark on the datasets page, and the heaviest install. Pick it when you need to compare architectures or train your own.

Choosing

  • Fastest path to boxes and text: EasyOCR.
  • Best accuracy per megabyte, multilingual, CPU-friendly: PaddleOCR.
  • Documents, clean code, production service: docTR.
  • Research, custom training, many detectors: MMOCR.
  • No install at all: the detector on this site, which runs PaddleOCR’s models through ONNX Runtime in the browser and exports JSON in the same box format as the table above.

Making outputs comparable

Every library uses a different coordinate convention. Convert everything to {x, y, width, height} in pixels of the original image before comparing, and remember that EasyOCR’s horizontal list orders values as x_min, x_max, y_min, y_max, not x, y, x, y.