Code readingTroubleshooting

Reading vertical text with OCR: rotate, segment, constrain

Why OCR fails on vertical text, when to rotate the image or segment per character, the pixel budget each glyph needs, and the checks that prove the fix.

LumaSpec Vision11 min read Share on LinkedIn

On this page 10 sections
  1. 01Why does OCR find no text when the characters are stacked vertically?
  2. 02Should you rotate the image first or segment every character separately?
  3. 03How do you measure the text angle before rotating?
  4. 04How many pixels does each character need?
  5. 05Which camera resolution reads your character height at your working distance?
  6. 06How do you handle parts that arrive in any orientation?
  7. 07Why does a trained OCR still return empty strings after rotation?
  8. 08When is per-character classification the only workable route?
  9. 09What do you check before the line goes live?
  10. 10Questions

Vertical text fails in a pattern you can diagnose in minutes: the detector reports no text at all, or it draws a correct bounding box and returns an empty string. The character model is rarely at fault — the layout stage in front of it is. This guide gives you the decision rule for rotating versus segmenting, the angle-measurement method that holds on real parts, the pixel budget that makes each glyph readable, and the checks that prove the fix before the line runs. The same logic applies on fixed code readers, smart cameras and PC-side pipelines.

Why does OCR find no text when the characters are stacked vertically?

The layout stage fails before recognition ever runs: most engines hunt for a horizontal line of text first, and six glyphs stacked in a column form a region about six times taller than it is wide, so detection returns nothing, or one tall box with an empty string.

Two failure modes, one root cause. Detection engines learn what text looks like as a line: a wide, low region with evenly spaced glyphs. A vertical stack violates that prior on both axes, so the detector either discards the region as non-text or keeps it and hands the recognizer a single "line" whose characters it cannot order. The second mode — a correct box and an empty string — is the recognizer declining to output anything from a region it cannot segment.

The two-minute test isolates it. Crop one glyph, upright and alone, and classify it. If the single glyph reads correctly, recognition works and layout is the entire problem, which is the case in the overwhelming majority of vertical-text failures. Document engines expose page-layout modes, and machine-vision OCR tools carry the same assumption in their region and line-direction parameters; changing a mode flag helps only on clean, straight crops, never on real parts.

Should you rotate the image first or segment every character separately?

Rotate the image first whenever text direction is fixed for the station: a 90° rotation is an exact pixel rearrangement with no accuracy cost, while per-character segmentation adds splitting, ordering and labeling work you should only take on when orientation genuinely varies part to part.

Three routes cover every case, in order of preference:

  1. Fixed direction per station. Measure the angle once on a known part, store it, rotate every image by it before recognition. This is the answer for labels that always run the same way on the belt.
  2. A short list of orientations. Run recognition on each candidate rotation — original, +90°, −90° — and keep the result with the highest total character score. Simple and robust; the price is one recognition pass per candidate.
  3. Anything-goes orientation. Classify orientation first (next-but-one section), or fall back to per-character segmentation.

Crop before you rotate. A text-region ROI cuts the pixels the transform touches and the time it takes, exactly as setting an ROI for inline code reading cuts decode time. Rotating frames before decoding is standard practice on barcode image rotation for the same reason; the pattern transfers one-to-one to text.

How do you measure the text angle before rotating?

Fit a minimum-area rotated rectangle around the text region and take the angle from it: on a clean, high-contrast crop the estimate lands within about 1° of true, comfortably inside the few degrees of skew a recognition model tolerates.

Four steps:

  1. Threshold the text region at a polarity that makes the glyphs solid — dark text on a light background, or the reverse.
  2. Take the connected component that covers the string, or the union of the glyph boxes.
  3. Fit the smallest rotated rectangle around it and read its angle.
  4. Rotate the crop by minus that angle.

Watch the ambiguity. A rectangle's angle is defined modulo 180°, and a vertical stack is ambiguous between top-to-bottom and bottom-to-top, so the raw angle alone cannot tell you the reading direction. Resolve it once on a known part, lock the sign of the correction, and store it with the recipe. The same trap exists in barcode deskew, and the Hough angle ambiguity fix walks through it.

How many pixels does each character need?

Give every character at least 30 pixels of height and target 50; below roughly 20 pixels the normalized glyph bitmap loses the counters and stroke gaps that separate similar characters, and misreads stop being occasional.

The budget is pixels of glyph height, not font points. From 30 pixels up, reads are dependable on clean print; 50 pixels buys margin for print defects, glare and the resampling of an arbitrary-angle deskew. Stacking makes the budget harder, not easier: a six-character stack needs six glyph cells plus gaps along one image axis, so the axis that matters is the one the stack runs along. The same budget governs horizontal text — why small text fails and how to fix it covers it in depth; only the axis changes here.

