Cameras & sensorsHow-to

Read exposure time from frame metadata under auto exposure

Query the frame metadata support flag first, read the applied exposure time in microseconds from each frame, and fix the pipelines that never deliver it.

LumaSpec Vision10 min read Share on LinkedIn

On this page 9 sections
  1. 01What current exposure means once auto exposure runs
  2. 02What you need
  3. 03Read the applied exposure, step by step
  4. 04Worked example: exposure headroom on a 12 MP camera at 9 fps
  5. 05Register read or per-frame chunk: pick one deliberately
  6. 06When the readback never arrives
  7. 07Common mistakes
  8. 08The short version
  9. 09Questions

When auto exposure is running, the exposure value you set before enabling it is no longer the truth. The camera now picks the exposure itself, and the number worth logging is the one it actually applied to the frame you are holding. This guide shows the two ways to read that applied value on GigE Vision and USB3 Vision area scan cameras: the ExposureTime feature, which turns read-only and tracks the applied value, and per-frame chunk metadata such as ChunkExposureTime. You will check support before reading, take the value once per frame, prove the readback is live with a light step, and fix the cases where the metadata never arrives on a given PC — including depth and stereo cameras whose metadata rides on the operating system's capture pipeline.

What current exposure means once auto exposure runs

Machine-vision cameras expose their controls through GenICam. The auto mode lives in ExposureAuto, with the values Off, Once and Continuous on SFNC-conformant cameras. While Once or Continuous runs, ExposureTime becomes read-only and reports the exposure the camera actually used; that is the documented SFNC behavior, so a plain register read already returns the applied value, in microseconds on SFNC 2.0 cameras. Your old setpoint is out of the picture: writing ExposureTime while auto runs fails with an access error, which is the camera confirming the handover, not a fault.

The register has one weakness: frames are in flight. During a triggered burst, a register read can lag the newest buffer by a frame or two. When the value must belong to one specific image, enable chunk mode so every buffer carries ChunkExposureTime inside its payload. Both routes are standard GenICam; choosing between them is a scheduling question, not a hardware one. To steer the value rather than just watch it, you set the auto exposure brightness target for inspection or change the light — and if you also drive exposure by hand anywhere in the program, the guide on setting exposure time through a GenICam API covers the write side.

What you need

  • A GigE Vision or USB3 Vision camera with GenICam access — every area scan camera in the shop qualifies — plus its SDK or GenICam binding on your PC.
  • A camera feature viewer, so you can confirm the feature names and ExposureTime's declared unit before writing code.
  • For depth, stereo and ToF cameras that stream through the OS video-class stack: a capture pipeline that delivers metadata; the platform section below covers the checks.
  • Optionally, a dimmable light or LED driver, for the live test in the worked example.

Any current GigE Vision or USB3 Vision model exposes both routes through its feature map. The first card below runs the same 20 MP sensor over GigE, the second over USB 3.0, and the third is the camera used in the worked example:

Area scan camerasHikrobot MV-CS200-10GC 20 MP Area Scan Camera, GigE, IMX183, Color, BasicMV-CS200-10GC
Sensor format
1"
Lens mount
C-mount
$739.00View part
Area scan camerasHikrobot MV-CS200-10UM 20 MP Area Scan Camera, USB3.0, IMX183, 2nd Gen., MonoMV-CS200-10UM
Sensor format
1"
Lens mount
C-mount
$759.00View part
Area scan cameras12 MP GigE area scan camera, IMX226, 1/1.7" rolling shutter, 9 fps (LS-CMR-0053)LS-CMR-0053
Sensor format
1/1.7"
Lens mount
C-mount
$560.00View part

Read the applied exposure, step by step

  1. Inspect the feature map. In your camera viewer, confirm ExposureAuto and ExposureTime exist and note ExposureTime's declared unit. This is also where you check which chunk features your camera implements.
  2. Turn auto on. Set ExposureAuto to Continuous. From this moment the camera owns exposure: a write to ExposureTime returns an access error, which confirms the read-only state is active.
  3. Pick the route. For logging, trending and live dashboards, read the register (step 4). When each value must be paired with its own image — triggered bursts, offline audits — enable the per-frame chunk (step 5).
  4. Register route, once per frame. After each delivered buffer, read ExposureTime. Guard every read: check the feature is readable, treat a not-available result as a normal condition, count the miss and keep the last good value. Store the result as a float in microseconds.
  5. Chunk route, before streaming. Enable chunk mode and switch on the exposure-time chunk, then start the stream. After each buffer, read the chunk from the buffer itself; if the buffer does not carry it, fall back to step 4 and record the miss.
  6. Log value and frame together. Store the exposure next to the frame ID and timestamp so later analysis can pair them.
