If your tool accepts user screenshots, sooner or later a tiny one arrives: a thumbnail cropped out of a chat app, text maybe 8 px tall, and the OCR output is mush. The reflex fix is one line before recognition, resize 4x and move on. I wanted to know whether that line belongs on every image or behind a check, because the resize isn't free. The 8 px English test image here went to 1352×712 after a 4x upscale, sixteen times the pixels to push through the recognizer, and through your upload if the OCR runs on someone else's server.
The test set is small and deliberately clean. One self-written English paragraph of 452 characters in Times New Roman, black on white, rendered directly at nine text heights from 6 to 60 px, where text height means the ink bounding box of a capital H. A 275-character Chinese paragraph in a serif (Song) and a sans (Hei) face rides along. Three recognizers: Tesseract 5.5.3 with the English model only, built-in macOS text recognition in accurate mode, and for the third column the image-to-text tool in ImgIng https://imging.ai/ , which runs in a desktop browser and downloads about 31.2 MB of model the first time. Each number is one run on an Apple M4 Mac, with no real photos or JPEG noise, so real screenshots will probably do worse at the same height.
Tesseract went from 21 errors to 0
At native size Tesseract is the engine that needs help. At 8 px it made 21 errors on 452 characters (95.35%), at 10 and 12 px still 3 each, and it only reached zero at 16 px. Upscaling to about 32 px text height cleaned that up: the 8 px image dropped to 0 errors with bilinear and bicubic and to 3 with Lanczos, and 10 and 12 px both dropped to 0 with bilinear. Even the hopeless 6 px case went from 376 errors to 81. If Tesseract is behind your tool, "always upscale small text" looks like a fine rule.
The in-browser model barely moved
The browser engine didn't need the help. At 8 px it made 0 errors, and at 6 px it made 18 (96.02%) where Tesseract made 376. Upscaling the 8 px image with bilinear kept it at 0, while bicubic introduced 4 errors and Lanczos 5. At 6 px bilinear helped a little (18 to 12), bicubic doubled the errors to 37, and Lanczos pushed them to 115. The Chinese 6 px Song paragraph said the same: 79 errors, 73 with bilinear, 133 with Lanczos. For this engine the reflex resize ranges from pointless to harmful.
macOS sits in between. Its English was already at 3 errors at 8 px, and resizing just shuffled that between 1 and 4. On tiny Chinese text it gained a lot, the 6 px Hei paragraph going from 256 errors to 37, yet the 6 px Song paragraph topped out at 53.1% while the same text rendered natively at 12 px scored 99.64%. Interpolation smooths strokes that have already run together; it doesn't separate them. Why Lanczos was the filter most likely to come out worse on all three engines I'm not sure. My guess is the ringing it adds beside sharp edges, but I haven't checked that.
Measure the text height first
So the answer depends on the engine and on the height you actually have, and getting the height is cheap. Binarize with Otsu, take connected components, drop specks under 3 pixels, use the 90th percentile of component heights. On these renders that landed within 1 px of the true Chinese height up to 30 px, and within 3 px of the English cap height all the way to 60. A horizontal projection profile is the other few-line option, but on English it measures the whole line with ascenders and descenders, so the 8 px sample read as 10.
With a height in hand, a reasonable rule is to leave 12 px and above alone, and below that upscale toward about 30 px with bilinear, only for engines you've confirmed benefit. Tesseract passes easily. The browser model in ImgIng doesn't, so for it the sixteen-fold pixel bill buys nothing. A handful of images with known text and a before and after error count is enough to find out which group your engine is in, and it's cheaper than guessing.
Pixel height isn't the only input, either: pasting the 8 px Hei paragraph unscaled into a blank 1200×1200 canvas took macOS recognition from 88.0% to 0%, possibly because it shrinks the whole image internally, which is a guess this test can't confirm. And when a bigger original is available, a fresh screenshot or a higher device pixel ratio, take it: none of the 6 px upscales here reached what the same engine scored on native 12 px text.
What I haven't settled is the per-image call in production, with no ground truth to count against. With 452 characters one error is about 0.2%, so treat these counts as direction, not benchmark. For now: measure, threshold per engine, bilinear, and spot-check known images whenever the engine changes.


