# LumiScan Area Detector 1.2.0.6 – complete documentation

> All pages of the LumiScan Area Detector 1.2.0.6 manual (language: en) by HD Vision Systems GmbH, in navigation order. Each page starts with a level-1 heading followed by its URL; cite that URL. Manual: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/

# Description – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/description.html

LumiScan Area Detector finds regions in a camera image and reports how big each one is.

It runs on ctrlX OS (ctrlX CORE or ctrlX IPC) with the ctrlX Data Layer, and on a PC (Windows 11 or Ubuntu 24.04) with LumiScan Keryx, the Data Layer of HD Vision Systems for PCs. Its nodes are the same on both, see [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html).

What is the same for every LumiScan app - how addresses are built, the handshake, execute and stream call patterns, status codes, settings and tools - is described in the [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html) manual. This manual covers only what is specific to LumiScan Area Detector; its own nodes are listed in the [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html).

Unlike the other LumiScan matching applications it needs **no reference picture**. You describe what counts as a region - how bright, how large, how round - and it reports every region matching that description, with its area and position.

That suits counting parts, checking coverage or contamination, measuring a fill level, and any inspection where the thing being measured has no fixed appearance: a spill, a scratch, a gap.

> [!NOTE]
> If you are looking for a **specific known part**, the sibling applications are the better fit: LumiScan Template Finder matches a stored picture at a range of scales and rotations, and LumiScan Object Finder matches an object’s shape. Area Detector answers "what is here, and how big", not "where is this thing".

## How a region gets found

Every method measures - the reported area is always a pixel count. What `input/method` chooses is how a region is found in the first place:

`input/method` is `FIXED`: the image is thresholded once at a level you commission, and every connected region is measured by counting its pixels, whatever its shape. It is the only method this version offers, and anything else written to that node is refused rather than ignored.

A region is counted as the pixels that passed the threshold, so a hole inside a part is **not** counted unless `fill-holes` is set — which is a choice about what a washer’s area means, not a correction.

To find the level, run [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html): it measures the picture, suggests a level, and publishes the grey-level histogram that level should sit in the valley of.

## Where the images come from

The application does not talk to a camera itself. It reads an image node published by another application on the Data Layer, given as an address, for example:

```
hdvisionsystems/lumiscan-cam-driver/camera1/output/image
```

The node must publish `data`, `width`, `height` and `pixel-type`, which is what LumiScan Cam Driver provides.

## Modules

A **module** is one configured instance of the detection: its own camera address, its own settings and its own results, at its own Data Layer address. One installation can run several modules to watch several cameras at once. On ctrlX OS one licence covers ten of them. See [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html).

Modules share nothing: there is no stored reference image, so there is nothing application-wide to configure.

# Requirements – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html

## Licence {#licence}

How LumiScan Area Detector is licensed depends on where you bought it and where it runs:

| Bought from | Runs on | Licensing |
| --- | --- | --- |
| HD Vision Systems | Windows 11 or Ubuntu 24.04 | The licence is held on your LumiScan Key. It is a one-time purchase and needs no renewal.<br><br>[Licensing path: bought from HD Vision Systems](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-hdvs.html) |
| ctrlX Store | Windows 11 | The licence is held in ctrlX WORKS. The LumiScan Key is required in addition; it protects the software against reverse engineering.<br><br>[Licensing path: ctrlX Store, Windows](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-windows.html) |
| ctrlX Store | ctrlX OS (ctrlX CORE or IPC) | ctrlX licence `SWL-W-XCx-AxxDETECTxHDVSx-V1NN`, one licence per ten modules.<br><br>[Licensing path: ctrlX Store, ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-os.html) |

Each device on which LumiScan Area Detector runs at the same time needs its own LumiScan Key. Keys can be exchanged between devices.