# Illustrative pseudocode for the GenICam route. ExposureAuto, ExposureTime,
# ChunkModeActive and ChunkExposureTime are standard SFNC feature names; the
# camera.* and frame.* helpers stand in for your SDK's own calls.
exposure_auto: str = camera.get_string_feature("ExposureAuto")   # "Off"
camera.set_string_feature("ExposureAuto", "Continuous")

exposure_us: float = 0.0    # applied exposure of the last frame, microseconds
misses: int = 0             # frames that delivered no value

def on_frame(frame) -> None:
    global exposure_us, misses
    if frame.has_chunk_data("ChunkExposureTime"):        # per-frame route
        exposure_us = frame.get_chunk_value("ChunkExposureTime")
    elif camera.is_feature_readable("ExposureTime"):     # register route
        exposure_us = camera.get_float_feature("ExposureTime")
    else:
        misses += 1   # metadata not delivered this frame; normal, log it

The test that proves this plumbing works is the light step in the worked example below: change the light, and the number must move with it. For checking what the camera reports frame by frame — gain as well as exposure — the guide on per-frame exposure and gain metadata is the follow-up.

Worked example: exposure headroom on a 12 MP camera at 9 fps

The example camera, printing 9 fps at full resolution:

Area scan cameras12 MP GigE area scan camera, IMX226, 1/1.7" rolling shutter, 9 fps (LS-CMR-0053)LS-CMR-0053
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
12 MP
$560.00View partBuild a system with it

Inputs. The camera runs 9 fps at full resolution (catalog). The light sits at 50% driver output and stays constant until the test. Auto gain is off, so gain cannot absorb a light change. After the auto settles — give it a few frames after any light step; the first-frame-dark guide shows why early frames mislead — the readback reports 30,000 µs. That readback is the illustrative input; the frame rate is the printed one.

Rule. At full frame rate a camera cannot expose longer than one frame period: t_frame = 1 / fps. With gain fixed and the brightness target fixed, applied exposure moves inversely to the light reaching the sensor — halve the light and the exposure must double to hold the same brightness.

Arithmetic.

t_frame = 1 / fps = 1 / 9 s = 0.111 s = 111,000 µs (rounded) live test: light 50% -> 25%, readback 30,000 µs -> 60,000 µs (60,000 / 30,000 = 2.0) headroom = 111,000 - 60,000 = 51,000 µs = 46% of the frame period light still buyable from exposure = 111,000 / 60,000 = 1.85x

Decision. At 54% of the frame period used (60,000 / 111,000), keep letting the auto stretch exposure: at 9 fps, exposure alone still covers a 1.85x drop in light. The threshold for this camera at this frame rate: once the readback passes about 100,000 µs — 90% of 111,000 µs — exposure can add under 11% more light (111,000 / 100,000 = 1.11). Past that point, add light or allowed gain — each doubling of linear gain is +6 dB — instead of waiting for exposure. If the scene needs more than 1.85x more light, size a light for it; frame rate will not pay for the difference. What moves the readback day to day: ambient light, part reflectivity and any gain limit you set — the readback is how you catch those changes without inspecting images.

Register read or per-frame chunk: pick one deliberately

ExposureTime register ChunkExposureTime
What you read Applied exposure of the most recently delivered frame, in microseconds The exposure embedded in that frame's own payload
Set-up None beyond auto running Chunk mode and the chunk enabled before the stream starts
Best for Continuous logging, dashboards, live control Triggered bursts, traceability records, offline audits
Weak point Lags in-flight frames by one or two during bursts An SDK build that silently strips payload data

