Cameras & sensorsTroubleshooting

Dark frames under auto exposure: wait for convergence

Frames captured before auto exposure settles come out dark. The frame count to expect at 6 fps, and a capture gate built on exposure and gain metadata.

LumaSpec Vision11 min read Share on LinkedIn

On this page 8 sections
  1. 01Why are some frames darker when auto exposure is on?
  2. 02How many frames does auto exposure need to converge?
  3. 03How do I know the auto exposure loop has settled?
  4. 04How do I stop capturing dark frames after startup or a scene change?
  5. 05Why do frames go dark again in the middle of a run?
  6. 06Should I cap auto exposure or fix exposure manually?
  7. 07Which checks separate convergence from other dark-frame causes?
  8. 08Questions

A run of intermittently dark frames usually has nothing to do with the lighting: the camera's exposure loop was still moving when you grabbed the image. Auto exposure is a feedback loop. After every power-up, job change or scene change it measures, steps and measures again, and any frame captured during the climb is underexposed by however far the loop still has to go. At low frame rates the climb lasts seconds, not milliseconds, so the dark frames land inside ordinary production captures. Below you get the settling count for your frame rate, a formula for the exact number, a metadata test that says when the loop has finished, and the decision between capped auto exposure and manual exposure for each case.

Why are some frames darker when auto exposure is on?

Your frames are dark because they were captured while the auto exposure loop was still stepping toward its brightness target: the loop needs several frames to settle after startup or a scene change, and every frame it captures inside that window is underexposed.

The loop works like this. Each frame, it measures the mean brightness of a chosen window in the image, compares that with a target — around half of full scale on most cameras, and settable on many, as Set an auto exposure brightness target for inspection covers — then moves exposure, or gain, one bounded step toward it. The step is bounded on purpose: an unbounded jump would make the image pump visibly between frames, so firmware climbs in limited increments and turns every change into a ramp over several frames.

Nothing is broken while the ramp runs. What breaks inspections is capturing inside it. A single-frame grab at 6 fps lands somewhere on the ramp, and where it lands decides whether the part passes. Two moments always produce the ramp: the first frames after streaming starts, and the frames after the scene's brightness changes.

How many frames does auto exposure need to converge?

Plan on 5–15 frames of settling after an abrupt scene change; at 6 fps that is 0.8–2.5 s of dark images. The count comes from the loop's per-frame step limit: exposure roughly doubles each frame until it reaches the target.

Model the loop as a bounded proportional step. If the scene needs E_target of exposure to hit the brightness target and the loop starts at E_start, and firmware lets exposure grow by a fraction k per frame — k = 1 means doubling — the count is:

n = ceil( ln(E_target / E_start) / ln(1 + k) ) t_settle ≈ n / frame rate

That is an estimate for a bounded-step loop: gain moves and measurement noise add one or two frames of trimming, so keep a frame of margin.

Worked example, at the 6 fps and 1280 × 720 of a typical low-rate inspection line:

  • Start exposure: E_start = 0.1 ms, a common power-on default for a bright scene.
  • Scene target: E_target = 16 ms. The frame period at 6 fps is 1/6 s = 166.7 ms, so 16 ms fits inside one frame.
  • Step: k = 1, doubling.
  • n = ceil(ln(160) / ln(2)) = ceil(5.08 / 0.693) = ceil(7.33) = 8 frames.

The ramp runs 0.2 → 0.4 → 0.8 → 1.6 → 3.2 → 6.4 → 12.8 → 16 ms, with the last step clamped at the target: 8 steps after the first frame. Add the trim frames and budget 9–10 frames, which at 6 fps is 9/6 ≈ 1.5 s of dark-or-changing images. If firmware limits the step to k = 0.5, the same gap needs ceil(5.08 / ln(1.5)) = ceil(5.08 / 0.405) = 13 frames, about 2.2 s at 6 fps. The 5–15 frame planning band covers a restart from a saved value at the low end and a cold start with a modest step at the high end.

One lever is yours: start closer to target. Starting at 8 ms instead of 0.1 ms turns the same scene into ceil(ln(2) / ln(2)) = 1 frame. Write the last converged exposure back before shutdown and the next start settles almost immediately.

How do I know the auto exposure loop has settled?

Most cameras give no ready flag for auto exposure, so read the exposure time and gain values the SDK reports with each frame and accept the first frame after two consecutive reads match; these values ride along as per-frame metadata on GigE Vision and USB3 Vision cameras.

Per-frame exposure and gain: verifying camera metadata shows how to confirm the values you read are live and not stale leftovers. The stability test is then short: the loop has stopped when the reported exposure time and gain hold still from one frame to the next. One identical pair can be a rounding coincidence; two in a row, with gain included, mean the loop has landed.

The variable names below are our own. Feed the read function whatever your SDK's per-frame exposure readout is:

exposure_prev_us: float = -1.0   # previous frame's exposure in µs, -1 = none yet
stable_reads: int = 0            # consecutive frames with matching values
for frame in stream:
    exposure_us: float = read_exposure_metadata(frame)   # e.g. 15840.0
    if exposure_prev_us >= 0.0 and abs(exposure_us - exposure_prev_us) <= 1.0:
        stable_reads = stable_reads + 1
    else:
        stable_reads = 0
    exposure_prev_us = exposure_us
    if stable_reads >= 1:
        accept frame    # two consecutive equal reads: the loop has settled

Prove it on your line: log the mean brightness of accepted frames across a hundred captures after a scene change. Accepted frames should sit within a few percent of target, and the ramp should appear only in the discarded frames. If the first frame after power-up is dark and stays dark, that is a different fault: First camera frame dark: exposure settling or light timing? separates exposure settling from a light-timing problem with a timing test.

How do I stop capturing dark frames after startup or a scene change?

Gate your capture on stability instead of time: discard frames until the reported exposure and gain stop changing, or if you must use a timer, discard the first 15 frames — about 2.5 s at 6 fps — after every enable, scene change or lighting change.

The metadata gate wins because the window's length moves with the gap the loop must close: a restart from a saved value converges in a frame or two, while a cold start after a lighting failure can take twenty. A fixed timer has to cover the worst case, so it wastes good frames whenever the camera starts near target. Keep the timer as the fallback, computed from the formula above, and re-arm the gate on every event that changes what the camera sees: streaming start, job load, a switch of the exposure measurement window, lights toggled, a new part family on the belt.

On a smart camera, the gate belongs in the inspection job's start condition, because there may be no PC in the loop to throw frames away for you.

Why do frames go dark again in the middle of a run?

Dark frames that return mid-run are a scene or lighting change re-triggering convergence: order of likelihood is a brightness shift inside the exposure measurement area, ambient light change, then mains flicker beating against the exposure time.

Work down that order:

  1. Part brightness changed. White parts leave, dark parts arrive, and the exposure the scene needs doubles or halves. The log shows a clean ramp to a new value that begins with the first changed part. When the measurement window itself follows a detection result, the loop can chase its own tail: Auto exposure ROI instability from detection feedback walks through that case.
  2. Ambient light changed. A door opened, sun reached the bench, ceiling banks switched. The ramp lines up with the wall-clock moment. Containment on the ambient side is in Ambient light variation in pick and place vision: control it.
  3. Mains flicker. Exposure competing with the 100 Hz or 120 Hz ripple of mains-powered lights produces periodic dips and banding, not a one-way ramp. Shift the exposure slightly and the bands move: Image brightness changes frame to frame: fix mains lighting flicker.
Exposure log pattern Likely cause Test that confirms it
One-way ramp, then flat Convergence after a change Expected behavior — gate on stability
Oscillation around one value Step too large: the loop hunts Values swing past the target both ways — cap exposure or narrow the window
Evenly spaced periodic dips Mains flicker Dips move when the exposure shifts
Dips tied to specific parts Part brightness inside the window Log part ID with exposure — ramps start with part changes

Should I cap auto exposure or fix exposure manually?

Fix the exposure manually when your lighting is fixed, and keep auto exposure with a capped maximum when lighting moves; a cap bounds both motion blur and the recovery time, because the loop then has a shorter gap to close and settles in fewer frames.