Which camera resolution reads your character height at your working distance?

Work backwards from the part: a 4 mm character held to a 50-pixel target needs 12.5 pixels per millimetre, so a 2048-pixel-tall sensor covers a 164 mm field of view with every glyph on target.

pixels per mm s = glyph target (px) / character height (mm) vertical FOV FOV_y = image height (px) / s motion blur b (px) = part speed (mm/s) × exposure (s) × s

Worked example, inputs stated: characters 4 mm tall on a panel, target 50 px per glyph.

  • s = 50 px / 4 mm = 12.5 px/mm
  • FOV_y = 2048 px / 12.5 px/mm = 163.8 mm, round to 164 mm
  • At the 30 px minimum: s = 7.5 px/mm, FOV_y = 2048 / 7.5 = 273 mm

So the readable window for this label sits between a 164 mm and a 273 mm vertical field of view. Frame tighter than 164 mm and you waste pixels; wider than 273 mm and glyphs drop below target.

Camera resolution for the smallest feature
Units
Pixels needed
–
Sensor size
– MP
Smallest sensor that fits
–
Pixel on the part
– mm
Pixels across the feature, that sensor
–

Pixels needed = field / feature × pixels per feature on each axis (field incl. margin). The lens must resolve the pixels too: Nyquist = 1000 / (2 × pixel µm) lp/mm.

Find cameras with enough pixels Open the full calculator

The calculator above runs the same numbers from whichever camera you own. The LS-CRD-0028 fixed code reader carries exactly the numbers this example used: 2560 × 2048 pixels, 5 MP, 8 mm lens, global shutter.

Fixed code readers2560 x 2048 fixed code reader, 30 fps, 60 codes/s, 8 mm lens (LS-CRD-0028)LS-CRD-0028
Interface
Fast Ethernet
Resolution
5 MP
Sensor format
1/1.7"
Shutter
Global
$920.00View part

Characters below the 4 mm example need more pixels than a 5 MP sensor carries. The MV-ID5120RM-08M-RBN reads at 12 MP over GigE. That is about 2.4 times the pixel count and roughly 1.5 times the linear scale, which turns an about 2.6 mm character into the same 50-pixel target.

Mono sensors put the whole contrast into one channel instead of splitting it across a color filter array, which helps on shiny or colored parts. The MV-SC5060XM-08M-WBN is a 6 MP mono smart camera with an 8 mm M12-mount lens.

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
$1,629.00View part
Fixed code readersHikrobot MV-ID5120RM-08M-RBN Industrial Code ReaderMV-ID5120RM-08M-RBN
Interface
GigE
Resolution
12 MP
$1,969.00View part

Once the px/mm target is fixed, the camera finder filters by resolution and shutter for the rest.

How do you handle parts that arrive in any orientation?

Decide orientation before recognition, not inside it: crop the text region, read its aspect ratio to tell a horizontal string from a vertical stack, then rotate once and run one recognition pass on the upright image.

Three practical options, ordered by cost:

  • Mechanical presentation. A fixture, chute or indexing stop that presents the label one way up removes the problem for the cost of a bracket. On a controlled line this is almost always the right answer.
  • Try all candidates, keep the best score. Run the recognizer on the original and the two 90° rotations, accept the highest total character score, reject the part if no candidate passes. Cycle time carries one extra pass per candidate.
  • Classify, then read once. The stack region's aspect ratio separates horizontal strings from vertical stacks; per-glyph aspect and stroke direction sort out the four 90° orientations of rotated glyphs. A decision this inexpensive belongs before recognition, not inside it.

When one image holds several strings in mixed directions, impose a deterministic assembly order; the multiple text strings in one image guide shows the pattern.

Why does a trained OCR still return empty strings after rotation?

Empty output after a correct rotation points at segmentation and polarity, not at recognition: the engine still receives one tall region and splits it at the inter-character gaps, so assign one region per character and confirm light-on-dark versus dark-on-light polarity matches how the font model was trained.

Work down this list; the first three items explain almost every post-rotation failure:

  1. Region shape. Give the recognizer one region per character, or confirm the tool treats the rotated column as a directed line. Splitting at gaps and reading garbage is the vertical cousin of touching letters, covered in the segmentation fix guide.
  2. Polarity. Training saw dark-on-light; the crop presents light-on-dark; the model returns nothing. Invert the crop or retrain with both polarities.
  3. Character set. An unrestricted set lets the model output nothing when uncertain. Whitelist the exact glyphs on the part — for example A-Z, 0-9 and hyphen — so every position must resolve.
  4. Acceptance threshold. A threshold tuned on training images rejects valid runtime glyphs. The settings that must match between training and runtime are listed in the OCR trains but fails at runtime guide.
  5. String order. Assemble top-to-bottom after rotation and check it once on a known part; a reversed string fails downstream lookups that would otherwise pass.

