A four-pixel-tall character is not a small character; it is an unresolved one. When OCR rejects tiny text, half-fills grey legends on dark panels, or reads the same letter differently in each ROI, the cause is almost always one number: how many pixels tall each glyph lands on the sensor. You will get the floor to design against, a worked example that sizes the camera from it, and the fixes in order: optical enlargement for size, one locked manual threshold for contrast, tight ROIs and uniform light for stable segmentation.
The number that decides: pixels per character
OCR classifies shapes, and shapes need enough sampled strokes to stay distinguishable. The working floor is 20 pixels of character height, measured on the image the engine actually sees; 30-40 pixels is the design target that survives focus drift, part wobble and lighting change. Under the floor, the crossbar of a G fills in until it reads as an O, an 8 closes toward a B, and no tuning recovers the difference, because the sensor never captured it. Tiny fiducial markers fail for the identical reason.
Two numbers set pixels per character: the sensor's row count and the field of view.
Both relationships are linear: doubling the sensor rows doubles the count, and halving the field of view does the same. A font size of 4 set in an editor or on a screen says nothing about the camera; the only number that matters is glyph height in pixels in the saved image. The same pixel rule sizes cameras for defect work — see camera resolution for defect detection.
Worked example: sizing a camera for 2 mm characters in a 60 mm field
The case: the drawing calls out 2 mm tall laser-etched characters, and the fixture window forces a 60 mm tall field of view. Choose the sensor.
Rule in words: take the character's share of the field height, multiply by the sensor's row count, and compare with the 20-pixel floor.
Arithmetic:
- Character share of the field: 2 / 60 = 0.033.
- Rows for the 20-pixel floor: 20 / 0.033 = 600.
- Rows for 30 pixels of margin: 30 / 0.033 = 900.
- A 480-row VGA sensor: 2 / 60 × 480 = 16 pixels per character. Below the floor.
- A 1024-row 1.3 MP-class sensor: 2 / 60 × 1024 = 34 pixels. Passes with margin.
- A 2048-row 5 MP-class sensor: 2 / 60 × 2048 = 68 pixels. Margin holds across two text lines.
Decision: with the field fixed at 60 mm, buy at least 600 sensor rows and prefer 900 or more; the 1.3 MP class is the practical entry point and 5 MP buys headroom. If you can shrink the field to 30 mm instead, even a 480-row sensor reaches 2 / 30 × 480 = 32 pixels and passes. Geometry you cannot change is what forces the sensor upgrade.
This reader pairs 5 MP resolution with 2048 sensor rows and an 8 mm lens:
- Interface
- Fast Ethernet
- Resolution
- 5 MP
- Sensor format
- 1/1.7"
- Shutter
- Global
Run the example on those rows: 2048 × 2 / 60 = 68 pixels per character, double the comfortable target.
Symptoms, most likely causes and the test for each
| Symptom | Most likely cause | Test | Fix |
|---|---|---|---|
| Every glyph rejected | Height under the 20-pixel floor | Measure one bounding box in the saved image | Shorter field or more sensor rows |
| Grey text on a dark panel half-fills | Threshold sitting above the stroke grey level | Sample stroke and background grey values | Manual threshold at the midpoint |
| Same letter reads differently per ROI | Pixels per character or the threshold changed with the ROI | Overlay segmentation boxes in both ROIs | Constant pixels per character, one locked threshold |
| Letter pairs merge into one box | Characters touching after thresholding | Inspect the binary image, not the original | Threshold, lighting, then glyph splitting |
| Special characters cannot be trained at all | Glyphs under about 2 pixels: no shape was captured | Zoom the stored image and look | Optical enlargement before any training |
Work top to bottom: a size problem survives every contrast and segmentation fix you throw at it.
Four pixels high: the read no setting can save
At 4 pixels of character height, a stroke is roughly half a pixel wide after thresholding. The engine receives blobs, not glyphs, and every decode becomes a guess. Two software moves look tempting, and both fail:
- Resizing the image 5× averages neighboring pixels into new ones; the enlarged G is a smoother blob with no new edge information, and the misreads stay.
- Lowering the OCR tool's minimum character-size setting accepts the blobs and turns no read into a confident wrong read, which is worse on a production line.
Getting from 4 pixels to 20 is a 5× gain, and it comes from optics:
- Shrink the field of view 5× with a shorter working distance or a longer focal length. Magnification is sensor width divided by field width, and focal length ≈ working distance × magnification; run your own numbers in the lens focal length calculator.
- Or multiply the sensor rows by 5: a 480-row VGA sensor cannot get there, while 2400 rows in the 5-10 MP class can.
Re-measure after the change, because focus error and part wobble eat margin. If the field shrinks far enough, a compact reader pairing a 1.3 MP sensor with a 12 mm lens covers a small window:
- Interface
- Fast Ethernet
- Resolution
- Up to 3 MP
- Shutter
- Global
- Lens mount
- M12
Check the result the same way every time: one glyph, one bounding box, pixel height from the image statistics.
Grey text on a dark panel: one threshold, not a second font
Grey characters on a near-black background fail for a contrast reason, not a training reason. Work the numbers: sampling the image shows the background parked at grey level 40 and the strokes at 110, on the 0-255 scale. A default threshold of 128 pushes both to the same side, and the text vanishes. Set the manual threshold midway — (40 + 110) / 2 = 75 — and the glyphs cut cleanly.
The typeface has not changed, so train it once. Light-on-dark versus dark-on-light is binary polarity: invert it, or set the engine's polarity option, and reuse the same font set. A second training of the same font doubles your maintenance and buys nothing.
If the panel is glossy, lift the grey-level separation with light before touching the threshold. Glare saturates pixels toward white and shadows crush them toward black, and both shrink the gap the midpoint depends on. If the two measured levels drift toward each other across a shift, fix the light first: a locked threshold only works while the gap holds. A polarizer suppresses reflected glare on curved or coated panels, and this reader builds it in:
- Interface
- Fast Ethernet
- Resolution
- Up to 3 MP
- Shutter
- Global
- Lens mount
- M5.8
Measure the two grey levels with the production light running, not with the bench lamp.
The same letter, different boxes: scale and segmentation drift
One glyph reads in a tight ROI and fails in a wider one. Three things change when the region grows, and each can flip a G to an O or fuse a letter pair into one box:
- Pixels per character changes. Templates trained at one glyph height mismatch the new scale, and at the smaller height the G's bar fills in until it reads as an O. Hold the pixels-per-character value constant across ROIs: same working distance, same lens, no rescaling between training and runtime.
- The histogram changes. A wider region pulls background into the statistics, an automatic threshold hunts, and the same glyph segments differently frame to frame. Lock one manual threshold from measured grey levels and keep the region tight to the text line — the guide to setting an ROI for inline code reading shows how much stability a tight region buys.
- Segmentation splits differently. When two characters touch after thresholding, the engine sees one component; a merged letter pair next to separate letters is the classic sign. That is the touching-glyph problem — the segmentation fix for touching OCR letters and the method for separating touching digits before OCR walk through the threshold, lighting and splitting fixes in order.
Test the fix: overlay the segmentation rectangles on the same text in both ROIs and compare glyph bounding-box heights; they should agree within a pixel or two. If the line genuinely mixes two character heights, read it as two ROIs with one font set each, or normalize the scale before classification.
Why retraining is the wrong lever for a size problem
Training answers which shape this is, not whether enough shape exists to see. A font trained on 4-pixel glyphs memorizes thresholding noise, then fails at runtime the moment lighting moves — the same incomplete set-up behind OCR jobs that train but fail at runtime. Special characters under about 2 pixels have nothing to learn: their strokes were never resolved, so the training samples are rectangles.
Retraining is the right lever only when the shapes themselves differ: a curved surface, an unusual typeface, a stylized digit set. For curved inner-cap text, see training a custom OCR font for curved inner-cap text; for typefaces whose O, 0 and D stay distinct when small, see OCR font selection. That choice is free margin: at equal pixel height, a clean grotesque with open counters beats a thin serif.
One shortcut to check first: if the characters live on an HMI or controller rather than on a part, read them over the connection instead of photographing the screen. Screen fonts are sized for the operator's eye, and the minimum font size for HMI readability was chosen for a human, not for your pixel budget.
Choosing the fix: geometry first, sensor second, software never
| Case | Pull this lever | Effect |
|---|---|---|
| Field of view movable | Shrink it until characters sit at 30+ pixels | Linear gain, no new camera |
| Field locked by a fixture window | More sensor rows, from the formula | Gain linear with rows |
| Size fine, contrast poor | Measured manual threshold, better light | No hardware at all |
| Glossy or curved panel | Diffuse light geometry plus polarization | Lifts grey-level separation |
| Two character heights in one image | Two ROIs, one font set each | Clean templates at each scale |
Software resolution changes are absent on purpose: interpolation adds no edges.
If the field is locked, shop by row count. The camera finder filters code readers and smart cameras by resolution, and mono smart cameras run OCR onboard without a PC; this 6 MP model with an 8 mm lens is one such onboard option:
- Interface
- GigE
- Resolution
- 6-10 MP
- Sensor format
- 1/2.4"
- Shutter
- Rolling
A mono sensor reads text with more usable contrast than color at the same resolution, because no Bayer filtering spreads each pixel's value across its neighbors.
Checks before you order parts
- Shoot a sample at the real working distance and lens, then measure one glyph's bounding box in the saved image. Count pixels, not font points.
- Run the rows formula with your field and character height: 20 pixels required, 30 preferred.
- Sample stroke and background grey levels under production lighting, and confirm the gap survives a full shift before locking the threshold.
- Check stroke width after thresholding: 2 pixels across minimum, or segmentation will alternate between merging and dropping strokes.
- List every character the strings can contain, specials included, and confirm the font set covers them all.
- Prefer mono sensors for text; add a polarizer when the marking sits on a glossy or curved surface.
Prevention checklist
- Fix the working distance and field of view, and record the pixels-per-character value for the job.
- Lock focus, then lock a manual threshold from measured grey levels; no auto-exposure hunting across parts.
- Keep each ROI tight to its text line; do not widen it to hand the engine context.
- Light the whole ROI uniformly, and strobe when the part moves.
- Log glyph pixel height with every read and alarm when it drifts below 20.
- Re-run the rows formula whenever the field, the lens or the camera changes.
Measure tonight what you have been guessing at: the worst glyph's pixel height, its two grey levels, its segmentation boxes. Under 20 pixels, change the optics before anything else; a healthy grey-level gap, and one locked threshold may be the whole fix. When you need the row count the formula asked for, filter the fixed code readers by resolution, start from the camera configurator, or contact us with the part and the numbers. The rest of the code-reading guides cover the runtime side: ROI sizing, touching glyphs, fonts.
Questions
What is the minimum character height for OCR in pixels?
Plan on 20 pixels as the working floor and 30-40 pixels as the design target for each glyph, measured on the image the engine sees after focusing. Below roughly 20 pixels, strokes merge and lookalikes such as G and O become indistinguishable. Pixels per character scale with sensor rows and shrink as the field of view grows, so both numbers move the result.
Do grey characters on a dark background need a separately trained font?
No. If the typeface is the same, train it once. A grey background only moves the grey levels, so set the manual threshold midway between the measured background and stroke values, and invert the binary polarity if the engine expects dark text on a light field. Retrain only when the typeface, stroke weight or surface finish genuinely differs.
Does upsampling the image help OCR read 4-pixel characters?
No. Interpolation creates new pixels by averaging old ones, so a larger blurred glyph carries no extra edge information and the same misreads remain. The pixels have to exist at the sensor: shorten the working distance, fit a longer focal length, or move to a sensor with more rows until character height crosses 20 pixels.
Why does one letter read correctly in one ROI and wrongly in another?
Because the character's pixel height and its segmentation change with the ROI. A wider region pulls background into the histogram and shifts the threshold, and scaled templates no longer match the glyph size. Overlay the segmentation boxes in both ROIs, compare bounding-box heights, then hold the pixels-per-character value constant and keep the region tight to the text line.
What lighting makes grey text on shiny plastic or metal readable?
Any light that separates the stroke grey level from the background grey level. A diffuse or dome geometry softens reflections, and a polarizer on the light or lens suppresses the glare that saturates pixels toward white. Measure both grey levels with the production light running, then place the binary threshold at their midpoint.