How to install CodeMeter Runtime and how to request, renew and move licences is described in [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

On ctrlX OS, the application shuts down shortly after starting if the licence is missing; the reason is written to the system log.

## A platform and its Data Layer

| Platform | Data Layer |
| --- | --- |
| ctrlX OS (ctrlX CORE or ctrlX IPC) | ctrlX Data Layer, provided by ctrlX OS |
| a PC with Windows 11 or Ubuntu 24.04 | LumiScan Keryx, the Data Layer of HD Vision Systems for PCs |

On ctrlX OS there is nothing to install for the Data Layer.

On a PC the application starts the LumiScan Keryx broker when none is running; installing and setting up LumiScan Keryx is described in [LumiScan Keryx on a PC](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

## An image source on the same device

The application reads its images from another application’s Data Layer image node. That application must run on the **same device** as the Area Detector - the same ctrlX CORE or ctrlX IPC, or the same PC. Remote Data Layer access is not supported.

In practice this is LumiScan Cam Driver, but any application works as long as its image node provides these four children:

| Node | Type | Description |
| --- | --- | --- |
| `data` | array of uint8 | Raw, uncompressed pixel data |
| `width` | uint64 | Image width in pixels |
| `height` | uint64 | Image height in pixels |
| `pixel-type` | string | GenICam pixel format name |

### Supported pixel formats

`Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `BayerGR8`, `BayerGR12`, `BayerRG8`, `BayerRG12`.

Bayer images are converted to colour and 12-bit images are scaled down to 8 bit before detection, so a threshold tuned on one format still applies to another.

Any other pixel format is rejected with status code `-3`.

## Storage

The application stores nothing but its module list and their settings - a few kilobytes of JSON in the application’s configuration directory. On ctrlX OS that directory is part of the active solution. Where it is on each platform is listed under [Configuration file](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html#configuration-file). There is no reference image to keep, so no storage needs planning for.

The image stream (experimental) adds one folder beside them, `settings-history/`: one small JSON file for each settings hash a module publishes, never deleted. See [Processing an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html).

## Timing

Detection is **synchronous**: the call to `execute` returns when the search has finished. How long that takes depends on the image size and on the mode. Measuring (`input/method`) is a threshold and one connected-components pass, so it scales with the image. Estimating repeats the detection once per threshold level, so it scales with the image **and** with how many levels `method-specific/circle/threshold/step` produces - which makes `method-specific/circle/threshold/step` the setting to widen first when a cycle is too slow.

See [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html).

# Execute a Method – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execute-a-method.html

Every operation of this application - detection, scene analysis and module management - is started the same way, and reports its outcome the same way. They are execute methods of the Data Layer; how execute methods work in general is described in [Execute Methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html).

## The shape of an operation

An operation lives under its own address and always has three parts:

```
<operation>/execute                 write here to run it
<operation>/input/...               the values it works on
<operation>/output/status-code      what happened, as a number
<operation>/output/status-text      what happened, in words
```

Some operations have more under `output/` - a detection result, a label image or a histogram - but `execute`, `status-code` and `status-text` are always there.

## Running an operation

1. Write the input nodes.
2. Write to `execute`. The value does not matter; the write itself triggers the operation.
3. Read `output/status-code` to find out whether it worked.

Writing to `execute` is a **blocking call**: it returns when the operation has finished, so there is no need to poll a "ready" flag or track state in your program. Inputs keep their values between runs, so a repeated operation only needs step 2.

## Checking the outcome

`output/status-code` is a signed number, and **the sign alone tells you whether it worked**:

| Value | Meaning |
| --- | --- |
| greater than 0 | The operation succeeded |
| 0 | The operation has not run since the application started |
| less than 0 | The operation failed and produced nothing |

So the check in a PLC is simply `status-code < 0`. You only need a specific code when you want to react differently to different failures - an invalid input, say, versus a camera that is not answering.

`output/status-text` carries the same outcome as a sentence, and names the offending value when there is one:

```
error: crop/startX + crop/width (100 + 900 = 1000) exceeds the image width 640
```

Read it when something goes wrong; do not build logic on it, because the wording can change between releases. The full list of codes is in [Execution Status](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html).

> [!NOTE]
> The reason arrives on `output/status-text`, not in the response to the `execute` write itself. A failed write answers with a status code only - over REST, a bare `400`. The Data Layer discards any detail a provider attaches to a failed call, so reading `output/status-text` afterwards is the way to find out what was wrong. The results a write can answer with, and their names on the ctrlX Data Layer and on LumiScan Keryx, are listed in [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).
>
> The same text is written to the application log, so a failure is also diagnosable without touching the Data Layer at all: on ctrlX OS from the ctrlX Logbook or `journalctl`, on a PC from the application’s console output. When several inputs are wrong, each one gets its own warning line.

## One operation at a time

A module runs one operation at a time. Starting a second one while the first is still running does not queue it - it returns immediately with status code `-1` (busy) and does nothing. The write itself answers `TooManyOperations` (ctrlX: `DL_TOO_MANY_OPERATIONS`), see [One operation at a time](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html#busy).

The lock is per module, so different modules detect in parallel - a second camera is not held up by the first. `system/analyse-scene` has its own lock, so analysing a scene does not block detection and two analyses cannot race.

## The outputs belong to the run that is starting

Every method clears its own output nodes as soon as it begins - `detect-area` its `output/result`, `analyse-scene` its `output/histogram`. They are cleared **before** anything that can fail, so a run that fails for any reason leaves them empty rather than holding what an earlier run produced.

That is what makes it safe to read an output without checking `output/status-code` first: what you see is either this run’s work or nothing, never a stale value from a previous image.

`output/status-code` and `output/status-text` are the exception - they always describe the latest attempt, which is the whole point of them.

> [!WARNING]
> **Read an output before triggering the next run.** The outputs describe the most recent run, and the next call empties them the moment it starts. Calling `execute` again and then reading the previous result gives you nothing.
>
> The one case that does **not** clear anything is a call rejected as `-1` (busy): it never ran, so it leaves the running operation’s outputs alone. So a second `execute` fired immediately after the first has two possible outcomes, and they differ:
>
> - the first run is **still going** - the second is refused with `-1`, and the outputs still hold the run before it;
> - the first run has **just finished** - the second is accepted, and it clears the outputs the first run had only just written.
>
> Wait for `execute` to return, read the outputs, and only then trigger the next run.

# Execution Status – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html

Every operation reports its outcome on two nodes beside it: `output/status-code` for your program, and `output/status-text` for a person. These codes are the execution status of the finders, not the module status of the Cam Driver, AI Object Matching or Calibration; see [Execution status of the finders](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#execution-status).

## Status codes

| Code | Meaning | When it happens |
| --- | --- | --- |
| `0` | Idle | The operation has not run since the application started |
| `1` | OK | The operation completed. A search may still have found nothing - that is a normal result, not an error |
| `-1` | Busy | Another operation of the same module was still running. Nothing was done; try again when it has finished |
| `-2` | Invalid input | An input value cannot be used - a required node left empty, an unknown `input/method` or `input/preprocess/method`, a parameter outside its range, or an image address pointing at this application itself |
| `-3` | Image read failed | The image node at the given address is missing, empty, inconsistent, or uses an unsupported pixel format. Check that the camera application is running and has captured an image |
| `-4` | Source not found | A required file or directory is missing or unreadable |
| `-5` | Invalid crop region | The region of interest does not fit inside the image. The message names the actual image size |
| `-6` | Write failed | A file could not be written - usually a permission problem or a full disk |
| `-7` | Algorithm failed | The detection itself failed |
| `-8` | Publish failed | The result could not be written back to the Data Layer |
| `-9` | Module not found | The named module does not exist. Check `system/modules` for the current list |
| `-10` | Module already exists | A module with that name is already there |
| `-11` | Licence unavailable | No licence covers the module. See [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html) |

> [!NOTE]
> These numbers are part of the application’s interface. New codes may be added in later releases, but existing ones never change meaning, so logic written against them keeps working after an update.
>
> This is also why checking the **sign** is the more robust test: `status-code < 0` stays correct even when a release introduces a failure your program has never seen.

## Which operation reports which

| Operation | Possible codes |
| --- | --- |
| `detect-area` | `1`, `-1`, `-2`, `-3`, `-7`, `-8` |
| `system/analyse-scene` | `1`, `-1`, `-2`, `-3`, `-7` |
| `system/save-module-inputs` | `1`, `-6`, `-9` |

## Status text

`output/status-text` always starts with `ok:` or `error:` and gives the reason in words. It is written at the same time as the status code, so both always agree.

Each operation has its own pair of nodes, and they keep their values until that operation runs again. A failed scene analysis therefore does not disturb the result of the last detection.

# Detecting Areas – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html

`<module>/detect-area` searches one image, once, and reports the regions it finds.

## Running it

Set the image address and execute:

```
module-1/detect-area/input/input-image-address = hdvisionsystems/lumiscan-cam-driver/camera1/output/image
write module-1/detect-area/execute
```

Then read `output/status-code` and `output/result`.

Everything else has a working default, so this first run tells you whether anything is being found at all. Tuning follows: see [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html), and [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html) for commissioning the threshold level.

## The result

`output/result` is an `area_detect_result` flatbuffer.

| Field | Meaning |
| --- | --- |
| `blobs[].x`, `.y` | Centre of the region. |
| `blobs[].area` | [pixel^2] Pixels the region covers, counted - never derived from a fitted shape. |
| `blobs[].label` | Which region this is in `output/blob-labels` - how a reported area maps to its pixels. |
| `blobs[].bbox_x/y/width/height` | Tight box around the region. |
| `blob_count` | How many regions, for a control program that only needs a count. |
| `total_area` | [pixel^2] Sum over all regions - the headline number for a coverage check. |
| `largest_index`, `largest_area` | The biggest region. |
| `image_width`, `image_height` | The searched region - the whole image unless a crop was set. |
| `preprocess_method` | `NONE`, `LOG`, `DOG` or `DOH`, as applied. |
| `timestamp` | Microseconds since epoch, when the run finished. |

Regions are sorted by area, so `blobs[0]` is the largest.

`total_area` is usually the number to act on: coverage, contamination and fill checks are all "how much", not "how many".

## Colour images

Either a grey or a colour image goes in. Thresholding and connected components are single-channel operations, so a colour image is converted and measured like any other. On ctrlX OS, a ctrlX image node delivers three colour channels whatever the camera is, so a grayscale camera produces three identical copies. There is no flag, and a region is reported once however many channels arrived.

## Restricting the search

`input/crop/{startX, startY, width, height}` limits the search to part of the image. A zero width or height reaches the corresponding edge, so the default all-zero region searches everything and `startX=100` with zero sizes searches from there to the bottom-right corner.

Two reasons to use it: speed, and excluding areas where a region cannot be, which avoids counting background clutter.

A region reaching past an edge is refused rather than trimmed, naming the input and the limit it broke.

## Preprocessing

`input/preprocess/method` applies one filter before detection:

| Method | What it does |
| --- | --- |
| `NONE` | The default. |
| `LOG` | Laplacian of Gaussian - blur then a second derivative; emphasises regions of a size set by the sigma. |
| `DOG` | Difference of Gaussians - two blurs subtracted, a band pass. `sigma-first` must differ from `sigma-second`. |
| `DOH` | Determinant of Hessian - second derivatives combined. `kernel-size` must be 1, 3, 5 or 7. |

Only the chosen method’s parameters are read, and only they are validated.

## The regions themselves

The result carries numbers, not pixels. The pixels are in `output/blob-labels`, published by every run: one region number per pixel, and `blobs[].label` says which number is which region. See [The Label Image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/the-label-image.html).

## An empty result

An empty `blobs` list with `status-code` 1 means **no regions matched** - nothing else. Every other reason a run could produce nothing is caught before detection and reported as a negative status code. See [Execution Status](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html).

# The Label Image – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/the-label-image.html

Every run publishes `output/blob-labels`, and nothing else. It is an ordinary image node - `data`, `width`, `height`, `pixel-type` - carrying one number per pixel: the region that pixel belongs to, or `0` for background.

## Why one output and no choice

The detector finds regions with connected components, so a label image **is** the result. Contours, polygons and per-region masks were all ways of describing the same thing less directly, and `input/publish` was a menu for choosing between descriptions. One output cannot disagree with itself.

## Reading it

`pixel-type` is **Mono16**, not Mono8 - a picture can hold more than 255 regions, and a label is a number rather than a brightness, so wrapping it at 255 would silently merge two regions into one.

The numbers are the `blobs[].label` values in `output/result`. That is what makes the image useful rather than decorative: from a reported area you can reach the exact pixels it was measured from.

```none
blobs[2].label == 7   ->   every pixel of blob-labels holding 7 is that region
```

A binary mask, if that is all you need, is `labels > 0`.

## What is in it, and what is not

The image is **whole frame**, at the size of the input image - not the crop. Crop with `crop_x/crop_y/crop_width/crop_height` from `output/result` if you want just the searched region.

Every region `output/result` reports is lit here, and no other is. The picture and the numbers always describe the same regions, so a region you can see is one you can look up.

Labels are **not** renumbered. `blobs[].label` has to keep addressing the same pixels, so the numbers are the detector’s own rather than a position in the reported list — which is sorted by area, and so does not run in label order.

## In the Cockpit

The Cockpit tints each region a different colour over the camera picture. That is why the label image exists rather than a plain mask: neighbouring regions come back as **different colours**, so a reported area can be traced to the exact pixels it was measured from. A bounding box could never show that - two overlapping boxes tell you nothing about which pixels belong to which region.

# Detecting Areas on an Image Stream (Experimental) – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html

> [!IMPORTANT]
> The image stream is **experimental**. Its nodes and settings may still change. Use it for evaluation, and verify it with your cameras and your Data Layer before relying on it.

`detect-area` searches one image per call: your program sets `input/input-image-address` and writes to `execute`. An image stream works the other way round. The Cam Driver publishes every image it takes on `<camera name>/control/publish/output/stream/frame`, with its size, its pixel format and its lineage (see the Cam Driver manual, *Streaming Images*). A module subscribes to the stream of one camera, detects the regions in each frame as it arrives, and publishes one result per frame on `control/subscribe/output/stream/result`. The stream works the same way on the ctrlX Data Layer and on LumiScan Keryx; the concept shared by all LumiScan apps is described in [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html). This page describes what is particular to the Area Detector.

Each frame is searched with the inputs of `detect-area` as they are at that moment: the threshold level, the preprocessing, the crop region and every other node under `detect-area/input/`. The one input the stream does not use is `input/input-image-address`: the frame takes its place. If you change an input while the stream runs, the next frame is searched with the new value.

> [!IMPORTANT]
> The stream publishes the measurements only. The label image `detect-area` publishes on `output/blob-labels` has no stream counterpart. `blobs[].label` is still filled in, but there is no image to look it up in.

Each result carries the lineage of its frame - which camera took it, in which run of the camera’s stream, as which frame of the run - with the module’s own step added. See [The lineage of a result](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#lineage).

By default the module never falls behind its camera. When frames arrive faster than the module searches them, it takes the newest frame each time the previous search is finished. The frames in between are counted as skipped. How many frames may wait is set with the queue size, see [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#queue-size).

A module takes the stream of one camera. For another camera, or other settings, use another module.

## The stream’s nodes {#addresses}

Every module has the stream’s nodes, whether it subscribes to a stream or not. No restart is needed to start using them. All addresses below start with `hdvisionsystems/lumiscan-area-detector/<module-id>/`. They sit beside `detect-area/`, not inside it.

**Table 1. Methods**

| Address | Meaning |
| --- | --- |
| `control/subscribe/execute` | Checks the five inputs of `control/subscribe` together, saves them in the module’s settings file, then applies them: a running stream follows on its next cycle, with no restart. Writing an input alone changes nothing. See [Changing the source](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#subscribing). |
| `control/unsubscribe/execute` | Drops the source named by `control/unsubscribe/input/address`, which ends stream mode too. The tag stays. Saved in the module’s settings file like a subscribe. |

**Table 2. Inputs of control/subscribe**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/input/enable` | bool | Stream mode: `true` runs the stream, `false` stops it. |
| `control/subscribe/input/address` | string | The one source: a camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`. The module reads its `frame` node. Another address replaces the source. |
| `control/subscribe/input/tag` | string | The tag the module puts on its results: the module’s step in the lineage of each result carries it, so whoever reads a result downstream sees which module made it. Empty: the module id, the last segment of the module’s address, for example `module-1`. A new tag marks the next result; the source stays subscribed. |
| `control/subscribe/input/queue-size` | uint32 | How many frames may wait while a frame is searched: `1` to `64`. See [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#queue-size). |
| `control/subscribe/input/keep-latest-output` | bool | `true` to write each stream result to `detect-area/output/result` as well. See [Keeping the latest output](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#keep-latest-output). |

The inputs start with what is applied at the start of the application, so a client can change one of them and execute.

What the source must hold: read `hdvisionsystems/lumiscan-area-detector/system/meta/subscription-schema`, the same for every module. It is a JSON Schema of the `frame` node of the source, a `stream_image` with its `lineage` and its `image`, in its JSON form. See [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html).

**Table 3. Input of control/unsubscribe**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/unsubscribe/input/address` | string | The source to drop: the address `setting/stream/address` shows. A `/` at either end does not count. |

**Table 4. Settings**

| Address | Type | Meaning |
| --- | --- | --- |
| `setting/stream/enable`, `setting/stream/address`, `setting/stream/tag`, `setting/stream/queue-size`, `setting/stream/keep-latest-output` | as the inputs | What `control/subscribe/execute` or `control/unsubscribe/execute` applied last, as the settings file keeps it. Read-only. |
| `setting/settings-hash` | string | The hash of what the results are made with, as 16 hex digits. Read-only. See [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#settings-hash). |

**Table 5. Outputs**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/output/stream/active` | bool | `true` while the stream runs. |
| `control/subscribe/output/stream/result` | flatbuffers `stream_areas` | The regions found in each frame, and the frame’s lineage. Subscribe to it to receive each one. See [The result of a frame](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#result). |
| `control/subscribe/output/stream/last-failure` | string | Why the last frame that could not be searched failed. It names the source by its address, see [The result of a frame](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#result). Emptied when the stream starts. |
| `control/subscribe/output/stream/statistics/…` | uint64 | Counters of the current or the last stream, see [Reading the statistics](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#statistics). |

The stream publishes its results on `control/subscribe/output/stream/result`. Of the nodes of `detect-area` it writes only `detect-area/output/result`, and only with `keep-latest-output` on: `output/blob-labels`, `status-code` and `status-text` keep what the last call of the method left there.

## Setting it up {#setting-up}

1. Make sure the Cam Driver’s stream runs: its `hdvisionsystems/lumiscan-cam-driver/<camera name>/control/publish/output/stream/active` is `true`.
2. Set the inputs of `detect-area` as for a single detection, see [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html). A call of `detect-area/execute` on the camera’s `output/image` is a quick way to check them.
3. Write the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `control/subscribe/input/address`. Leave `control/subscribe/input/tag` empty to mark the results with the module id, or write a tag of your own to it.
4. Subscribe to `control/subscribe/output/stream/result`.
5. Set `control/subscribe/input/enable` to `true`, then write to `control/subscribe/execute`. Wait until `control/subscribe/output/stream/active` is `true`. The results arrive from then on.
6. To stop, set `control/subscribe/input/enable` to `false` and write to `control/subscribe/execute` again. The frame being searched is finished first.

On ctrlX OS, use the Data Layer view of the ctrlX OS web interface or your PLC program for these steps.

On a PC, the same steps with `krxclient`, the command line client of LumiScan Keryx that stands in for a PLC (see [Tools](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/tools.html#krxclient)). Add the `--keryx-backend` and `--keryx-url` options your broker needs:

```none
krxclient write hdvisionsystems/lumiscan-area-detector/module-1/control/subscribe/input/address hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream
krxclient write hdvisionsystems/lumiscan-area-detector/module-1/control/subscribe/input/enable true
krxclient execute hdvisionsystems/lumiscan-area-detector/module-1/control/subscribe/execute
krxclient subscribe hdvisionsystems/lumiscan-area-detector/module-1/control/subscribe/output/stream/result --count 5
```

`krxclient subscribe` shows a flatbuffer by its size only. It tells you that results arrive, not what they hold.

Good to know:

- Stream mode is a **level**, not a command: the stream runs for as long as the applied `enable` is `true`.
- The stream can be started before the Cam Driver’s stream. Results arrive once frames do.
- What `control/subscribe/execute` applies is saved in the module’s settings file. After a restart of the application the module starts as it was: one that streamed streams again at once, without your program executing anything. See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#saving).

## Changing the source {#subscribing}

A module takes one source. A PLC or another client changes it while the application runs, with or without a running stream:

1. Write the new values to the inputs of `control/subscribe` - only those you change: the others hold what is applied.
2. Write to `control/subscribe/execute`. The inputs are checked together, saved in the module’s settings file, and only then applied: `setting/stream/` shows them at once, and a running stream follows on its next cycle. Another address replaces the source; the frames the old one had waiting are counted as skipped. A new tag, queue size or `keep-latest-output` needs no new subscription: a new tag marks the next result.
3. To drop the source, write its address to `control/unsubscribe/input/address`, then write to `control/unsubscribe/execute`. Stream mode ends with it. The inputs of `control/subscribe` are set to what it applied: stream mode off, no address. The tag stays: it marks the module’s results, not the source.

When the settings file cannot be written, nothing changes. See [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#saving).

The methods answer with a result of the Data Layer. Its name differs between the two Data Layers, see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results):

| ctrlX OS | PC (LumiScan Keryx) | When |
| --- | --- | --- |
| `DL_OK` | `Ok` | Done. |
| `DL_INVALID_VALUE` | `Rejected` | `control/subscribe/execute`: stream mode without an address, or a queue size outside `1` to `64`. `control/unsubscribe/execute`: the address is not the source, or there is no source. |
| `DL_CREATION_FAILED` | `CreationFailed` | The settings file could not be written, for example because it is not valid JSON. Nothing changed. |

These methods have no `status-text`. The reason for a refusal is written to the application log.

When the source cannot be subscribed to, the module tries it again every 5 seconds while the stream runs, and logs the first failure.

## The result of a frame {#result}

`control/subscribe/output/stream/result` holds a FlatBuffers table of type `stream_areas` (file identifier `HSAR`), registered on the Data Layer as `types/hdvisionsystems/lumiscan-area-detector/stream_areas`. Its compiled schema is installed as `bfbs/stream_areas.bfbs`.

| Field | Meaning |
| --- | --- |
| `lineage` | Where the result came from, see [The lineage of a result](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#lineage). |
| `result` | The regions, as a `hdv.area_detect.Result`: the same table `detect-area` writes to `output/result` for the same picture, described in [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html). |

A read of `control/subscribe/output/stream/result` returns the latest result; before the first frame, an empty one. The last result stays after the stream stops.

A frame is decoded as `detect-area` decodes the image node, so the same pixel formats are accepted, see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html). A frame and the same picture read through `input/input-image-address` give the same regions.

A frame that cannot be searched gives no result. It is counted in `statistics/failed-frames`, and `control/subscribe/output/stream/last-failure` says why, for example:

```
a frame of 'hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream' failed: invalid input: preprocess/method 'LAPLACE' is unknown; expected NONE, LOG, DOG or DOH
```

The reasons are the ones `detect-area` gives in its `status-text`: an input it would refuse, a crop region that does not fit the frame, a detection that failed.

## The lineage of a result {#lineage}

`lineage.steps` lists where the result came from, origin first:

1. The camera’s step, as the Cam Driver made it: `producer` is the camera’s address, `hdvisionsystems/lumiscan-cam-driver/<camera name>`; `run` when the camera’s stream started; `sequence` the frame’s number in that run; `external_id` the camera’s own frame number; `settings_hash` the camera’s settings; `tag` the Cam Driver’s tag for the camera, by default its module id, for example `camera1`.
2. The module’s step: `producer` is the module’s address, `hdvisionsystems/lumiscan-area-detector/<module-id>`; `run` when the module’s stream started (each start is a new run); `sequence` the result’s number in the run, from `1`; `settings_hash` the module’s settings, see [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#settings-hash); `elapsed_us` the microseconds from the frame’s arrival at the module to its result, waiting included; `time_us` when the result was made, in microseconds since the epoch; `tag` the module’s tag, `control/subscribe/input/tag`, or the module id when it is empty.

So a result names its frame exactly: the camera by `producer`, the frame by `run` and `sequence`. To know which camera a result came from, read the `producer` of its first step. A gap in the camera step’s `sequence` between two results of the same camera is frames that were skipped, failed or lost.

A lineage holds at most 16 steps. A longer one keeps the origin and the newest steps, and `dropped` counts the steps left out.

A frame that carries no lineage gives a result with the module’s step alone. A value on a stream’s `frame` node that is not a `stream_image` is ignored, and logged once.

## The settings hash {#settings-hash}

`setting/settings-hash`, and the `settings_hash` of the module’s step in each result, identify what the results are made with. The node shows the hash as 16 hex digits; the step holds the same value as a number. The hash covers:

- every input of `detect-area` the detection reads, exactly as it was read for the frame - all of them but `input/input-image-address`;
- the application’s name and version.

No input of `detect-area` names a file, so no file is part of the hash. Stream mode, the source, the queue size and keep-latest-output are not part of it either: they choose and pace the frames, they do not change what is found in them.

`setting/settings-hash` is updated about every half second, also while the stream is off. The first time a hash appears, the module writes the settings it stands for to `settings-history/<module-id>-<hash>.json` in the application’s configuration directory, so a hash found in a result can be looked up later. The application does not delete these files. A file looks like this, shortened:

```json
{
    "format": 1,
    "settings": {
        "detect-area/input/method": "FIXED",
        "detect-area/input/method-specific/fixed/level": 128.0,
        "detect-area/input/preprocess/method": "NONE",
        "software.name": "lumiscan-area-detector",
        "software.version": "<version>"
    },
    "settingsHash": "<16 hex digits>"
}
```

> [!NOTE]
> A result carries the hash only. A different hash says that something the results are made with changed, not what changed. To find out, compare the two files in `settings-history` that the hashes name, by hand.

The hash covers the parameters of every preprocessing method, not only the selected one. Editing `input/preprocess/dog/…` while `input/preprocess/method` is `NONE` changes the hash, though not a single region.

## Reading the statistics {#statistics}

The counters start from zero each time the stream starts, are updated about four times a second while it runs, and keep their last values after it stops. All addresses start with `control/subscribe/output/stream/statistics/`.

| Counter | Meaning |
| --- | --- |
| `elapsed-ms` | Milliseconds since the stream started. Divide a counter by it for a rate. |
| `received-frames` | Frames the subscription delivered. |
| `processed-frames` | Frames searched, each with a result published on `control/subscribe/output/stream/result`. |
| `skipped-frames` | Frames never searched: pushed out of the queue by newer ones while a frame was searched (see [The queue size](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#queue-size)), or waiting when the source was replaced or dropped. |
| `failed-frames` | Frames that could not be searched. `control/subscribe/output/stream/last-failure` says why the last one failed, and the log names the failures, at most one line every 5 seconds. |
| `lost-frames` | Frames dropped before they arrived, counted from gaps in the camera’s `sequence` within one run of its stream. A new source, or a new run of the camera’s stream, starts the count again. |
| `processing-us` | Microseconds all detections took, summed, without the time a frame waited for `detect-area`. Divide by `processed-frames` for the mean. |

Frames still waiting when the stream stops are dropped without being counted.

## Kept in the settings file {#saving}

Stream mode and the source are settings of the module. They are kept in the `stream` member of the module’s settings file, `<module-id>.json` in the application’s configuration directory - the file `system/save-module-inputs` writes the inputs to.

`control/subscribe/execute` and `control/unsubscribe/execute` save what they apply there themselves, all five values in one write, before they apply them. When the file cannot be written, the method answers `DL_CREATION_FAILED` (on a PC `CreationFailed`) and nothing changes. After a restart the module subscribes to the same source and, when `stream.enable` is `true`, starts its stream at once: nobody needs to execute anything.

Saving changes only the `stream` member; the rest of the file stays as it was. The module makes the file when there is none yet - a module whose inputs were never saved has none. `system/save-module-inputs` in turn keeps the `stream` member when it rewrites the file; the inputs of `control/subscribe` are not saved as the module’s inputs.

The configuration directory is:

| Platform | Configuration directory |
| --- | --- |
| ctrlX OS | `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-area-detector` |
| PC (Windows) | `%APP_RESOURCE_DIR%\etc\lumiscan-area-detector`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-areadetect\etc\lumiscan-area-detector` |

The `stream` member, beside the inputs of `detect-area` (shortened here):

```json
{
    "detect-area": {
        "method-specific/fixed/level": 128.0
    },
    "stream": {
        "enable": true,
        "address": "hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream",
        "queueSize": 1,
        "keepLatestOutput": false
    }
}
```

| Key | Required | Meaning |
| --- | --- | --- |
| `enable` | No | Stream mode: `true` starts the stream at the start of the application. Needs an `address`. `false` if left out. |
| `address` | No | The one source: a camera’s stream folder. |
| `tag` | No | What marks the module’s results: the `tag` of the module’s step in their lineage. The module id if left out. |
| `queueSize` | No | How many frames may wait: `1` to `64`, `1` if left out. |
| `keepLatestOutput` | No | `true` to write each stream result to `detect-area/output/result` as well. `false` if left out. |
| `onEntry` | No | The steps applied to each frame as it arrives, each an object with a `kind`, as every LumiScan application’s `stream` has them. This application has none yet: leave it out, or empty (`[]`). A step starts the module out of stream mode, with a warning in the log; saving keeps it. |

`control/subscribe/execute` and `control/unsubscribe/execute` write all five.

Good to know:

- The file is read once, when the module is restored at the start of the application: a module in the saved module list, or `module-1` on a fresh installation. Changes made to the file by hand take effect at the next start.
- A module made with `system/create-module` starts with the stream off, no source, a queue size of `1` and `keep-latest-output` off, whatever a file of its name holds. What it applies from then on is saved to that file.
- To have a module and its stream back after a restart, save the module list too, with `system/save-current-modules`. Saving a list that no longer names a module deletes that module’s file, and its stream settings with it. See [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html).
- A value that cannot be used is ignored, and logged: an `enable` or `keepLatestOutput` that is not `true` or `false`, an `address` or `tag` that is not a string, a `queueSize` outside `1` to `64` (`1` is used). Stream mode without an `address` is ignored: the module starts out of stream mode.
- The `subscriptions` member of earlier versions is no longer read, and the module logs that it moved: give the source as `address`.

> [!WARNING]
> Do not add comments to `<module-id>.json`. The stream reads a file with comments, but the module’s inputs are then not restored at start: the log reports the file as unreadable.

## The queue size {#queue-size}

`control/subscribe/input/queue-size` sets how many frames may wait while a frame is searched: `1` to `64`, `1` by default. It is saved as `stream.queueSize`, and `setting/stream/queue-size` shows the value in use. A frame that arrives when that many wait pushes out the oldest of them, which is counted in `statistics/skipped-frames`. A new queue size applies from the next frame that arrives, with no new subscription.

| Queue size | Effect |
| --- | --- |
| 1 (default) | The module searches the newest frame. It never falls behind; when the search is slower than the camera, it skips frames. |
| More than 1 | Short bursts of frames are all searched, and fewer are skipped. When the search is slower than the camera for longer, the module falls behind: it searches frames up to that many searches old. Each waiting frame holds a whole image in memory. |

## Keeping the latest output {#keep-latest-output}

With `control/subscribe/input/keep-latest-output` `true` - applied by `control/subscribe/execute`, saved as `stream.keepLatestOutput` - the module also writes each stream result to `detect-area/output/result`, as `detect-area/execute` writes it, once the result is published on `control/subscribe/output/stream/result`. A client that reads `detect-area/output/result` then has the newest frame’s result without subscribing to the stream. `output/blob-labels`, `status-code` and `status-text` are not written: they keep what the last call of `detect-area` left there. It costs a copy of each result. Off by default.

## detect-area while the stream runs {#while-streaming}

The stream and `detect-area` use the same inputs, and they never run at the same time on one module:

- A frame that arrives while `detect-area` runs waits until the method has finished. It is delayed, not failed.
- A call of `detect-area/execute` while a frame is searched answers busy: `output/status-code` is `-1`, the write answers `DL_TOO_MANY_OPERATIONS` (on a PC `TooManyOperations`), and nothing is done. `output/result` and `output/blob-labels` keep their values, as for any busy call (see [Execute a Method](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execute-a-method.html)). With a camera streaming, this happens often. Stop the stream before you call the method, or call it again.
- `system/remove-module` also answers busy (`-1`) while a frame of that module is searched. Stop the stream first. Removing a module stops its stream.
- `system/analyse-scene` has a lock of its own and is not held up by the stream.

Other modules are not affected: each module has its own lock and its own stream.

## Limitations {#limitations}

- The label image is not streamed, see above.
- The stream has been tested on Windows with LumiScan Keryx and with simulated images only. It has not been verified on Linux, on the ctrlX Data Layer, or with a real camera.
- LumiScan Cockpit does not draw the stream’s results yet.
- Changes made to the settings file by hand take effect at the next start of the application.
- The hash covers every input the detection reads, the parameters of preprocessing methods that are not selected included. It changes with some edits that do not change a result.

# Analysing a Scene – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html

`system/analyse-scene` measures a picture and tells you what a fixed threshold would have to be commissioned at to measure the parts in it. It reports; it changes nothing.

It sits on `system/` rather than inside a module because the answer is about the **picture**. Ten modules looking at the same camera would have asked the same question ten times and got the same answer back.

## What it needs

| Node | Type | Default | Meaning |
| --- | --- | --- | --- |
| `input/input-image-address` | string | `""` | The image node to analyse. Its own, not a module’s. |
| `input/crop/startX` .. `height` | uint16 | 0 | The region to analyse; all zero means the whole image. |
| `input/bin-size` | int32 | 0 | Measure a shrunk copy: every `bin-size` × `bin-size` block becomes one pixel. 0 shrinks only what needs shrinking. Everything reported stays in **your** image’s units. |
| `input/histogram-bins` | int32 | 256 | How finely `output/histogram` counts grey levels, 2 to 256. |

> [!NOTE]
> `bin-size` and `histogram-bins` are different knobs. `bin-size` shrinks the image the analysis measures, and wants a small number. `histogram-bins` only decides how the grey levels are bucketed, and 256 — one bucket per level — is usually right.

## What it reports

`output/recommended-settings` is the practical one: a list of `node=value` lines, relative to a module’s `detect-area/input/`, holding the level to commission, which end is the part, and whether a region has to be measured as the shape its outline encloses. Nothing is written for you — read them and set them deliberately.

`output/histogram` is how you check that advice. A fixed level wants to sit in the valley between the part’s hump and the background’s, and a single suggested number cannot show you whether there is one valley, two, or none at all. It is counted on the cropped image at full size, before any shrinking `bin-size` asked for, so it describes the picture rather than a resampling of it.

The rest describe the picture: `parts-are-dark`, `parts-touching`, `region-count`, `expected-region-count`, `illumination-spread`, `separability`, `feature-thickness` and `area-sensitivity`. `output/findings` says in words anything worth knowing, including the cases where no level will work.

## The one to read first

`area-sensitivity` answers "will a fixed level hold here?". It is how much the measured area moves when the threshold moves one grey level — **smaller is better**, and there is nothing to aim for below `0`.

| Value | What it means |
| --- | --- |
| `0.006` | A hard edge. The threshold sits in an empty valley; a fixed level is safe. |
| `0.01` | Still comfortable. |
| **`> 0.05`** | **Brittle.** One grey level costs 5 % of the reading. A fixed level is **not** a safe thing to commission here, and the application will say so in `output/findings`. |
| `0.15` | A picture that will not hold still at all. |

The arithmetic that matters is `area-sensitivity × drift in grey levels = fractional error`. At `0.05`, a lamp that ages ten grey levels over a shift moves your reading by half.

### It only costs you if something moves

A high value under a **steady** lamp is a constant offset: it calibrates out of an absolute reading and cancels entirely when you compare one part against another. It bites when the lighting or the threshold moves. So read this number together with how stable your cell actually is.

### Fixing a brittle picture

Nothing in `detect-area/input/` fixes it. This application offers one thresholding method, `FIXED`, so there is no swept or adaptive level to hide behind — a brittle picture is fixed at the camera.

Sensitivity is roughly `perimeter × edge-ramp-width / (contrast × area)`, which gives three levers. Work down the table:

| Lever | What raises the number | What to do |
| --- | --- | --- |
| **Edge softness** | Defocus, motion blur, sensor noise at high gain. Usually the biggest cause, and the one least suspected — the same scene defocused, with the lighting untouched, more than doubles this number. | Refocus. Shorten the exposure or steady the part to kill motion blur. Drop the gain and add light instead. Better optics. |
| **Contrast** | A narrow grey gap between part and background, so the edge transition is spread thin. | Lighting: backlight, change the angle, add a diffuser or a polariser, change the background. |
| **Feature size** | Thin or intricate parts — a lot of perimeter for very little area. Inherent to the part, not to your setup. | More pixels on the part: magnification, a closer working distance, or a higher resolution sensor. |

### Which lever is yours

Do not guess — the other outputs name it, and they outrank each other in this order:

1. `illumination-spread`, against the part-to-background gap. If the light varies more than about a third of that gap, uneven lighting is the real problem and no single level fits the frame at all. Fix this first.
2. `feature-thickness`. Below about 8 px the features are simply fine, and no amount of lamp tuning changes that — you need more pixels on the part.
3. Only then is it edge softness or contrast.

`output/findings` says which of the three it hit, in words, most important first.

# Tuning the Detection – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html

The defaults find **something** in most images. This page is how to make them find the right thing.

## The settings that matter

Only three, which is much of the appeal:

- **`method-specific/fixed/level`:** The brightness a pixel must exceed to count as part of a region. Commission it with [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html) rather than by guessing - it suggests a level and shows you the histogram the level has to sit in.
- **`detect-dark`:** Turn on when the parts are darker than the background.
- **`fill-holes`:** Turn on to measure a region as the shape its outline encloses. A washer measures as a ring with this off and as a disc with it on, and both are true answers.

There is no area window here. Every region is reported, and dropping the ones too small or too large to be a part is done where the result is read - only there is it known what a part is.

## Preprocessing

Try `preprocess/method` when regions have soft or noisy edges. `LOG` and `DOG` both emphasise features of a particular size - set the sigmas to roughly the size of what you are looking for - and `DOH` responds to blob-like structure. All three normalise their output, so the intensity thresholds above may need revisiting after enabling one.

## When no level works

If the reading will not settle, check `system/analyse-scene/output/area-sensitivity` before touching the settings. Above `0.05` the picture is brittle — one grey level costs 5 % of the measured area — and no value in `input/` repairs that. It is fixed at the camera: sharper edges, more contrast, or more pixels on the part. See [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html) for which of the three it is.

## Speed

In order of effect:

1. **Restrict the area** with `input/crop`.
2. **Raise the level** so sensor noise and dust stop crossing the threshold at all. That is cheaper than reporting those regions and discarding them afterwards.

# Module Management – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html

A **module** is one configured instance of the application. It owns the detection operation, with its own settings and results:

```
hdvisionsystems/lumiscan-area-detector/<module-id>/detect-area/...
```

Modules can be created and removed while the application runs. A fresh installation serves one module, named `module-1`.

> [!IMPORTANT]
> **On ctrlX OS, one licence covers ten modules.** The eleventh module acquires a second licence of the same key, and a module is refused with status `-11` when no licence on the device covers it.

The management node sits outside the modules:

```
hdvisionsystems/lumiscan-area-detector/system/
```

## Nodes

| Node | Type | Description |
| --- | --- | --- |
| `modules` | string array | The modules that currently exist |
| `create-module/execute` | method | Create a module and its node subtree |
| `create-module/input/module-id` | string | Name of the module to create. Lower case letters, digits, `-` and `_` only; must not be `system` and must not already exist |
| `remove-module/execute` | method | Remove a module and its node subtree |
| `remove-module/input/module-id` | string | Name of the module to remove |
| `save-current-modules/execute` | method | Persist the module list, so the same modules are recreated on the next start |
| `save-module-inputs/execute` | method | Persist one module’s settings |
| `save-module-inputs/input/module-id` | string | Name of the module whose settings to save |

Every method also has `output/status-code` and `output/status-text`. How these modules compare with those of the other LumiScan apps is described in [Settings, Modules and Restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html#registry-apps).

## Creating a module

1. Set `system/create-module/input/module-id` to the new name
2. Write to `system/create-module/execute`
3. Check `system/create-module/output/status-code` is `1`

The module is live at once, with default settings, and appears in `system/modules`. It is **not** permanent until the module list is saved.

Removing a module is the mirror image, through `remove-module`. A module is refused with `-1` (busy) while one of its own operations is running, rather than having its nodes destroyed mid-execution.

> [!NOTE]
> A module created now is a **new** module: it starts with the default input values, even if a module of that name existed before and its settings were saved. Those settings stay on disk until the removal is made permanent - `save-current-modules` deletes the saved inputs of every module the new list no longer names, because until the list is written a removal is not permanent and a restart brings the module back with its settings intact.

## Saving

Two things are saved separately, and both must be saved to survive a restart:

- **the module list** - `save-current-modules`, so the same modules are recreated;
- **each module’s settings** - `save-module-inputs`, once per module.

To save a module’s settings:

1. Set `system/save-module-inputs/input/module-id`
2. Write to `system/save-module-inputs/execute`
3. Check `system/save-module-inputs/output/status-code` is `1`

Every input of that module is written to the application configuration directory and restored on the next start. Results are not saved - they are produced by the next run.

A setting whose node no longer exists after a software update is skipped with a log entry, so an older configuration never prevents the application from starting.

## Why the address contains a module even with one module

The `<module-id>` level is always present, so addresses do not change when a second module is added: a program written today against `module-1` keeps working. It also matches the path convention the other LumiScan applications document.

## What is shared between modules

Modules are entirely independent: each has its own camera, its own detection settings and its own results, and the application holds no shared state for them to contend over. Detection needs no stored reference image, so there is nothing application-wide to configure.

# Data Layer Reference – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html

Every address below is relative to

```
hdvisionsystems/lumiscan-area-detector/
```

## Data Layer {#data-layer}

LumiScan Area Detector offers its functions on the Data Layer under `hdvisionsystems/lumiscan-area-detector`.

On ctrlX OS (ctrlX CORE or ctrlX IPC), LumiScan Area Detector uses the [ctrlX Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

On a PC with Windows 11 or Ubuntu 24.04, LumiScan Area Detector uses [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

The node addresses, types and call patterns are the same on both. LumiScan Area Detector offers:

- [execute methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html)
- a [stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) subscription to one source (experimental)

How addresses are built, how to call functions, the status codes and the tools are described in [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html).

## Application-wide nodes

| Address | Type | Access | Description |
| --- | --- | --- | --- |
| `system/modules` | string[] | read | The modules that exist right now |
| `system/create-module/execute` | method | write | Add a module |
| `system/create-module/input/module-id` | string | read/write | Name for the new module |
| `system/remove-module/execute` | method | write | Remove a module |
| `system/remove-module/input/module-id` | string | read/write | Module to remove |
| `system/save-current-modules/execute` | method | write | Persist the module list |
| `system/save-module-inputs/execute` | method | write | Persist one module’s settings |
| `system/save-module-inputs/input/module-id` | string | read/write | Module to save |
| `system/meta/subscription-schema` | string | read | What the node a module subscribes to must hold, as a JSON Schema (draft-04) of its JSON form: here a `stream_image`, the `frame` node of the stream folder, with `lineage` and `image`. The same for every module. Experimental |

Every method also serves `output/status-code` and `output/status-text`.

## Per-module nodes

All addresses below are under `<module-id>/detect-area/`.

### Used by every method

| Address | Type | Default | Description |
| --- | --- | --- | --- |
| `execute` | method | - | Run one detection |
| `input/input-image-address` | string | (empty) | Address of the image node to search |
| `input/method` | string | FIXED | `FIXED` is the only one this version offers; anything else is refused |
| `input/crop/startX` | uint16 | 0 | Left edge of the region to search |
| `input/crop/startY` | uint16 | 0 | Top edge |
| `input/crop/width` | uint16 | 0 | Width; 0 reaches the right edge |
| `input/crop/height` | uint16 | 0 | Height; 0 reaches the bottom edge |
| `input/preprocess/method` | string | NONE | `NONE`, `LOG`, `DOG` or `DOH` |
| `input/preprocess/log/sigma-x` | float64 | 1.0 | Must be > 0 |
| `input/preprocess/log/sigma-y` | float64 | 0.0 | 0 means equal to sigma-x |
| `input/preprocess/log/kernel-size-x` | uint32 | 0 | 0 computes it from the sigma, else odd |
| `input/preprocess/log/kernel-size-y` | uint32 | 0 | 0 computes it from the sigma, else odd |
| `input/preprocess/dog/sigma-first` | float64 | 1.0 | Must differ from sigma-second |
| `input/preprocess/dog/sigma-second` | float64 | 2.0 | Must differ from sigma-first |
| `input/preprocess/dog/kernel-size-x` | uint32 | 0 | 0 computes it from the sigma, else odd |
| `input/preprocess/dog/kernel-size-y` | uint32 | 0 | 0 computes it from the sigma, else odd |
| `input/preprocess/doh/kernel-size` | uint32 | 3 | Must be 1, 3, 5 or 7 |

### What counts as a region

| Address | Type | Default | Description |
| --- | --- | --- | --- |
| `input/detect-dark` | boolean | false | Dark regions on a light background |
| `input/connectivity` | int32 | 8 | 4 or 8; 8 joins diagonal neighbours |
| `input/fill-holes` | boolean | false | Measure a region as the shape its outline encloses |

There is no area window to configure. Every region the detector separated is reported, however small or large, and whether one of them is too small to be a part or too large to be a single one is a decision about the parts — which belongs to whoever reads `output/result`.

### The threshold

| Address | Type | Default | Description |
| --- | --- | --- | --- |
| `input/method-specific/fixed/level` | float64 | 128 | The level itself, 0-255 |

The folder keeps its name so the address survives if the methods that took their level from the image come back.

### Outputs

| Address | Type | Description |
| --- | --- | --- |
| `output/result` | flatbuffers | Regions of the last run |
| `output/status-code` | int16 | Outcome as a number |
| `output/status-text` | string | Outcome in words |
| `output/blob-labels/{data,width,height,pixel-type}` | image (`data` is `raw`) | Mono16, one region number per pixel; 0 is background |

The label image is whole-frame and holds the `blobs[].label` numbers, so a reported area can be traced to the pixels it was measured from. It is emptied when the next run starts. See [The Label Image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/the-label-image.html).

### Analysing a scene

Under `system/analyse-scene/` - it describes a picture, not a module. See [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html).

| Address | Type | Default | Description |
| --- | --- | --- | --- |
| `execute` | method | - | Measure the image and report what a fixed level would have to be |
| `input/input-image-address` | string | (empty) | The image node to analyse; its own, not a module’s |
| `input/crop/startX` .. `height` | uint16 | 0 | The region to analyse; all zero is the whole image |
| `input/bin-size` | int32 | 0 | Measure a shrunk copy; 0 shrinks only what needs it, 1 forces full size |
| `input/histogram-bins` | int32 | 256 | Buckets in `output/histogram`, 2-256. Not the same knob as `bin-size` |
| `output/histogram` | uint32[] | (empty) | Pixels per grey bucket, darkest first, at full size |
| `output/recommended-settings` | string[] | (empty) | `node=value` lines, relative to a module’s `detect-area/input/` |
| `output/findings` | string[] | (empty) | Why, in words, with the numbers in them |
| `output/parts-are-dark` | boolean | false | Whether the regions are darker than their background |
| `output/parts-touching` | boolean | false | Whether regions are really several parts stuck together |
| `output/region-count` | int32 | 0 | Regions found |
| `output/expected-region-count` | int32 | 0 | How many parts those regions look like they hold |
| `output/illumination-spread` | float64 | 0 | [grey levels] Background variation across the frame |
| `output/separability` | float64 | 0 | How cleanly the picture splits, 0 to 1 |
| `output/feature-thickness` | float64 | 0 | [pixel] Half the width of a typical feature |
| `output/area-sensitivity` | float64 | 0 | [per grey level] How much the area moves with the threshold. Smaller is better; above `0.05` a fixed level is not safe to commission |

## Per-module image stream nodes (experimental)

All addresses below are under `<module-id>/`, beside `detect-area/`. The stream searches each frame with the inputs of `detect-area`, all but `input/input-image-address`, and publishes the measurements only: there is no stream counterpart of `output/blob-labels`. See [Detecting Areas on an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html).

| Address | Type | Default | Description |
| --- | --- | --- | --- |
| `control/subscribe/input/enable` | boolean | as applied | Stream mode: `true` runs the stream, `false` stops it |
| `control/subscribe/input/address` | string | as applied | The one source, a camera’s stream folder, e.g. `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`. Another address replaces it |
| `control/subscribe/input/tag` | string | as applied | The tag on the module’s results: the module’s step in the lineage of each stream result carries it. Empty: the module id, e.g. `module-1`. A new tag keeps the source; the next result carries it |
| `control/subscribe/input/queue-size` | uint32 | as applied | Frames that may wait while one is searched, 1-64 |
| `control/subscribe/input/keep-latest-output` | boolean | as applied | `true` also writes each stream result to `detect-area/output/result` |
| `control/subscribe/execute` | method | - | Check the inputs of `control/subscribe` together, save them in `<module-id>.json` as `stream`, then apply them. Writing an input alone changes nothing |
| `control/unsubscribe/execute` | method | - | Drop the source named by `control/unsubscribe/input/address`, which ends stream mode; the tag stays. Saved in `<module-id>.json` like a subscribe |
| `control/unsubscribe/input/address` | string | (empty) | The source to drop, as `setting/stream/address` shows it |
| `setting/stream/{enable, address, tag, queue-size, keep-latest-output}` | as the inputs | `stream` in `<module-id>.json` | What `control/subscribe/execute` or `control/unsubscribe/execute` applied last. Read-only |
| `setting/settings-hash` | string | - | Hash of what the results are made with, 16 hex digits. Read-only |
| `control/subscribe/output/stream/active` | boolean | false | `true` while the stream runs |
| `control/subscribe/output/stream/result` | flatbuffers | empty | One `stream_areas` per searched frame. Subscribe to receive each one |
| `control/subscribe/output/stream/last-failure` | string | (empty) | Why the last frame that could not be searched failed, naming the source by its address |
| `control/subscribe/output/stream/statistics/elapsed-ms` | uint64 | 0 | Milliseconds since the stream started |
| `control/subscribe/output/stream/statistics/received-frames` | uint64 | 0 | Frames the subscription delivered |
| `control/subscribe/output/stream/statistics/processed-frames` | uint64 | 0 | Frames searched, each with a result |
| `control/subscribe/output/stream/statistics/skipped-frames` | uint64 | 0 | Frames pushed out of the queue, or waiting when the source was replaced or dropped |
| `control/subscribe/output/stream/statistics/failed-frames` | uint64 | 0 | Frames that could not be searched |
| `control/subscribe/output/stream/statistics/lost-frames` | uint64 | 0 | Frames lost before they arrived |
| `control/subscribe/output/stream/statistics/processing-us` | uint64 | 0 | Detection time of all searched frames, summed, microseconds |

The inputs of `control/subscribe` start with what is applied, and only `control/subscribe/execute` applies them. `control/subscribe/execute` is refused for stream mode without an address or a queue size outside 1-64, `control/unsubscribe/execute` for an address that is not the source. When `<module-id>.json` cannot be written, both answer `DL_CREATION_FAILED` (on a PC `CreationFailed`) and change nothing.

## The result flatbuffer

`output/result` carries `hdv.area_detect.Result`:

| Field | Type | Meaning |
| --- | --- | --- |
| `blobs` | Blob[] | All regions, sorted by area descending |
| `blobs[].x`, `.y` | float | [pixel] Centre of the region |
| `blobs[].area` | float | [pixel^2] Pixels the region covers, counted |
| `blobs[].label` | uint | Which region this is in `output/blob-labels`; 0 never occurs |
| `blobs[].bbox_x/y/width/height` | int | Tight box around the region |
| `blob_count` | uint | Number of regions |
| `total_area` | float | [pixel^2] Sum over all regions |
| `largest_index` | ulong | Index of the largest region |
| `largest_area` | float | [pixel^2] Its area |
| `image_width`, `image_height` | uint | The frame the coordinates are in |
| `preprocess_method` | string | NONE, LOG, DOG or DOH, as applied |
| `timestamp` | ulong | Microseconds since epoch |

`control/subscribe/output/stream/result` carries `hdv.stream.StreamAreas` (`stream_areas`, registered as `types/hdvisionsystems/lumiscan-area-detector/stream_areas`): `lineage`, where the frame came from, and `result`, the `hdv.area_detect.Result` above. Its `blobs[].label` has no label image to look up.

## Configuration file {#configuration-file}

The application settings file is `lumiscan-area-detector.json` in the application’s configuration directory:

| Platform | File |
| --- | --- |
| ctrlX OS | `<active solution>/lumiscan-area-detector/lumiscan-area-detector.json`, the active solution being `/var/snap/rexroth-solutions/common/solutions/activeConfiguration` |
| PC (Windows) | `%APP_RESOURCE_DIR%\etc\lumiscan-area-detector\lumiscan-area-detector.json`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-areadetect\etc\lumiscan-area-detector\lumiscan-area-detector.json` |

```json
{
    "system": { "logLevel": "INFO" },
    "modules": [ { "id": "module-1", "advanced": false } ]
}
```

`logLevel` accepts `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL` and `OFF`, read at startup. Each module’s saved settings are in `<module-id>.json` beside it, and so are its image stream’s mode, source, queue size and keep-latest-output, under `stream`.

## Starting from an Example (PC) {#generate-settings}

On a PC, the Area Detector writes an example of its settings into a folder of your choice, and ends without starting. On Windows:

```shell
lumiscan-areadetect --generate-settings C:\work\area-detector-settings
```

Without a folder (`-g` alone) it writes into the current folder. The example is the application settings file `lumiscan-area-detector.json`, which names the module `module-1`, and the module file `module-1.json` beside it: every input of `detect-area` with the value it has by default, except the image address, which is the Cam Driver’s `camera1`. Beside them, in `schemas/`, are the schemas the two files name in `"$schema"`: `lumiscan-area-detector.schema.json`, `lumiscan-area-detector-module.schema.json`, and `stream.schema.json` for the `stream` section of a module file. They describe every key the Area Detector reads - each input of `detect-area` with its type, its default and the range a run accepts - so an editor that understands JSON Schema can check the files and show what each value means. Copy the `schemas` folder along with the files: `system/save-module-inputs` keeps the `"$schema"` of a module file it saves. Existing files are never overwritten: when one of them is in the folder already, nothing is written and the Area Detector says which.

The Area Detector then names the folder it reads its settings from, on Windows by default `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-areadetect\etc\lumiscan-area-detector`. Edit the example, copy it there, and start the Area Detector. See also [Where the files are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#files).

# How To: Measure Part Area from a Camera Image – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/how-tos/measure-part-area-from-a-camera-image.html

Start to finish: get a real area measurement out of a live camera, and make it survive a restart.

## Before you start

- LumiScan Cam Driver is installed and publishing an image, for example at `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`.
- LumiScan Area Detector is installed, and `system/modules` lists `module-1`. On ctrlX OS it is also licensed, see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html).
- The parts are in front of the camera, in the lighting the installation will actually use.

## Step 1: see what is found with the defaults

```
module-1/detect-area/input/input-image-address = hdvisionsystems/lumiscan-cam-driver/camera1/output/image
write module-1/detect-area/execute
```

Check `output/status-code` is `1`, then read `output/result`. Look at `blob_count`: too many means noise is being counted, zero means nothing matched.

The areas are already real pixel counts. What the next step changes is how the regions are found.

## Step 2: commission the level

The one setting that decides whether this works is the brightness a pixel must exceed. Do not guess it - measure the picture:

```
system/analyse-scene/input/input-image-address = "hdvisionsystems/lumiscan-cam-driver/camera1/output/image"
write system/analyse-scene/execute
read  system/analyse-scene/output/recommended-settings
read  system/analyse-scene/output/histogram
```

`recommended-settings` gives you a level, which end is the part, and whether to fill holes. `histogram` is how you check it: the level wants to sit in the valley between the part’s hump and the background’s. Two humps with a gap means the picture separates cleanly; one hump means no level will save it and the lighting needs fixing instead.

Then set it on the module:

```
module-1/detect-area/input/method-specific/fixed/level = 128
write module-1/detect-area/execute
```

If the parts are darker than the background, add:

```
module-1/detect-area/input/detect-dark = true
```

## Step 3: stop counting noise

Look at the smallest entries in `blobs`. The app reports every region it separated - there is no area window to raise - so noise and dust are dealt with in one of two places:

- **At the level.** Raising `method-specific/fixed/level` until noise stops crossing the threshold is the better fix, because those regions then cost nothing to find.
- **In your control program.** Ignore any `blobs[]` entry whose `area` is below what a part can be. A quarter of the area of the smallest part you care about is a good starting point. That decision belongs to you: only you know what a part is.

## Step 4: check the number against something you know

Measure a part whose real area you know - or count its pixels once in an image viewer - and compare it against `blobs[0].area`. They should agree closely. If the measurement is consistently low, the threshold is cutting into the part: lower `method-specific/fixed/level`, and try `detect-dark` if the part is the darker of the two.

## Step 5: make it permanent

```
system/save-module-inputs/input/module-id = module-1
write system/save-module-inputs/execute
write system/save-current-modules/execute
```

Both should report `1`. The module and its settings now survive a restart.

## Step 6: run it from a control program

Per cycle:

1. Write to `module-1/detect-area/execute`.
2. Read `module-1/detect-area/output/status-code`.
3. If negative, the run failed - read `output/status-text` and do not use the result.
4. If `1`, read `output/result` and act on `total_area`, or on `blob_count` for a presence check.

Read the outputs **before** triggering the next `execute`: a run empties them as it starts.

## If the numbers look wrong

Problems are described step by step in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html):

- [The measured area is larger or smaller than the part](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-area-wrong) - much larger, consistently short, or a part with a hole
- [Many tiny regions are reported](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-tiny-regions)
- [One part is reported as several regions](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-part-split)
- [Nothing is found, or the result is empty](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-nothing-found)
- [The reading drifts with the lighting, or no level works](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-reading-drifts)

# FAQ – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/faq.html

Short answers to common questions about LumiScan Area Detector. Each entry links to the page with the details.

> [!TIP]
> Each entry has a fixed anchor (for example `#faq-pixel-formats`). Problems, error messages and status codes are described step by step in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html).

## Requirements and setup

### Which image source does the Area Detector need? {#faq-image-source}

- **Answer:** The application does not talk to a camera itself. It reads the image node of another application that runs on the **same device** - the same ctrlX CORE or ctrlX IPC, or the same PC (remote Data Layer access is not supported), normally LumiScan Cam Driver, for example `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`. Any application works if its image node provides `data` (raw, uncompressed uint8 pixel data), `width`, `height` and `pixel-type` (GenICam pixel format name). No reference picture is needed.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html), [Description](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/description.html)

### Which pixel formats are supported? {#faq-pixel-formats}

- **Answer:** `Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `BayerGR8`, `BayerGR12`, `BayerRG8` and `BayerRG12`. Bayer images are converted to colour and 12-bit images are scaled down to 8 bit before detection, so a threshold tuned on one format still applies to another. Any other pixel format is rejected with status code `-3`.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html)

## Detecting and measuring

### How do I run a detection and read the result? {#faq-first-run}

- **Answer:** Set `<module>/detect-area/input/input-image-address`, write to `<module>/detect-area/execute` (a blocking call) and check that `output/status-code` is `1`. Then read `output/result`: `blobs` is sorted by area, so `blobs[0]` is the largest; each blob has its centre `x`, `y`, its `area` in pixels (counted, never derived from a fitted shape), its `label` and a bounding box. `blob_count` gives the number of regions and `total_area` the sum, which is usually the number to act on for coverage, contamination and fill checks.
- **More:** [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html), [How To: Measure Part Area from a Camera Image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/how-tos/measure-part-area-from-a-camera-image.html)

### How do I find the right threshold level? {#faq-commission-level}

- **Answer:** Measure the picture instead of guessing. `FIXED` is the only `input/method` in this version; anything else is refused.
  - Set `system/analyse-scene/input/input-image-address` and write to `system/analyse-scene/execute`.
  - Read `output/recommended-settings`: `node=value` lines relative to a module’s `detect-area/input/`, holding the level, which end is the part and whether to fill holes. Nothing is written for you.
  - Check the advice with `output/histogram`: the level should sit in the valley between the part’s hump and the background’s. One hump means no level will work and the lighting needs fixing.
  - Set `<module>/detect-area/input/method-specific/fixed/level` (0-255, default `128`).
- **More:** [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html), [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html)

### Which preprocessing filters are there, and what do they need? {#faq-preprocessing}

- **Answer:** `input/preprocess/method` applies one filter before detection: `NONE` (default), `LOG` (Laplacian of Gaussian), `DOG` (Difference of Gaussians; `sigma-first` must differ from `sigma-second`) or `DOH` (Determinant of Hessian; `kernel-size` must be 1, 3, 5 or 7). Only the chosen method’s parameters are read and validated. All three normalise their output, so the threshold level may need revisiting after enabling one.
- **More:** [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html), [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html)

### How do I find the pixels belonging to a reported region? {#faq-label-image}

- **Answer:** Every run publishes `output/blob-labels`, an ordinary image node (`data`, `width`, `height`, `pixel-type`) in `Mono16`, with one region number per pixel and `0` for background. The numbers are the `blobs[].label` values in `output/result`, so all pixels holding a blob’s label are that region; a binary mask is `labels > 0`. The image is whole frame, at the size of the input image, and labels are not renumbered. It is emptied when the next run starts.
- **More:** [The Label Image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/the-label-image.html)

### How do I restrict the search or make it faster? {#faq-crop-speed}

- **Answer:** Set `input/crop/` (`startX`, `startY`, `width`, `height`); a zero width or height reaches the right or bottom edge, so all zero searches the whole image. A region reaching past an edge is refused rather than trimmed, naming the input and the limit it broke. For speed, restrict the area first, then raise the level so noise and dust stop crossing the threshold.
- **More:** [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html), [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html)

### How do I detect areas on every frame of a camera stream? {#faq-stream}

- **Answer:** Subscribe a module to the Cam Driver’s stream (experimental): write the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`, to `<module>/control/subscribe/input/address`, set `control/subscribe/input/enable` to `true` and write to `control/subscribe/execute`. Each frame is searched with the inputs of `detect-area`, and one result per frame is published on `control/subscribe/output/stream/result`. The label image is not streamed. To read the latest result as a plain `detect-area/output/result`, set `control/subscribe/input/keep-latest-output` to `true`.
- **More:** [Detecting Areas on an Image Stream](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html), [Streams](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html)

## Status codes and errors

### How do I know whether a detection worked, and where is the reason for a failure? {#faq-status-codes}

- **Answer:** Check the sign of `output/status-code`: greater than 0 is success, `0` means the operation has not run since the application started, less than 0 means it failed and produced nothing; do not use the result then. The reason is on `output/status-text`. A failed write to `execute` answers only with a status code (over REST, a bare `400`), so read `output/status-text` afterwards; the text is also in the application log: on ctrlX OS in the ctrlX Logbook or `journalctl`, on a PC in the application’s console output.
- **More:** [Execute a Method](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execute-a-method.html), [Execution Status](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html)

## Troubleshooting {#troubleshooting}

Problems and error messages are described step by step in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html):

- [Status code `-1` (busy)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-status-minus-1)
- [Status code `-2` (invalid input)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-status-minus-2)
- [Status code `-3` (image read failed)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-status-minus-3)
- [The crop region does not fit the image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-crop-does-not-fit)
- [Status code `-6` (write failed)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-status-minus-6)
- [Nothing is found, or the result is empty](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-nothing-found)
- [The measured area is larger or smaller than the part](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-area-wrong)
- [Many tiny regions are reported](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-tiny-regions)
- [One part is reported as several regions](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-part-split)
- [The reading drifts with the lighting, or no level works](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-reading-drifts)
- [`output/result` is empty although the detection worked a moment ago](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-result-empty-next-run)
- [The image stream delivers no results](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-stream-no-results)
- [My settings or modules are gone after a restart](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-settings-lost)
- [The application stops shortly after starting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-app-stops-after-start)
- [Status code `-11` (licence unavailable)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-licence-unavailable)

## Modules, licensing and support

### Where are the settings files? {#faq-settings-files}

- **Answer:** In the application’s configuration directory, `lumiscan-area-detector/`: the application settings file `lumiscan-area-detector.json` and one `<module-id>.json` per saved module.
  - On ctrlX OS: in the active solution, `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-area-detector`.
  - On a PC (Windows): `%APP_RESOURCE_DIR%\etc\lumiscan-area-detector`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-areadetect\etc\lumiscan-area-detector`.
  - On a PC, `lumiscan-areadetect --generate-settings <folder>` writes an example of both files, with their JSON schemas, into a folder of your choice.
- **More:** [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html#configuration-file), [Where the files are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#files)

### Which licence do I need, and how many modules does it cover? {#faq-licence}

- **Answer:** One licence covers ten modules; the eleventh module acquires a second licence of the same key, and a module is refused with status `-11` when no licence on the device covers it. Purchase routes:
  - Bought from HD Vision Systems: the licence is on a LumiScan Key (Windows 11 or Ubuntu 24.04). One LumiScan Key is needed per device running the software at the same time; keys can be exchanged between devices.
  - Bought in the ctrlX Store for Windows 11: ctrlX WORKS plus a LumiScan Key.
  - Bought in the ctrlX Store for ctrlX OS (ctrlX CORE or IPC): a ctrlX licence, no key.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html#licence), [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html), [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

### Where can I find more answers or get support? {#faq-support}

- **Answer:** See the site-wide [LumiScan FAQ](https://docs.hdvisionsystems.com/en/faq.html). Contact HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905; for licences, [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).
- **More:** [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

# Troubleshooting – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html

This page describes problems and error messages of LumiScan Area Detector, grouped by category. Start with the [general checks](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#general-checks), then find your symptom below: each problem lists its symptoms, the possible causes, a diagnostic procedure and the resolution. Problems of the Data Layer itself are described in [Data Layer troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html), licence problems in [Licensing troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/troubleshooting.html).

## General checks {#general-checks}

1. **Check the status code.** Read `output/status-code` of the operation that failed. Expected: `1`. A value greater than 0 means success, `0` means the operation has not run since the application started, and a value less than 0 means it failed and produced nothing; do not use the result then. The codes are listed in [Execution Status](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html).
2. **Read the status text.** Read `output/status-text` of the same operation. It starts with `ok:` or `error:` and names the offending value when there is one. A failed write to `execute` answers with a status code only (over REST, a bare `400`), so the reason is only on `output/status-text`.
3. **Read the application log.** It holds the same text, with one warning line for each invalid input: on ctrlX OS from the ctrlX Logbook or `journalctl`, on a PC from the application’s console output. How much is logged is set with `logLevel` in the `system` block of `lumiscan-area-detector.json` (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL` or `OFF`). It is read at startup, so restart the application after you change it. See [Configuration file](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html#configuration-file).
4. **Check the image source.** The camera application, normally LumiScan Cam Driver, must run on the **same device** - the same ctrlX CORE or ctrlX IPC, or the same PC - and must have captured an image. Remote Data Layer access is not supported. Expected: the node named in `input/input-image-address` provides `data`, `width`, `height` and `pixel-type`.
5. **Check the order of the calls.** A module runs one operation at a time, and every run clears its outputs as it starts. Expected: your program waits for `execute` to return, reads the outputs, and only then triggers the next run.
6. **Check the licence (ctrlX OS).** Expected: the application keeps running after it starts. Without a licence it shuts down shortly after starting; see [Problem: The application stops shortly after starting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-app-stops-after-start).

The configuration directory holds `lumiscan-area-detector.json`, the module files `<module-id>.json` and `settings-history/`:

| Platform | Configuration directory |
| --- | --- |
| ctrlX OS | `/var/snap/rexroth-solutions/common/solutions/activeConfiguration/lumiscan-area-detector`, part of the active solution |
| PC (Windows) | `%APP_RESOURCE_DIR%\etc\lumiscan-area-detector`; without `APP_RESOURCE_DIR`, `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-areadetect\etc\lumiscan-area-detector` |

## Status codes and error messages {#ts-status-codes}

### Problem: Status code `-1` (busy) {#faq-status-minus-1}

**Symptoms**

`output/status-code` of `detect-area` is `-1`. The write to `execute` answers `DL_TOO_MANY_OPERATIONS` (on a PC `TooManyOperations`). Nothing was done, and `output/result` and `output/blob-labels` keep their values. With a camera streaming, this happens often. `system/remove-module` can answer `-1` (busy) as well.

**Possible causes**

- Another operation of the same module was still running. The call is not queued; it returns at once and does nothing.
- The module’s image stream is searching a frame. The stream and `detect-area` never run at the same time on one module.

**Diagnostic procedure**

1. Check in your program whether it writes to `execute` of the same module again before the previous write has returned. Expected: one call per module at a time.
2. Read `<module-id>/control/subscribe/output/stream/active`. `true` means that the stream of this module runs.

**Resolution**

- **If another operation was still running:** wait for the running `execute` to return, then call the method again. The lock is per module, so other modules are not held up. `system/analyse-scene` has its own lock and does not block detection.

- **If the stream of the module runs:**

  a. Stop the stream before you call the method: set `control/subscribe/input/enable` to `false` and write to `control/subscribe/execute`. Or call the method again.

  b. To read the latest result of the stream instead, set `control/subscribe/input/keep-latest-output` to `true` and read `detect-area/output/result`.

- **If `system/remove-module` answers busy:** stop the stream of the module first. Removing a module stops its stream.

See [Execute a Method](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execute-a-method.html) and [detect-area while the stream runs](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#while-streaming).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the module id, the answer of the write to `execute` and the value of `control/subscribe/output/stream/active`.

### Problem: Status code `-2` (invalid input) {#ts-status-minus-2}

**Symptoms**

`output/status-code` of `detect-area` or `system/analyse-scene` is `-2`. `output/status-text` starts with `error:` and names the offending value. When several inputs are wrong, each one gets its own warning line in the log.

**Possible causes**

- A required input is empty.
- `input/method` is not `FIXED`. `FIXED` is the only method this version offers; anything else is refused.
- `input/preprocess/method` is unknown. It accepts `NONE`, `LOG`, `DOG` and `DOH`.
- A parameter is outside its range, for example `input/method-specific/fixed/level` outside 0-255, `input/preprocess/dog/sigma-first` equal to `sigma-second`, `input/preprocess/doh/kernel-size` other than 1, 3, 5 or 7, or `system/analyse-scene/input/histogram-bins` outside 2-256. Only the chosen preprocessing method’s parameters are validated.
- The image address points at this application itself.

**Diagnostic procedure**

1. Read `output/status-text` of the operation. Expected: it names the offending input and its value.
2. Read the application log. Each invalid input has its own warning line.
3. Compare the inputs with the ranges in the [Data Layer Reference](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/datalayer-reference.html).

**Resolution**

- **If a required input is empty:** set it.
- **If `input/method` is not `FIXED`:** set it to `FIXED`.
- **If `input/preprocess/method` is unknown:** set it to `NONE`, `LOG`, `DOG` or `DOH`.
- **If a parameter is outside its range:** correct it to a value inside the range given in the Data Layer Reference.
- **If the image address points at this application:** set `input/input-image-address` to the image node of the camera application, for example `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`.

Then run the operation again. Expected: `output/status-code` is `1`. See [Execution Status](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execution-status.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the content of `output/status-text`.

### Problem: Status code `-3` (image read failed) {#faq-status-minus-3}

**Symptoms**

`output/status-code` of `detect-area` or `system/analyse-scene` is `-3`.

**Possible causes**

- The camera application is not running, or it runs on another device.
- The camera application has not captured an image yet.
- The address in `input/input-image-address` is wrong.
- The image node at the address is missing, empty or inconsistent.
- The image uses an unsupported pixel format. Supported are `Mono8`, `Mono12`, `RGB8`, `RGB12`, `BGR8`, `BGR12`, `BayerGR8`, `BayerGR12`, `BayerRG8` and `BayerRG12`.

**Diagnostic procedure**

1. Check that the camera application, normally LumiScan Cam Driver, runs on the same device. Expected: it runs on the same ctrlX CORE or ctrlX IPC, or on the same PC.
2. Compare `input/input-image-address` with the address of the camera’s image node, for example `hdvisionsystems/lumiscan-cam-driver/camera1/output/image`. Expected: identical. `system/analyse-scene` has its own address node, not a module’s.
3. Read `width`, `height` and `pixel-type` of the image node. Expected: values greater than 0, and a `pixel-type` from the list above.

**Resolution**

- **If the camera application is not running:** start it on the same device and capture an image.
- **If no image has been captured yet:** capture an image in the camera application.
- **If the address is wrong:** correct `input/input-image-address`.
- **If the pixel format is not supported:** use one of the supported pixel formats, see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html).

Then run the operation again. Expected: `output/status-code` is `1`.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the content of `output/status-text`, the image address and the `pixel-type` of the image node.

### Problem: The crop region does not fit the image {#ts-crop-does-not-fit}

**Symptoms**

`detect-area` fails with a negative status code, and `output/status-text` names the input and the limit it broke, for example:

```
error: crop/startX + crop/width (100 + 900 = 1000) exceeds the image width 640
```

In the image stream, the frame fails, and `control/subscribe/output/stream/last-failure` names a crop region that does not fit the frame.

**Possible causes**

- The region reaches past an edge of the image. A region reaching past an edge is refused rather than trimmed.

**Diagnostic procedure**

1. Read the image size from the message, or `width` and `height` of the image node.
2. Add `input/crop/startX` and `input/crop/width`, and `input/crop/startY` and `input/crop/height`. Expected: the sums are not larger than the image width and the image height.

**Resolution**

- Correct `input/crop/startX`, `startY`, `width` or `height`, so that the region fits the image. A zero width or height reaches the right or bottom edge, so all zero searches the whole image.

Then run `detect-area` again. Expected: `output/status-code` is `1`. See [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the content of `output/status-text` and the four `input/crop/` values.

### Problem: Status code `-6` (write failed) {#ts-status-minus-6}

**Symptoms**

`output/status-code` of `system/save-module-inputs` is `-6`.

**Possible causes**

- A file could not be written - usually a permission problem or a full disk.

**Diagnostic procedure**

1. Read `output/status-text` of the operation. Expected: it names the file that could not be written.
2. Read the application log at the time of the call.
3. Check the configuration directory (see [General checks](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#general-checks)). Expected: it exists and the application can write to it.

**Resolution**

- **If it is a permission problem:** make the configuration directory writable for the application.
- **If the disk is full:** free disk space on the device.

Then run the operation again. Expected: `output/status-code` is `1`.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the content of `output/status-text`.

## Detection results {#ts-results}

### Problem: Nothing is found, or the result is empty {#faq-nothing-found}

**Symptoms**

`output/status-code` of `detect-area` is `1`, but `blobs` in `output/result` is empty and `blob_count` is `0`.

**Possible causes**

An empty `blobs` list with status code `1` means that no regions matched, nothing else. Every other reason a run could produce nothing is reported as a negative status code. If the parts are there:

- `input/detect-dark` does not match which end the parts are. Set it to `true` when the parts are darker than the background.
- The level `input/method-specific/fixed/level` is above every pixel in the part.

**Diagnostic procedure**

1. Read `output/status-code`. Expected: `1`. If it is negative, the run failed: read `output/status-text` and see the entries under [Status codes and error messages](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-status-codes).
2. Read `input/detect-dark`. Expected: `true` when the parts are darker than the background, `false` when they are brighter.
3. Run `system/analyse-scene` on the same image: set `system/analyse-scene/input/input-image-address` and write to `system/analyse-scene/execute`. Read `output/parts-are-dark` and `output/recommended-settings`. Expected: `input/detect-dark` and the level of the module match the advice.
4. Check the advice with `output/histogram`. Expected: the level sits in the valley between the part’s hump and the background’s.

**Resolution**

- **If `input/detect-dark` is wrong:** set it to `true` when the parts are darker than the background.
- **If the level is above every pixel in the part:** set `input/method-specific/fixed/level` to the level `output/recommended-settings` gives. Nothing is written for you.
- **If the histogram shows one hump:** no level will work; fix the lighting, see [Problem: The reading drifts with the lighting, or no level works](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-reading-drifts).

See [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html) and [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the inputs of `detect-area` and the outputs of `system/analyse-scene`.

### Problem: The measured area is larger or smaller than the part {#faq-area-wrong}

**Symptoms**

`blobs[0].area` or `total_area` differs from the real area of the part: much larger, consistently short, or a part with a hole measures as a ring.

**Possible causes**

- The area is much larger than the part: the level is letting background in.
- The area is consistently short: the level is trimming the part’s edge.
- `input/detect-dark` does not match which end the part is.
- The part has a hole, and `input/fill-holes` is off. A region is counted as the pixels that passed the threshold, so a hole is not counted unless `fill-holes` is set.

**Diagnostic procedure**

1. Measure a part whose real area you know, or count its pixels once in an image viewer, and compare it with `blobs[0].area`. Expected: they agree closely.
2. Look at the region in `output/blob-labels`: every pixel holding the region’s `blobs[].label` was counted. In the Cockpit, each region is tinted in its own colour over the camera picture.
3. Read `input/detect-dark` and `input/fill-holes`.

**Resolution**

- **If the level is letting background in:** check `input/detect-dark`, then commission the level again with `system/analyse-scene`, see [Problem: Nothing is found, or the result is empty](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#faq-nothing-found).
- **If the area is consistently short:** lower `input/method-specific/fixed/level`, and try `input/detect-dark` if the part is the darker of the two.
- **If a part with a hole measures as a ring:** turn on `input/fill-holes` to measure the shape its outline encloses. A washer then measures as a disc.

See [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html) and [How To: Measure Part Area from a Camera Image](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/how-tos/measure-part-area-from-a-camera-image.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the inputs of `detect-area`, `output/result` and the area you expected.

### Problem: Many tiny regions are reported {#faq-tiny-regions}

**Symptoms**

`blob_count` is much higher than the number of parts, and `blobs` holds many entries with a small `area`.

**Possible causes**

- Sensor noise and dust cross the threshold. The application reports every region it separated; there is no area window.

**Diagnostic procedure**

1. Look at the smallest entries in `blobs`. Expected: their `area` is far below the area of a part.
2. Look at those regions in `output/blob-labels`.

**Resolution**

Deal with noise and dust in one of two places:

- **At the level:** raise `input/method-specific/fixed/level` until the noise stops crossing the threshold. This is the better fix, because those regions then cost nothing to find.
- **In your control program:** ignore `blobs[]` entries whose `area` is below what a part can be. A quarter of the area of the smallest part you care about is a good starting point.

See [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the inputs of `detect-area` and `output/result`.

### Problem: One part is reported as several regions {#faq-part-split}

**Symptoms**

One part appears as several entries in `blobs`; in `output/blob-labels` its pixels carry several labels.

**Possible causes**

- The part is being split by a shadow or a highlight.

**Diagnostic procedure**

1. Look at the part in `output/blob-labels`. In the Cockpit, neighbouring regions come back as different colours.
2. Compare the split with the camera picture. Expected: a shadow or a highlight runs where the part is split.

**Resolution**

- Try preprocessing with `input/preprocess/method` (`LOG`, `DOG` or `DOH`), or `input/detect-dark`. All three filters normalise their output, so revisit the level after enabling one.

See [Detecting Areas](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/detecting-areas.html) and [Tuning the Detection](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/tuning-the-detection.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the inputs of `detect-area` and `output/result`.

### Problem: The reading drifts with the lighting, or no level works {#faq-reading-drifts}

**Symptoms**

The measured area changes when the lighting changes, does not settle, or no level separates the parts from the background.

**Possible causes**

- The picture is brittle: `system/analyse-scene/output/area-sensitivity` is above `0.05`, so one grey level costs 5 % of the measured area, and a fixed level is not safe to commission. No value in `detect-area/input/` repairs this; it is fixed at the camera.
- Uneven lighting: the light varies more than about a third of the part-to-background gap.
- The features are too fine: below about 8 px.
- The edges are soft (defocus, motion blur, sensor noise at high gain), or the contrast is low.

**Diagnostic procedure**

1. Run `system/analyse-scene` on the image and read `output/area-sensitivity`. Expected: well below `0.05` - `0.01` is still comfortable; above `0.05` the picture is brittle.
2. Read `output/findings`. It says in words which lever it hit, most important first.
3. Read `output/illumination-spread` against the part-to-background gap. Expected: less than about a third of the gap.
4. Read `output/feature-thickness`. Expected: about 8 px or more.

**Resolution**

Work through the levers in this order:

- **If the lighting is uneven:** fix the uneven lighting first. No single level fits the frame.
- **If the features are below about 8 px:** put more pixels on the part: magnification, a closer working distance, or a higher resolution sensor.
- **If the edges are soft:** refocus, shorten the exposure or steady the part, drop the gain and add light instead.
- **If the contrast is low:** change the lighting: backlight, another angle, a diffuser or a polariser, another background.

A high `area-sensitivity` under a steady lamp is a constant offset; it costs you only when the lighting or the threshold moves. See [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with all outputs of `system/analyse-scene`.

### Problem: `output/result` is empty although the detection worked a moment ago {#faq-result-empty-next-run}

**Symptoms**

A run produced regions, and shortly afterwards `output/result` (and `output/blob-labels`) is empty.

**Possible causes**

- The next run has started. Every run clears its own outputs as soon as it begins, before anything that can fail. A run that fails for any reason leaves them empty.
- A call refused with `-1` (busy) clears nothing, so this is not the cause when the second call was refused.

**Diagnostic procedure**

1. Check the order of the calls in your program. Expected: it reads `output/result` before it triggers the next `execute`.
2. Read `output/status-code` of the latest run. A negative value means that this run failed and left `output/result` empty.

**Resolution**

- **If the next run started too early:** wait for `execute` to return, read the outputs, and only then trigger the next run.
- **If the latest run failed:** follow the entry for its status code.

See [Execute a Method](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/execute-a-method.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the sequence of calls your program makes.

## Image stream (experimental) {#ts-stream}

### Problem: The image stream delivers no results {#ts-stream-no-results}

**Symptoms**

`control/subscribe/output/stream/active` stays `false`, no results arrive on `control/subscribe/output/stream/result`, or `control/subscribe/output/stream/statistics/failed-frames` grows.

**Possible causes**

- Only the inputs were written. Writing `control/subscribe/input/enable` alone starts nothing; `control/subscribe/execute` applies the inputs.
- `control/subscribe/execute` was refused (`DL_INVALID_VALUE`, on a PC `Rejected`): stream mode without an address, or a queue size outside `1` to `64`.
- The settings file `<module-id>.json` could not be written, for example because it is not valid JSON (`DL_CREATION_FAILED`, on a PC `CreationFailed`). Nothing changed.
- The stream of the Cam Driver does not run, so no frames arrive.
- The source cannot be subscribed to. The module tries it again every 5 seconds while the stream runs, and logs the first failure.
- Frames cannot be searched, for the reasons `detect-area` gives in its `status-text`.

**Diagnostic procedure**

1. Read `hdvisionsystems/lumiscan-cam-driver/<camera name>/control/publish/output/stream/active`. Expected: `true`.
2. Read `setting/stream/enable` and `setting/stream/address` of the module. Expected: `true` and the camera’s stream folder, for example `hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream`. They show what was applied last.
3. Check the answer of the write to `control/subscribe/execute`. Expected: `DL_OK` (on a PC `Ok`). These methods have no `status-text`; the reason for a refusal is in the application log.
4. Read `control/subscribe/output/stream/active`. Expected: `true`.
5. Read `received-frames`, `processed-frames` and `failed-frames` under `control/subscribe/output/stream/statistics/`. The first counter that does not grow shows where the chain stops.
6. If `failed-frames` grows, read `control/subscribe/output/stream/last-failure`. It says why the last frame failed, for example:
   ```
   a frame of 'hdvisionsystems/lumiscan-cam-driver/camera1/control/publish/output/stream' failed: invalid input: preprocess/method 'LAPLACE' is unknown; expected NONE, LOG, DOG or DOH
   ```

**Resolution**

- **If only the inputs were written:** set `control/subscribe/input/enable` to `true` and write to `control/subscribe/execute`. Wait until `control/subscribe/output/stream/active` is `true`.
- **If the call was refused (`DL_INVALID_VALUE`, `Rejected`):** write the camera’s stream folder to `control/subscribe/input/address`, set `control/subscribe/input/queue-size` to a value from `1` to `64`, and write to `control/subscribe/execute` again.
- **If the settings file could not be written (`DL_CREATION_FAILED`, `CreationFailed`):** make `<module-id>.json` in the configuration directory valid JSON again, without comments, then write to `control/subscribe/execute` again.
- **If the stream of the Cam Driver does not run:** start it. It is not kept after a restart: call its `control/publish/execute` with `enable` = `true` after every start, and connect the camera first. See [A stream delivers nothing](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html#stream-nothing).
- **If the source cannot be subscribed to:** check that `control/subscribe/input/address` is the camera’s stream folder and that the Cam Driver runs on the same device.
- **If frames fail:** correct the input that `last-failure` names, as for a single `detect-area` call.

The stream publishes the measurements only: `output/blob-labels` has no stream counterpart. See [Detecting Areas on an Image Stream (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the values under `setting/stream/`, the counters under `control/subscribe/output/stream/statistics/`, `control/subscribe/output/stream/last-failure` and the module’s `<module-id>.json`.

## Modules, settings and licensing {#ts-modules}

### Problem: My settings or modules are gone after a restart {#faq-settings-lost}

**Symptoms**

After a restart of the application, a module is missing from `system/modules`, or a module’s inputs are back at their defaults.

**Possible causes**

- The module list was not saved. Settings and new modules are live at once but not permanent until saved; the module list and each module’s settings are saved separately.
- The module’s settings were not saved.
- A save failed: `system/save-module-inputs` or `system/save-current-modules` did not report status `1`.
- `<module-id>.json` contains comments. The stream reads such a file, but the module’s inputs are then not restored at start; the log reports the file as unreadable.
- A setting whose node no longer exists after a software update is skipped, with a log entry.

**Diagnostic procedure**

1. Read `system/modules` after the restart. Expected: all your modules.
2. Check the configuration directory (see [General checks](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#general-checks)). Expected: `lumiscan-area-detector.json` names your modules, and there is a `<module-id>.json` for each module whose settings you saved.
3. Read the application log of the start. Expected: no module file reported as unreadable, no skipped setting.

**Resolution**

- **If the settings or the module list were not saved:**

  a. Set `system/save-module-inputs/input/module-id` (for example `module-1`) and write to `system/save-module-inputs/execute`. Do this for each module.

  b. Write to `system/save-current-modules/execute`.

  c. Check that both report status `1`.

- **If the module file contains comments:** remove them from `<module-id>.json`. Changes made to the file by hand take effect at the next start.

- **If a setting was skipped after an update:** set the input again and save the module’s settings.

The image stream’s mode and source are saved by `control/subscribe/execute` itself, in the module’s `<module-id>.json`; they come back only if the module list is saved too. See [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html) and [Kept in the settings file](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/processing-an-image-stream.html#saving).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with `lumiscan-area-detector.json` and the module files `<module-id>.json`.

### Problem: The application stops shortly after starting {#ts-app-stops-after-start}

**Symptoms**

On ctrlX OS, the application shuts down shortly after it starts. Its nodes under `hdvisionsystems/lumiscan-area-detector` disappear from the Data Layer.

**Possible causes**

- The licence is missing. The reason is written to the system log.
- The application needs more licences than are installed. One licence covers ten modules, see [Problem: Status code `-11` (licence unavailable)](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#ts-licence-unavailable).

**Diagnostic procedure**

1. Open the ctrlX OS system log (ctrlX Logbook or `journalctl`). Expected: it names the reason and the missing licence.
2. Compare the licence with the ctrlX licence of LumiScan Area Detector, `SWL-W-XCx-AxxDETECTxHDVSx-V1NN`. Expected: it is installed on the device on which the application runs.

**Resolution**

- **If the licence is missing:** install a valid licence on the device and start the application again. Expected: it keeps running, and its nodes are on the Data Layer.

See [Licence](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html#licence) and [My ctrlX app stops shortly after starting](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/troubleshooting.html#faq-ctrlx-app-stops).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with the lines of the system log that name the licence. For licences, contact [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

### Problem: Status code `-11` (licence unavailable) {#ts-licence-unavailable}

**Symptoms**

A module is refused with status code `-11`.

**Possible causes**

- No licence on the device covers the module. One licence covers ten modules; the eleventh module acquires a second licence of the same key.

**Diagnostic procedure**

1. Count the entries of `system/modules`. Expected: no more than ten modules for each licence on the device.
2. Read `output/status-text` of the operation that answered `-11`.

**Resolution**

- **If more modules exist than the licences cover:** remove the modules you do not need with `system/remove-module` and save the module list with `system/save-current-modules`, or obtain another licence.

See [Module Management](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/module-management.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#support-information) to support, together with `system/modules`. For licences, contact [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

## Information for support {#support-information}

If a problem persists, send this information to support:

- **Software version:** the version of LumiScan Area Detector you run. The files in `settings-history/` in the configuration directory record it as `software.version`.
- **Platform:** ctrlX OS (ctrlX CORE or ctrlX IPC) and its ctrlX OS version, or a PC with Windows 11 or Ubuntu 24.04. Also say where you bought the software: from HD Vision Systems or in the ctrlX Store.
- **Data Layer:** the ctrlX Data Layer (ctrlX OS) or LumiScan Keryx (PC). On a PC, also the Data Layer address the application uses.
- **Log:** the application log from the time of the error - on ctrlX OS from the ctrlX Logbook or `journalctl`, on a PC the application’s console output.
- **Time:** the date and time of the error.
- **Communication status:** `output/status-code` and `output/status-text` of the operation that failed, and the answer of the write to `execute` (for example `DL_TOO_MANY_OPERATIONS` or `TooManyOperations`).
- **Configuration files:** `lumiscan-area-detector.json`, the `<module-id>.json` of the module concerned and, for the image stream, the file in `settings-history/` that its settings hash names. Where they are is listed under [General checks](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html#general-checks).

Contact HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905; for licences, [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com). See also [Before you contact support](https://docs.hdvisionsystems.com/en/faq.html#faq-before-contacting-support) in the LumiScan FAQ.

# Release Notes: v1.1.0 (2026-08-09) – LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/release-notes/v1-1-0-2026-08-09.html

First functioning release of LumiScan Area Detector. Earlier versions registered the application’s Data Layer nodes but returned a fixed placeholder result, so nothing below was usable before.

## New

**Area detection.** `<module>/detect-area/execute` finds the regions in a camera image and reports each one’s area and position, along with the total area across them all. No reference picture is needed: you describe what counts as a region by how bright, how large and how round it is.

**Five ways of finding a region**, chosen by `input/method`. `CIRCLE` sweeps a range of intensity levels and keeps what looks like a blob at several of them, which holds up when the lighting does not; the other four threshold once and take every connected region, whatever its shape. All five report a measured pixel area.

**A choice of threshold when measuring**, `input/method-specific/corrected/min-level`. A local threshold follows uneven lighting and suits fine features; a global one takes a solid region whole, which is what measuring a solid part needs.

**Shape filters** - area, circularity, convexity and elongation - so only the regions of interest are reported, with the meaning of each explained on the node itself.

**Optional preprocessing** before detection: Laplacian of Gaussian, Difference of Gaussians or Determinant of Hessian.

**A region of interest per run**, `input/crop`, to restrict and speed up the search.

**Several modules**, each with its own settings and results, so one installation can watch several cameras. One license is valid for ten modules.

**The regions' shapes, when you ask for them.** `input/publish` adds outlines, simplified polygons and masks beside the measurements, each on its own Data Layer node. Empty by default, and then a run costs exactly what it did before. The whole-frame and per-region masks are ordinary image nodes, so another application reads one with the code it already has for a camera image. (Withdrawn in 1.2.0: a single label image replaced all of them.)

**A status on every operation**: `output/status-code` and `output/status-text`, where a negative code always means the run failed and produced nothing.

## Worth knowing

Every invalid input is reported at once, and each message names the **node** to change rather than an internal field name - `threshold/min (250) must not exceed threshold/max (220)`.

An empty result means no regions matched, and nothing else: every other reason a run could produce nothing is caught before detection and reported as a negative status code.

The shapes are deliberately not inside the result flatbuffer. Over the REST API a flatbuffer arrives as one JSON string with its numbers quoted, so an array of coordinates comes back as an array of strings - too slow to use. The result carries the per-region point counts that slice the published buffers instead.

When measuring solid parts, turn `input/method-specific/corrected/min-level` off. A local threshold compares a pixel against its surroundings, so the middle of a large solid region - where the surroundings are equally bright - drops out and the region is measured hollow. See [Analysing a Scene](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/analysing-a-scene.html).

# LumiScan Area Detector

URL: https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/index.html

|   |   |   |
| --- | --- | --- |
| ![Dark regions of different sizes on a light surface](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/_images/intro/step-1.svg)<br><br>**Point it at the scene.** No reference picture: say what counts as a region. | ![The regions outlined and labelled with their area in square pixels](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/_images/intro/step-2.svg)<br><br>**Every region is found and measured.** With its area and position in the image. | Example result<br><br><br><br><br><br><br>Regions<br>4<br><br><br>Total area<br>5 700 px²<br><br><br>Largest<br>2 760 px²<br><br>**Hand the result to your PLC.** Count, total area and largest region. |

LumiScan Area Detector finds regions in a camera image and reports how big each one is. It needs no reference picture: you describe what counts as a region, by brightness, dark or light, with or without holes, and it returns every region with its area and position plus the count and total area. Use it for counting parts, checking coverage or contamination and measuring fill levels, or for things with no fixed shape such as a spill, a scratch or a gap.

For licensing, see [Licence](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/lumiscan-area-detector/requirements.html#licence). Questions? See the [FAQ](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/faq.html). A problem or an error message? See [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-area-detector/1.2.0/troubleshooting.html).