When the string finally assembles, send it as one message; the OCR string output over TCP guide covers the format. Characters still going missing after all of the above usually trace to text filtering, which the missing characters guide diagnoses step by step.

When is per-character classification the only workable route?

Per-character classification wins when no single rotation makes every glyph upright — wrap-around printing, curved caps, mixed angles on one part — at the cost of labeling a few hundred glyph samples per character class before accuracy settles.

Take that road when geometry defeats rotation, and build it as a pipeline:

  1. Segment connected components; keep glyph-sized blobs, drop specks and merged pairs.
  2. Normalize each glyph to a fixed size, say 32 × 32 pixels.
  3. Classify against the known character set — template matching for clean print, a trained model for real parts.
  4. Order by geometry: sort by column, then top-to-bottom within it.

The labeling cost is per glyph, not per image, and one labeled set serves every part that uses the same font. Curved caps are the classic case, and the custom OCR font training guide walks one end to end. Stylized glyph sets such as seven-segment displays need their own template per segment; the seven-segment display OCR guide covers the ROI and false-read rejection for them.

What do you check before the line goes live?

Prove the routine on the angle extremes rather than the tidy samples: replay archived images at 0°, +90°, −90° and 180°, require zero false accepts across the whole set, and re-time the cycle with recognition running on every candidate orientation.

Image budget

  • Glyph height at least 30 px on live images, 50 px targeted. Below 20 px, misreads stop being occasional.
  • Motion blur under 0.5 px. At the worked example's 12.5 px/mm and a 100 mm/s belt, the cap is 0.5 / (12.5 × 100) s = 0.0004 s = 0.4 ms of exposure.

Recognition set-up

  • One region per character or a directed line region; string assembled top-to-bottom and checked once on a known part.
  • Character set whitelisted to the exact glyphs on the part.
  • Acceptance threshold replayed against the archived image set until false accepts are zero.

Rotation path

  • Angle measured by minimum-area rectangle; sign locked against a known part.
  • Exact 90° multiples preferred; an arbitrary-angle deskew done once, not repeatedly.

Exposure under ambient light

A 0.4 ms exposure starves continuous lighting, so strobe instead: the flash freezes belt motion and ambient light contributes almost nothing to the frame. The LS-CTL-0070 strobe controller fires a light from a digital trigger on 4 channels with 200 W and RS-232 control. Match channels and power to your light in the light controllers range or the light controller finder.

Light controllersDigital control box, 4 ch, 200 W, RS232 (LS-CTL-0070)LS-CTL-0070
Output
Constant voltage 24 V
Channels
4 channels
Control
Digital
Feature
Strobe
$549.00View partBuild a system with it

Next step

Size the chain end to end — camera, lens, light, trigger — in the configurator below. If a string spec and cycle time still refuse to close, bring the part photo to the contact page and we will read it with you. More decode-side fixes live on the code-reading topic page.

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

Questions

Can document OCR engines read vertical text without rotating the image?

Some expose a page-layout mode for a uniform block of vertically aligned text, and it can work on clean, straight, high-contrast crops. On real parts — curved surfaces, uneven lighting, uneven gaps between glyphs — it rarely holds, which is why the dependable route is to normalize orientation in preprocessing and keep the recognition step ordinary.

Does a 90° rotation degrade the image?

No. Rotations in multiples of 90° only rearrange pixels, so no interpolation softens glyph edges and accuracy is unchanged. Arbitrary angles — a deskew by 7.3°, say — do resample the image and blur edges slightly. Measure once, rotate once, and avoid repeated resaves between processing steps.

How do you read text that runs bottom-to-top?

Measure the angle, rotate, then check which end the first character lands on. A 180° error turns ABC123 into a reversed string that fails downstream lookups even though every glyph looks sharp. Decide the sign of the correction on one known-good part and lock it into the recipe for the station.

Can one smart camera read both orientations on the same part?

Yes. Run the same OCR tool twice — once on the original crop, once on the 90°-rotated crop — and merge the results, keeping the higher total character score. The cost is cycle time, roughly one extra recognition pass. If timing is tight, classify the orientation first and run recognition once, in the direction the classifier reports.

Why does my fixed code reader read barcodes but ignore the text field?

Code readers ship tuned for barcodes and 2D codes; text reading is a separate OCR tool you add to the job, and not every model includes one. Check the reader's tool list for an OCR or text-string tool, set the character set and region, then apply the same rotation preprocessing described in this guide.