Default to the register read: no set-up, and accurate enough at a steady frame rate. Move to the chunk when values must be paired with images — burst captures, where the lag the trigger call versus exposure time guide explains becomes real, or when logs must survive an audit. Both can run at once: enable the chunk, prefer it when present, fall back to the register.

When the readback never arrives

On GigE Vision and USB3 Vision cameras, chunk data travels inside the image payload, so no operating system code sits between camera and buffer. A missing chunk there is set-up: chunk mode left off, a feature name your camera does not implement, or an SDK too old to parse the payload. Updating the SDK restores delivery more often than any code change does.

Depth, stereo and ToF cameras are a different story. Many stream through the operating system's USB video-class pipeline, and per-frame metadata survives only if that pipeline delivers it. On Linux that takes a recent kernel, or the vendor's documented patched module package installed from the vendor's own repository; on Windows it takes Windows 10 or later with metadata support set up as the vendor documents. If the support flag reads false on one PC and true on another, the camera did not change — the platform did. Fix the platform before touching your code. The same logic runs across the 3D sensors range, and the ToF exposure and frame-rate trade-off guide takes the exposure behavior of that camera class further.

Common mistakes

  • Reading the pre-auto setpoint as the current value. Under auto it is stale; the applied value lives in ExposureTime or the chunk.
  • Unit slips. SFNC declares microseconds: a readback of 2,000 is 2 ms, not 2 s. Check the node's unit once per camera model.
  • Treating the access error on ExposureTime as a fault. While auto runs, the write is supposed to fail.
  • Expecting ExposureAuto set to Once to keep tracking. Once settles and stops; the flat readback after it is the final value, not a stuck pipeline.
  • Polling on a free-running timer instead of once per frame. Timer reads pair exposure values with the wrong images.
  • Attributing every brightness change to exposure. With auto gain enabled, gain shares the load — read Gain alongside exposure; the guide on auto exposure and auto gain on color cameras explains which pixels drive the decision.

The short version

  • Check support before you read; treat not-available as a counted miss, not a crash.
  • ExposureAuto to Continuous; take ExposureTime per frame in microseconds, or enable ChunkExposureTime when values must pair with images.
  • Prove the readback is live with a light step: halve the light, expect the value to double.
  • Headroom = frame period minus readback; once the readback passes about 90% of the frame period, exposure is out of room — add light or gain.
  • Metadata missing on one PC is a platform problem: kernel version, module package, SDK build or Windows set-up, in that order.

Shortlist cameras with the camera finder, then configure a camera set-up around your frame rate and exposure needs. If you want a second opinion on whether a specific model exposes these features, contact us — free expert support comes with every order, and more camera guides sit on the cameras topic page.

Questions

How do I pair an exposure value with one specific frame?

Enable chunk mode so the value travels inside the frame's own payload, and log it next to the frame ID your SDK reports. At a steady frame rate with continuous auto, a register read lags at most a frame or two, which is fine for trending. In a triggered burst the lag grows because several buffers sit in flight while the register holds only the latest applied value — that is the case the chunk exists for.

What unit does the exposure readback come back in?

GenICam's SFNC 2.0 declares ExposureTime in microseconds, so 30,000 means 30 ms and 2,000 means 2 ms. Older firmware may present the node without a declared unit, and pre-SFNC-2.0 stacks occasionally report milliseconds. Open the camera viewer once per model, read the node's unit string, and store every logged value with its unit — that removes the most common factor-of-1000 error in exposure logs.

Why does the metadata read work on one PC and fail on another with the same camera?

Delivery is a platform job. On depth and stereo cameras that stream through the OS video-class pipeline, a recent Linux kernel or the vendor's documented patched module package decides whether metadata arrives; on Windows it takes Windows 10 or later with metadata support set up as the vendor documents. An outdated SDK that cannot parse the payload produces the same symptom. Check the support flag first, then the SDK build, then the OS path.

Can I convert the exposure readback into an absolute light level?

Not from exposure time alone. Light at the sensor depends on scene radiance, lens f-number, gain and the sensor's own sensitivity, and those sensitivity figures come from an EMVA 1288 characterization of the sensor. Use the readback for relative work instead: trend it to catch ambient changes, compare parts across a shift, and alarm when the auto pins itself near its cap — that last case means the lighting budget is spent.