Text capture: photograph the label, then tap the line you want - #8
Merged
Conversation
Reported from a real phone: a receipt in frame, brackets full of text, "No text found". Reproduced it and the cause was not the camera. PSM 7 tells Tesseract "this image is a single text line"; handed five lines it does not return a poor answer, it returns *nothing*. Every benchmark so far had put exactly one line in the band, so the mode that made single lines better was silently failing on everything else. Measured on a three-line crop: single-line mode empty, block mode all three cleanly, and on a genuine single line the two are identical. The band was the wrong shape for the job anyway. Lining one line up inside a guide is hardest exactly when the print is small and the phone is far away — which is when text capture is wanted at all. So: photograph the label, mark every line found, and tap the one you want. Pointing at a line on a picture is a better instruction than aiming a camera at one, and both engines already return the boxes needed to draw it — Tesseract per line, TextDetector per block. Two passes, for two different jobs. The first reads the whole frame in block mode: enough to find the lines and mark them, not enough to trust a product key from. Tapping one crops it and reads it three times at different scales — the close read that used to be spent on a guessed-at band, now spent on the line the user actually asked for. Single-line mode is kept for that second pass, where the claim is true and it is twice as fast as block mode for the same accuracy. The photo is zoomed to the text it found. A landscape frame letterboxed into a portrait viewport uses about a third of the screen and leaves receipt lines a few pixels tall; the margins of the label do not need the space. The picture and the boxes are placed from the same numbers, and re-placed by a ResizeObserver — the first cut positioned them once, before the panel below had finished rendering, and every box sat five lines below its own text. Also adds zoom, where the lens reports it: a phone cannot focus closer than ten or fifteen centimetres, so filling the frame with small print by moving nearer runs out of focus before it runs out of room. Verified in a browser on the case that failed: twelve receipt lines found, each box over its own text and in reading order, tap the eighth, close re-read agrees 3/3, and the receiver gets that line byte-for-byte. Barcode path unchanged, including a text-and-back round trip. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ooGSXdKf1ZKVKSiTycKFs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #7, from testing it on a real phone. One commit.
A receipt in frame, brackets full of text, "No text found".
Why it found nothing
Not the camera. #7 set page segmentation to "single text line", which is better when there is one line. Handed five, Tesseract does not return a poor answer — it returns nothing. Every benchmark in #7 had put exactly one line in the band, so the mode that helped single lines was silently failing on everything else.
Measured on a three-line crop:
The band is gone
The bug is fixable in one line, but the band was the wrong shape for the job regardless. Lining a single line up inside a guide is hardest exactly when the print is small and the phone is far away — which is when text capture is wanted at all.
So: photograph the label, every line found is boxed on the photo, tap the one you want. Pointing at a line on a picture is a better instruction than aiming a camera at one, and both engines already return the geometry — Tesseract per line,
TextDetectorper block.Two passes, two jobs. The first reads the whole frame in block mode: enough to find and mark the lines, not enough to trust a product key from. Tapping one crops it and reads it three times at different scales — the close read that used to be spent on a guessed-at band, now spent on the line the user actually asked for. Single-line mode is kept for the second pass, where the claim is true and it is 2× faster than block mode for identical accuracy.
The accuracy work from #7 is unchanged and still applies: three scales, agreement counts (
3/3,1/3) instead of the engine's own confidence, whitespace-only differences counted as agreement.Layout
The photo is zoomed to the text it found. A landscape frame letterboxed into a portrait viewport uses about a third of the screen and leaves receipt lines a few pixels tall; the label's margins do not need the space.
The picture and the boxes are placed from the same numbers, and re-placed by a
ResizeObserver. Worth calling out, because the first cut looked fine and was wrong: it positioned the boxes once, before the panel below had finished rendering, so all twelve sat five lines beneath their own text. The boxes are the entire promise of this UI — a box drawn anywhere but over its own text is worse than drawing none — so they cannot be allowed to drift.Zoom
Added, where the lens reports the capability. A phone cannot focus closer than ten or fifteen centimetres, so filling the frame with small print by moving nearer runs out of focus before it runs out of room. The control is absent, not disabled, on a lens without it.
Verification
On the case that failed, in a browser:
3/3→ receiver gets that line byte-for-byte, captionedOCR TEXTStill open
TextDetectorpath has still never executed anywhere I can test. On Android it is ML Kit and should be better than these numbers.🤖 Generated with Claude Code
https://claude.ai/code/session_012ooGSXdKf1ZKVKSiTycKFs
Generated by Claude Code