How To: Read a Part Marking from a Camera Image

Reading a printed part number off a camera image, from a fresh installation to a setting you can put into production.

The example is a six-digit part number printed on a label. Adapt the character set and the layout to your marking as you go.

Before you start

  • LumiScan Cam Driver, or another image source, running on the same ctrlX CORE and delivering images.

  • Its image node address to hand, e.g. hdvisionsystems/lumiscan-cam-driver/camera1/output/image.

  • A part in front of the camera, with the marking in shot, in focus and well lit.

1. Point the reader at the camera

write  hdvisionsystems/lumiscan-text-reader/module-1/read-text/input/input-image-address
       = "hdvisionsystems/lumiscan-cam-driver/camera1/output/image"

2. Take a first reading

Leave everything else at its default and run it:

write  .../module-1/read-text/execute
read   .../module-1/read-text/output/status-code   -> 1
read   .../module-1/read-text/output/status-text
read   .../module-1/read-text/output/result

A negative status code means it did not run - status-text says why. -3 is almost always a wrong image address.

At this point the reading is usually poor: too many words, some of them nonsense picked out of the background. That is expected, and the next three steps fix it.

3. Crop to the marking

Find the pixel coordinates of the label in the image - the ctrlX camera view will show them - and set a region a little larger than the text:

write  .../input/crop/startX = 620
write  .../input/crop/startY = 310
write  .../input/crop/width  = 260
write  .../input/crop/height = 90

Run it again. Most of the spurious words should be gone.

This is the step that helps most, and it also makes every reading faster. If the part can shift between cycles, make the crop large enough to cover the whole range it can occupy - a marking that drifts outside the crop reads as nothing, which is a better failure than reading as something wrong.

4. Restrict the character set

A six-digit part number contains only digits, so say so:

write  .../input/characters/mode = "DIGITS"

This is what stops 0 being read as O and 5 as S. If the number also contains letters, use UPPERCASE_LETTERS with allow = "0123456789" instead, or CUSTOM with allow set to exactly the characters your marking can contain.

5. Tell it what it is looking at

One line of print in a tight crop:

write  .../input/layout = "SINGLE_LINE"

Run it again. output/result.text should now be the part number and nothing else.

6. Choose a confidence threshold

Run five or ten known-good parts and note mean_score from each result, and the individual words[].score.

Correct readings on a decent image score well above 0.8. Set the threshold below your worst known-good reading and above the noise:

write  .../input/min-score = 0.7

min-score filters words[] only; text is always the engine’s full output. Check word_count rather than text when you need to know whether the reading was good.

7. Save the settings

Nothing above survives a restart until you save it:

write  hdvisionsystems/lumiscan-text-reader/system/save-module-inputs/input/module-id = "module-1"
write  hdvisionsystems/lumiscan-text-reader/system/save-module-inputs/execute

8. Wire it into the control program

Per cycle:

  1. Write read-text/execute - a blocking call, so there is no ready flag to poll.

  2. Check output/status-code. Negative means the reading failed and produced nothing.

  3. Read output/result.

  4. Check word_count is 1 and words[0].score is acceptable, then compare words[0].text against the expected part number.

Read the result before triggering the next reading: the next execute clears it.

Troubleshooting

Symptom What to do

Status code -3

The image node could not be read. Check the address, and that the source application is running on this ctrlX CORE.

Status code -2

A setting is unusable. status-text names every offending node and what it expected.

Status code -7

The OCR engine could not start. Usually the language model directory - check system/languages is not empty.

Status code 1 but no words, and the text is clearly there

A colour image with a photograph or other colourful scenery beside the text can read as completely empty. Set input/preprocess = "GRAYSCALE" - see Reading Accurately.

Status code 1 but no words

Nothing readable was found. Check the marking is inside the crop, in focus, and the right way up.

Digits confused with letters

Set input/characters/mode. This is what it is for.

Extra words from the background

Tighten input/crop, then raise input/min-score.

Text read in the wrong language

Check output/result.language. A language whose model is not installed is replaced by English - see Language Models.

Reading is too slow

Tighten input/crop, and avoid the AUTO_OSD and SPARSE_OSD layouts unless the orientation really varies.

Dot-matrix marking reads badly

Try input/engine = "LEGACY".