Skip to content

Expose hybrid OCR in the Python API + fix RapidOCR runner crash#44

Open
sh3raawii wants to merge 2 commits into
raphaelmansuy:mainfrom
sh3raawii:feat/python-hybrid-and-rapidocr-fix
Open

Expose hybrid OCR in the Python API + fix RapidOCR runner crash#44
sh3raawii wants to merge 2 commits into
raphaelmansuy:mainfrom
sh3raawii:feat/python-hybrid-and-rapidocr-fix

Conversation

@sh3raawii

Copy link
Copy Markdown

Summary

Two related changes that make hybrid OCR (--hybrid docling-fast) usable from the Python API:

  1. fix: RapidOCR runner crashes on NumPy result fields. The embedded RapidOCR driver read its results with getattr(result, 'boxes', []) or []. Current rapidocr returns NumPy arrays, and ndarray or [] raises ValueError: The truth value of an array with more than one element is ambiguous. The runner subprocess therefore exits non-zero, run_rapidocr_words returns None, and hybrid OCR silently recovers nothing whenever EDGEPARSE_OCR_ENGINE=rapidocr is selected. Fixed by normalizing each field explicitly (None[], otherwise list(...)).

  2. feat(python): expose hybrid / hybrid_mode in convert() and convert_file(). The CLI supports --hybrid docling-fast, but the Python bindings built a ProcessingConfig that always left hybrid = Off, so the OCR-recovery path was unreachable from Python. This adds the two keyword arguments (mapping identically to the CLI) to both the pyo3 binding and the edgeparse Python wrapper.

Motivation

import edgeparse had no way to turn on hybrid OCR — the only door to it was the CLI. And even via the CLI, the higher-accuracy RapidOCR engine was broken by the crash above. Together these meant hybrid OCR was effectively unavailable to Python users. After this change:

import edgeparse

# born-digital: unchanged
md = edgeparse.convert("report.pdf", format="markdown")

# image-based / scanned tables and prose, now reachable from Python
md = edgeparse.convert("scanned.pdf", format="markdown",
                       hybrid="docling-fast", hybrid_mode="full")

hybrid accepts "off" (default) or "docling-fast"; hybrid_mode accepts "auto" (default) or "full". Defaults are unchanged, so this is backward compatible.

As with the CLI, docling-fast shells out to pdftoppm and tesseract (and rapidocr when EDGEPARSE_OCR_ENGINE=rapidocr and it is importable), so those need to be present on the host for OCR recovery to run.

Testing

Built the wheel with maturin and verified against an image-only PDF (dense prose rendered as a picture, no text layer) with poppler-utils, tesseract-ocr, and rapidocr installed:

  • edgeparse.convert(pdf, hybrid="off") → 0 words (born-digital parser sees no text layer)
  • edgeparse.convert(pdf, hybrid="docling-fast", hybrid_mode="full") → full text recovered via RapidOCR

Born-digital PDFs are unaffected.

Changes

  • crates/edgeparse-core/src/pdf/raster_table_ocr.rs — NumPy-safe result parsing in the RapidOCR runner.
  • crates/edgeparse-python/src/lib.rshybrid / hybrid_mode args on convert() / convert_file().
  • sdks/python/edgeparse/__init__.py — same args on the Python wrapper, with docs.
  • sdks/python/edgeparse/_types.pyHYBRID_BACKENDS / HYBRID_MODES constants.

The embedded RapidOCR driver read its results with
`getattr(result, 'boxes', []) or []`. Current rapidocr returns NumPy
arrays, and `ndarray or []` raises "The truth value of an array with
more than one element is ambiguous". The runner subprocess then exits
non-zero, run_rapidocr_words returns None, and hybrid OCR silently
recovers nothing whenever the RapidOCR engine is selected.

Normalize each field explicitly (None -> [], otherwise list(...)).
The CLI supports --hybrid docling-fast, but the Python bindings built a
ProcessingConfig that always left hybrid = Off, so the OCR-recovery path
was unreachable from Python.

Add `hybrid` ("off" | "docling-fast") and `hybrid_mode` ("auto" |
"full") keyword arguments to convert() and convert_file() in the pyo3
binding and the edgeparse Python wrapper, mapping identically to the CLI.
Defaults are unchanged, so this is backward compatible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant