fix(ocr): assemble same-row detections into one line #116

Merged
TimCane merged 2 commits from fix/ocr-line-assembly into main 2026-07-07 16:56:39 +01:00
TimCane commented 2026-07-07 16:50:15 +01:00 (Migrated from github.com)

Summary

  • Live receipts parsed to zero items: PaddleOCR detects a row's name, quantity and right-aligned price as separate boxes, and the sidecar returned them 1:1 (recognizer._response_from_raw), so every price reached the parser nameless and every name reached it amount-less.
  • The parser and its whole fixture corpus assume the sidecar returns assembled reading lines (the shape docs/06 documents); it never did.
  • Fold detections that share a horizontal band into one line - ordered left-to-right by x, text joined, boxes unioned, confidence taken from the weakest fragment.
  • Update the docs/06 /ocr contract to spell out the assembly.

Test plan

  • New unit tests in ocr/tests/test_recognizer.py: columns on one row assemble into a single line (box union, weakest-fragment confidence); vertically separated rows stay apart.
  • Verified end-to-end against the real sidecar: ran hotel-bar-balance/receipt.jpg through live OCR, assembled the raw fragments with the new algorithm, and fed the result to the actual ReceiptParser - yields the 4 items + tax 476 + total 6076 (whole corpus green, 54/54).
  • ruff check clean.
## Summary - Live receipts parsed to zero items: PaddleOCR detects a row's name, quantity and right-aligned price as separate boxes, and the sidecar returned them 1:1 (`recognizer._response_from_raw`), so every price reached the parser nameless and every name reached it amount-less. - The parser and its whole fixture corpus assume the sidecar returns assembled reading lines (the shape `docs/06` documents); it never did. - Fold detections that share a horizontal band into one line - ordered left-to-right by `x`, text joined, boxes unioned, confidence taken from the weakest fragment. - Update the `docs/06` `/ocr` contract to spell out the assembly. ## Test plan - New unit tests in `ocr/tests/test_recognizer.py`: columns on one row assemble into a single line (box union, weakest-fragment confidence); vertically separated rows stay apart. - Verified end-to-end against the real sidecar: ran `hotel-bar-balance/receipt.jpg` through live OCR, assembled the raw fragments with the new algorithm, and fed the result to the actual `ReceiptParser` - yields the 4 items + tax 476 + total 6076 (whole corpus green, 54/54). - `ruff check` clean.
Sign in to join this conversation.
No description provided.