Characters molded into the inner face of a bottle cap are the hardest text on a packaging line: embossed rather than printed, stylized rather than standard, curved around a ring, and lit by a glossy surface that mirrors the light straight back. A shipped OCR font, built from printed glyphs, misreads most of the ring. The recipe that works is short: light the embossing so the strokes separate from the cap floor, unwrap the ring into a straight strip, and train a custom OCR font on your own molded characters. This guide gives you the imaging math, the lighting choice, the sample count, the training steps and the release gate, plus a reader shortlist to match.
Why the shipped OCR font fails on molded cap text
An OCR font is a model of what a glyph looks like, and the fonts your vision library ships were built from printed characters: uniform stroke width, sharp corners, flat ink on a flat surface. Molded cap text breaks every one of those assumptions.
The characters are raised plastic with draft angles, so the pixel pattern of one glyph shifts with light angle, molding depth and cavity wear. The typeface is usually a custom logotype that matches no standard font. And the cap floor is a concave mirror that erases half the strokes when the light sits wrong.
The classic first attempt: seven or eight characters, most of them wrong, with confusable pairs swapped — 0 for O, 1 for I, 8 for B, C for G. Re-tuning thresholds does not fix it, because the font itself is the wrong model.
Molded text from a single cavity tool is stable and repetitive, which is exactly the case a trained font handles well. Building one is hours of work, not weeks.
Decide first: train a font or template-match the ring
Before training anything, check whether you need to read the text at all.
If the ring only ever shows one or a few known patterns — a logo ring, a fixed mold identifier — match the whole unwrapped strip as a template. There is no font to build and no per-character score to tune; the OCR versus template matching comparison shows where that line sits.
Train a font when the characters carry data someone needs as text: date and lot codes, cavity numbers, strings your MES stores. Some platforms also ship pretrained deep-learning OCR that reads stylized text with no training at all — try it if you have it. For a fixed character set on dedicated optics, a font trained on your own parts stays lighter to run, faster to execute and fully under your control.
Decision rule: one or two fixed patterns, template match. Variable content or a required string, custom font.
Light the embossing on a glossy inner face
The inner face is a concave, polished mirror. Light aimed straight down returns as a bright ring that washes out the relief; light too steep leaves the strokes in shadow. Two geometries fix this, and both cost little to try on real caps.
A dome light surrounds the cap with diffuse light from every direction, so the mirror floor stops producing a hot spot. It is the standard first trial for small shiny and curved parts; reading QR codes on reflective and curved surfaces applies the same logic to curved labels.
The second geometry is darkfield: set a ring or bar light at a low angle so the floor stays dark and the raised strokes catch light as bright edges. The characters then read bright on a near-black cap, which is exactly the contrast thresholding wants.
A coaxial light through a beamsplitter is the third candidate, but it pays off on flat surfaces; a ring seated close to the cap wall rarely qualifies.
Whichever geometry wins, kill the leftover specular with polarization — a polarizer on the light and a crossed analyzer on the lens — set up and tested the way the polarized lighting guide describes for screens. For bar lights, a diffuser plate turns a hard reflection into a soft field: the lighting accessories range includes the 170 x 30 mm LS-LAC-0010 diffuser plate for standard bar lights, and the accessories finder filters the rest.
- Size
- 100-200 mm
Only the right-hand arc carries characters you need, so light that arc and mask the rest. Fewer glare sources, fewer cells, smaller training set. Compare candidates on real caps with a fixed reference target, as the reference-target method describes, so the choice does not ride on one lucky sample.
Unwrap the ring and segment the characters
OCR engines want straight, upright text of constant height. Characters on a circle are none of those, and the cap arrives at any rotation. A polar unwrap fixes all three at once: sample the image along circles centered on the cap and lay the angle on the horizontal axis.
After the unwrap, the ring is a horizontal band, every glyph stands upright at the same height, and cap rotation becomes a horizontal shift that a fixed search window absorbs. Segmentation reduces to thresholding the strip and counting blobs in a fixed number of cells.
Threshold on the strip, not the raw image: floor brightness drifts across the band, so a local method beats a global cut. The adaptive thresholding guide covers uneven backgrounds, and OCR thresholding with a dark background covers exactly the dark-floor case.
Then enforce the count. If the arc holds seven characters, expect seven blobs; two or nine means a bad unwrap or glare, and the image should be rejected before recognition rather than scored anyway.
Worked example: pixels, scale and exposure for a 28 mm closure ring
The inputs below are typical for a 28 mm screw closure. Measure your own cap; the arithmetic does not change.
- Character ring: about 20 mm across, on the inner top face (typical closure geometry).
- Character height: 2 mm molded, so the narrowest stroke is about 0.4 mm — roughly a fifth of the height.
- Sampling rule: 4 pixels across the narrowest stroke, enough to train and normalize a glyph cleanly.
- Nesting margin: 6 mm of cap-to-cap play added around the ring.
- Belt speed for the exposure check: 0.5 m/s, a common conveyor figure.
The field of view is ring plus margin: 20 mm + 6 mm = 26 mm.
The image scale follows from the sampling rule: 0.4 mm / 4 px = 0.1 mm/px. The pixel count follows from field and scale: 26 mm / 0.1 mm/px = 260 pixels across the field. The exposure follows from blur and speed: allow half a stroke of blur, 0.2 mm, so 0.2 mm / 500 mm/s = 0.0004 s = 0.4 ms.
260 pixels is the bare minimum, and real sensors leave it far behind. A 1.3 MP sensor, about 1280 pixels across, images the 26 mm field at 26 mm / 1280 px = 0.02 mm/px, so each 0.4 mm stroke lands about 20 pixels wide — five times the sampling minimum — and the 2 mm characters stand roughly 100 pixels tall. Pixel count is not your problem; contrast and font mismatch are.
The exposure result says the light must strobe: 0.4 ms is the ceiling, and a 0.2 ms flash passes with a 2x margin while freezing vibration. Size the flash energy against the light's duty limits with the strobe duty cycle guide.
Decision: any reader at 1.2 MP or more resolves this ring with margin, at any distance that frames 26 mm. Spend the effort on polarization and light angle, not resolution. Step up in pixels only to cover two caps per image or a much larger field.
Choose the reader
A fixed code reader is the default here: lens, light and decoder logic in one housing, configured over Ethernet, no frame grabber. With the pixel budget settled, choose on standoff, glare control and interface.
Four readers that fit this job:
| Specification | MV-IDB005EXI-05NRP | MV-ID3013PM-12M-WBN | LS-CRD-0047 | LS-CRD-0028 |
|---|---|---|---|---|
| Symbologies | 1D codes: Code 39, Code 93, Code 128, EAN8, EAN13, ITF 14, ITF 25, CodaBar, UPCA, UPCE; 2D codes: QR Code, Data Matrix, MicroQR, AZTEC, HanXin; Stacked codes: PDF417 | 1D codes: Code 39, Code 93, Code 128, CodaBar, EAN 8, EAN 13, UPCA, UPCE, ITF 14, ITF 25, Matrix 25, MSI, China Post, Code 11, and Industrial 25; 2D matrix codes: QR Code (GS1-QR included), Data Matrix (GS1-DM included), MicroQR, AZTEC, HanXin, Maxi code; Stacked codes: PDF417, MicroPDF417 | – | 1D: Code 39, Code 93, Code 128, CodaBar, EAN8, EAN13, UPCA, UPCE, ITF14, Matrix 2 of 5, Matrix 25, MSI, China Post, Code 11, Industrial 25; 2D: QR Code, Data Matrix; Stack codes: PDF417 |
| Max. frame rate | 50 fps | 60 fps | – | 30 fps |
| Max. reading speed | 30 codes/sec | 84 codes/sec | – | – |
| Sensor type | CMOS, global shutter, mono, 1/4", 2.7 μm × 2.7 μm | Global shutter, mono, 1/2.7", 4 μm × 4 μm | – | CMOS |
| Resolution | 1024 × 1280 | 1280 × 1024 | 1280 x 960 | 2560× 2048 px |
| Exposure time | 60 μs ~ 6000 μs | 35 μs to 1 sec | – | 35 μs ~ 1 s |
| Gain | 1 ~ 28 dB | 0 dB to 28 dB | – | – |
| Data interface | Fast Ethernet (100 Mbit/s), RS-232, DC terminal | Fast Ethernet (100 Mbit/s) | – | Fast Ethernet (100 Mbit/s) |
| Communication protocol | SmartSDK, TCP Client, Serial, FTP, TCP Server, UDP, Profinet, Ethernet/IP | SmartSDK, TCP Client, TCP Server, Serial, FTP, Profinet, Ethernet/IP, MELSEC/SLMP, ModBus, UDP, Fins, Modbus RTU | – | – |
| Digital I/O | DB15 connector for power and I/O, Incl. 2 opto-isolated inputs (pin 0/1 input), 2 opto-isolated outputs (pin 3/4 output), 1× RS-232, Trigger via side button supported, Device reboot | 17-pin M12 connector provides power and I/O, including non-isolated input (LineIn 0/1/2) × 3, non-isolated output (LineOut 3/4/5) × 3, RS-232 × 1. Supports device triggering via pressing button on top.;17-pin M12 connector provides power and I/O, including isolated input (LineIn 0/1/2) × 3, isolated output (LineOut 3/4/5) × 3, RS-232 × 1. Supports device triggering via pressing button on top. | – | 3 non-isolated inputs, 3 non-isolated outputs, 1 RS-232 |
| Power supply | 12 ~ 24 VDC | 24 VDC | – | 24 V |
| Power consumption | Avg. power 2.5 W @ 12 to 24 VDC, Max. power 5 W @ 12 to 24 VDC | Avg.: 9 W @ 24 VDC (light source enabled); Max.: 48 W @ 24 VDC (light source enabled) | – | 20 W @ 24 V |
| Price | $719.00 · quoted | $1,979.00 | $559.00 | $920.00 |
Values as printed in each product's data sheet; open a part for its drawing and full specifications.
The MV-IDB005EXI-05NRP is the pick for a cap floor that mirrors hard: it is polarized and focuses at 70 mm, with a 4.63 mm lens that frames a tight field over the nest. The MV-ID3013PM-12M-WBN carries a 12 mm focal length, so it reads from farther back and leaves room for the light above the cap. The LS-CRD-0047 reads at a 60-120 mm distance over USB 2.0 and makes a tidy bench rig for collecting training samples. When two caps must fit in one image, the LS-CRD-0028 resolves 2560 x 2048 and reads up to 60 codes/s with its 8 mm lens.
If the station must also run presence, orientation or reject logic without a PC, put the whole job on a smart camera. The LS-SMC-0063 integrates a 1.6 MP sensor, a 16 mm lens and polarized white light at up to 60 fps, so the anti-glare optics ship inside the housing.
- Interface
- GigE
- Resolution
- Up to 3 MP
Filter by pixels, interface and mount in the camera finder when your ring dimensions fall outside the example.
Train the font in seven steps
-
Lock the imaging first. Fix focus, exposure and gain — no auto modes — and strobe the light. The font learns the pixel patterns you give it; if the exposure drifts later, it is reading a different world.
-
Collect samples across the real variance. Shoot 20-30 good images per character from at least three lots or cavities, at every rotation the nest allows, and include the worst lighting you will permit in production. Thirty images from one perfect cap build a fragile font.
-
Unwrap and segment every sample the same way. Use the same center, threshold and cell count as production, and reject any image whose blob count is wrong. Never label a mis-segmented fragment.
-
Normalize the glyphs. Scale every glyph to one fixed height — 32 pixels is a common choice — and train in the polarity you will run. If production shows bright characters on a dark floor, the training set must too; light-on-dark training note shows what breaks when polarity flips between training and runtime.
-
Train one class per character. Feed the masked arc nowhere. Give the confusable pairs — 0/O, 1/I, 8/B, C/G — extra samples, because that is where the score dies.
-
Save the font where the runtime loads it. Export the trained font to the file your runtime reads at startup, so a power cycle cannot silently fall back to the shipped font; persistent runtime configuration note covers the settings that survive a restart. If the runtime refuses the file with a format error, unrecognized-font-file fix lists the usual causes.
-
Score on a hold-out set. Run fifty or more full images the trainer never saw, end to end, and read two numbers: per-character accuracy and whole-string matches. Add 10 samples to any class under 99 percent and retrain — the score should move within one iteration.
Validate, deploy and gate the release
Set the release gate before touching the line: 99.5 percent per-character accuracy and 98 percent whole-string matches on a 200-image hold-out. A font that clears that on the bench leaves the remaining risk in lighting and handling, not in the model.
At runtime, keep every imaging parameter identical to training: same strobe duration, same gain, same polarity, same unwrap center. Log the per-character score with every read and treat a low score the way you would judge whether a decode is trustworthy: accept, re-read once, then divert.
Route the failures deliberately — a second trigger on a low score, a reject chute on a second miss, and a record of every string with its score so traceability survives. The traceability validation guide shows how to connect reads, rejects and the batch record.
Then measure one full shift. If the string rate holds above 98 percent in production, the font is done. If it slips, look at the light first: a drifting LED or a bumped bracket changes glyphs faster than any training error.
Checklist before you train
- Measure the ring — diameter, character height, narrowest stroke — every other number follows from these.
- Fix the arc — mask the half you do not read; fewer classes mean fewer misreads.
- Choose and lock the light — dome or low-angle darkfield, polarization if hot spots remain, no auto exposure or gain.
- Seat the cap — a mechanical nest pins the unwrap center.
- Enforce the cell count — reject images whose segmentation returns the wrong number of blobs.
- Sample broadly — 20-30 glyphs per character across lots and rotations, plus a 50-image hold-out.
- Match polarity — train in the exact bright/dark orientation production will run.
- Gate the release — 99.5 percent per character and 98 percent whole strings on the hold-out, before the first shift.
- Log every score — re-read once on a low score, divert on the second, keep the record.
Send your ring measurements through the contact page if you want the reader choice checked against your cap, or start at the camera step of the configurator. The code reading topic page holds the rest of the decode guides.
Questions
How many sample images does training a custom OCR font need?
Start with 20-30 clean glyphs per character, drawn from at least three production lots or mold cavities. Add 10 extra samples for confusable pairs such as 0/O, 1/I and 8/B. Keep a separate hold-out of 50 or more full images that never enter training. If a class scores under 99 percent on that hold-out, collect 10 more samples for it and retrain.
Why does a built-in OCR font misread molded cap characters?
Shipped fonts are trained on printed glyphs with sharp, uniform strokes. Molded characters have rounded corners, draft angles and relief depth that shifts the pixel pattern with every change of light angle, so two caps rarely produce identical glyphs. The typical symptom is most of the ring misread, with round and straight characters confused and glare-flattened strokes dropped. Training on your own molded glyphs closes the gap.
Can OCR read cap-ring text without unwrapping the image?
Deep-learning OCR on some platforms reads mildly curved text directly, but a classic classifier font expects straight, upright characters of constant height, and a plain crop keeps cap rotation in the problem. The polar unwrap is a few lines of code, makes every glyph the same height and orientation, and lets one trained font serve caps seated at any angle.
What happens to the half of the ring you don't need to read?
Mask it. After the unwrap, the unwanted arc occupies a fixed horizontal band, so blank that band before segmentation. Fewer cells and fewer classes mean fewer chances to misread, a smaller training set and faster runs. If the layout ever changes, move the mask instead of retraining the font.
What accuracy should you demand before releasing the inspection to production?
Set two gates: at least 99.5 percent per-character accuracy and at least 98 percent full-string matches on a 200-image hold-out. Then log one full production shift and compare reject counts against manual reads of the same caps. If the string rate slips in production, suspect lighting drift before the font.