The decision per case:

  • Fixed light, fixed parts: manual exposure and manual gain, set once. The first frame after enable is already correct, so there is no settling window at all. Watch for slow drift from aging lamps or daylight — Camera image brightness drifts over time: turn every auto mode off explains why partial auto settings keep drifting.
  • Light or parts vary: auto exposure with the maximum exposure capped at what your motion allows. The cap is a camera setting, and setting it in the camera beats a tuning file: see Set the camera auto exposure limit instead of a tuning file. The cap also shrinks the convergence gap itself: with the target exposure bounded at E_cap, the worst-case count falls to ceil(ln(E_cap / E_start) / ln(1 + k)). The blur side of the same cap is in Cap the maximum auto exposure time to stop motion blur.
  • Random scenes, single grabs: keep auto exposure, keep the stability gate, and treat the first frames of every new scene as throwaways.

Any GigE Vision camera exposes exposure and gain as readable, settable features, and a 2.5 MP GigE camera with a global shutter such as this one does the job:

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
$309.00View partBuild a system with it

For inspection that runs on the camera itself, the gate moves into the job's start condition. A 5 MP color vision sensor handles capture and decision on the device:

Smart cameras & vision sensorsHikrobot MV-SC3050XC-16M-ATN-H 5 MP color vision sensorMV-SC3050XC-16M-ATN-H
Interface
Fast Ethernet
Resolution
5 MP
Sensor format
1/1.45"
Shutter
Global
$1,809.00View part

Both switch exposure from auto to manual in their settings, which is what ends dark frames for good on a fixed-light line.

Which checks separate convergence from other dark-frame causes?

Run four tests: log exposure metadata across the dark frames, sweep exposure to check for banding, review what fills the exposure measurement area, and note whether darkness appears once after each change or periodically; convergence shows a one-way ramp, flicker a repeating pattern.

The checks, cheapest first:

  • Log exposure and gain per frame around every dark frame. A ramp that ends at a stable value is convergence; flat values with dark images point at the light, the trigger timing or the lens, not the loop.
  • Sweep exposure under fixed light. Step the exposure up and down in small increments while scene and lighting hold still. Banding or dips that move with exposure are flicker; a uniformly dark scene is a lighting problem.
  • Inspect the measurement window. Record the window's contents at the moment of a dark frame. A dark part or a shadow inside it explains the ramp.
  • Power-cycle twice. Dark frames only inside the first ~15 frames after each start are the settling window; dark frames that persist past it are not convergence.

Then run the gate for a full shift: zero dark frames across a few hundred captures is the pass mark, and the exposure log should show a ramp only at scene changes, never inside accepted frames.

If you are choosing hardware for a line like this, the area scan cameras range filters by interface, shutter and resolution, the camera finder narrows by sensor and mount, and the configurator steps through camera, lens and light together. The cameras topic page collects the guides on exposure behavior across camera types. Expert support comes with every order, so bring the exposure log if a station still hunts after the gate is in.

Questions

Does auto exposure converge faster on global shutter cameras than on rolling shutter models?

No. The loop is a function of the image stream, not the shutter type: at a given frame rate, both reach the same brightness target in the same number of frames. Rolling shutter models expose line by line, but the exposure value the loop computes and reports is identical, so the same 5–15 frame settling window and the same two-read gate apply to both.

How do I measure the per-frame step my camera's auto exposure actually uses?

Cover the lens, then uncover it under fixed lighting, and log the reported exposure time on every frame. The ratio between consecutive values during the climb is the step. A log that reads 0.5 ms, 1.0 ms, 2.0 ms, 4.0 ms doubles each frame, so k = 1 and the count formula applies directly; a slower climb means a smaller k and a longer dark window.

How much margin should I add when captures are triggered, not streamed?

Budget one extra frame beyond the computed count when you trigger single shots: the loop can only react to a scene it has already measured, so the frame that shows the new part is captured one frame before the loop has seen it. Stream two frames, then trigger, and the count formula applies to the streamed frames alone.

Why do frames keep alternating bright and dark long after startup?

That is hunting, not settling: the loop's step is large relative to how far it sits from target, so it overshoots, corrects past the target and never lands. Shrink the exposure measurement window so the measurement is steadier, cap the maximum exposure, or move to manual exposure. The oscillation in the log disappears once the step has a shorter gap to cross.

What happens to the settling window when I change the exposure measurement area?

The loop re-measures with the new window and behaves as if the scene changed: a window moved onto a darker region reads low, so exposure climbs through the same ramp, and frames captured during the climb are dark. Treat any change to the window — position, size or shape — like a scene change, and hold captures until exposure and gain stabilize.