Skip to content
Lab 02Experiment

Read This

Hold a book, a label, or a business card up to the camera. The page recognises the text on it and reads it aloud, with no server involved at any point.

Hold a book, a label, a business card, or anything else printed up to the camera, press capture, and the page reads the text off it out loud. Nothing is recorded and nothing is sent.

Where this falls over

No accuracy number is published for this lab yet, because none has been measured. What follows is the list of things that broke it while it was being built, which is the honest version of the same information.

  • Curved pages

    A held paperback bows away from the camera near the spine. Letters stretch and the recogniser reads that column worst. Flattening the page, or shooting one column at a time, fixes most of it.

  • Glare and gloss

    A laminated cover or a phone screen throws a highlight that wipes out whole words. There is no dewarping or glare removal here, so the blown out region simply comes back empty or wrong.

  • Low light and hand shake

    A dim room makes the camera drop its shutter speed, and a hand held item then blurs. The still is captured on your press, so it inherits whatever blur the frame had.

  • Handwriting

    It will not read it. The model is trained on printed type, so handwriting comes back as confident nonsense rather than as an error, which is the worst failure shape it has.

  • Small or stylised type

    Ingredients lists, footnotes, script fonts, and logo lettering all fall over. The recogniser wants roughly thirty pixels of letter height, so filling the frame with less text beats fitting the whole item in.

  • Anything but Latin script

    Only the English model is loaded. Cyrillic, Greek, Arabic, and CJK are not just inaccurate, they are outside what this engine was given.

  • Columns and receipts

    Segmentation is automatic, so a two column page or a wide receipt is sometimes read straight across the gutter and the sentences interleave.

Everything above happens inside your browser. The recogniser is WebAssembly running on this page and the voice is your own operating system’s. No frame, no recognised word, and no audio is uploaded, recorded, or written to this device. There is no account, no storage, and no server that could receive any of it. A photograph of a document is more revealing than a photograph of a face, so the still and the text live in memory only: capturing again, stopping the camera, leaving this page, or closing the tab destroys them.

Hypothesis

A camera pointed at printed text is one of the few problems where the on device answer is genuinely better than the cloud one, not merely cheaper. Sending a photograph of whatever someone is holding to a server is the part people are right to hesitate over, and it is also the part that is unnecessary. The claim being tested is that a WebAssembly recogniser and the voice already built into the operating system are enough to make it useful, and that publishing where it fails is more convincing than publishing an accuracy figure.

How it works

  1. 01

    Running now: the camera preview asks for the rear lens where there is one, because holding an item up to a phone is the natural way to use this and the front camera is the wrong one for it. The preview is deliberately not mirrored, unlike Lab 01, since a flipped image is right for a face and useless for a page.

  2. 02

    Running now: a still frame is captured on a button press rather than running recognition on live video. A still is one sharp frame instead of thirty motion blurred ones, it costs a single pass instead of thirty a second, and it puts the visitor in charge of when the item is framed properly.

  3. 03

    Running now: the frame is converted to luminance and, on a low resolution camera, drawn at twice the size. The recogniser wants roughly thirty pixels of letter height and a 480p webcam pointed at a paperback does not deliver that. Neither step invents detail, and neither is claimed to improve accuracy, because that has not been measured.

  4. 04

    Running now: Tesseract runs as WebAssembly in a worker thread, so the page stays responsive while it reads. The runtime is imported inside the button handler, so a visitor who never starts the camera never downloads a byte of it.

  5. 05

    Running now: every word comes back with the engine's own confidence score, and the output is drawn on a continuous brightness ramp instead of being sorted into invented bands. The one threshold on the page, a dotted underline below 70, is labelled as a display choice rather than a measured cutoff.

  6. 06

    Running now: the text is spoken by the browser's built in speech synthesis, which is free, offline, and already tuned to the visitor's own device. It is also an inconsistent API, so the text is split into short utterances to work around the Chrome bug that silently truncates long ones, and the voice list is resolved ahead of the button press because iOS only permits speech to start inside a user gesture.

  7. 07

    Running now: the failure modes are printed on the page next to the demo. Curved pages, glare, low light, handwriting, small or stylised type, non-Latin scripts, and columns read across the gutter. Handwriting is the worst of them, because it fails confidently rather than reporting that it could not read anything.

  8. 08

    Next: measure a character error rate against a fixed set of printed items and publish it, including the split between clean flat pages and held curved ones.

  9. 09

    Next: decide whether page dewarping is worth its cost, which is the single change most likely to move the number on the case this lab was built for.

Measured so far

Character error rate
Not measured

no accuracy number is published here, because none has been measured. A fixed set of items photographed under repeatable conditions, scored against typed ground truth, is the next piece of work. Quoting a figure from the Tesseract documentation would be quoting someone else's scanner

Kept, stored, or sent
Nothing

no upload, no account, no server, and no browser storage of any kind. The recogniser's own default is to cache its language model in IndexedDB and that default is switched off, because a page holding an image of a document is a worse thing to leave behind than one holding a face

Runtime, on first press
About 7MB

3.9MB WebAssembly core, 2.9MB compressed English language data, 111KB of worker script. None of it is in the page bundle. It downloads once the camera is already live and never on a visitor who does not start one

Confidence shown
Per word

every word carries the recogniser's own score and is drawn on a continuous brightness ramp, so a word it was unsure of looks unsure. Confidence is not accuracy, and the two come apart most on handwriting, where it is confidently wrong

What's next

  • Measure a character error rate on a fixed item set and publish it rather than describing failures qualitatively
  • Score the confidence signal itself, since a score that does not predict correctness is worse than no score
  • Try dewarping a curved page, which is the failure that costs the most on the exact use case this was built for
  • Test whether a glare heuristic can warn before capture instead of after
  • Measure how much the luminance conversion and the upscale are actually worth, rather than assuming they help
  • Look at whether a second language model is worth the extra megabytes, and for whom