3D visionTroubleshooting

Why a 3D camera needs two captures after a parameter change

If a 3D camera needs two captures after a parameter change, auto exposure or a mis-addressed write is overriding your values. Here is the fix.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01Do you really need two captures after a parameter change?
  2. 02Why does the first frame still use the old exposure?
  3. 03Which camera node are you actually writing to?
  4. 04How do you prove the write landed before you capture?
  5. 05How much cycle time does the extra capture cost?
  6. 06What order gives you one clean capture?
  7. 07How do you keep single captures working in production?
  8. 08When is capturing twice actually justified?
  9. 09Questions

You changed exposure or gain on a stereo 3D camera, called capture once, and the frame came back with the old settings — so the code now captures twice, and every multi-shot point cloud costs double. The second capture is masking a failure, not satisfying a rule: in nearly every case an auto-exposure or auto-gain loop is rewriting your value, or the write reached a different camera node than the one you capture from. This walkthrough ranks the causes, gives the read-back test that shows exactly where the value is lost, the parameter order that produces one clean capture, and the arithmetic for what a throwaway frame costs in parts per minute on a 16-shot pattern capture.

Do you really need two captures after a parameter change?

No. A capture command programs the camera with the values currently in its parameter tree and then acquires, so one execute should return a frame taken with your new exposure and gain; if it does not, something overwrote or bypassed your write, and the second capture only hides that fault.

A stereo 3D camera is two area-scan sensors and a projector under one SDK. Exposure, gain and projector state sit in a parameter tree that you write before the capture command; the command reads the tree, programs the sensors and runs the shot sequence. Nothing in that chain needs a sacrificial frame. The "first capture updates the settings, second acquires" story is simply how a late-landing write looks from outside: the first frame really was taken with the old value.

A projected structured-light 3D camera such as the MV-DPS200P-02 keeps exposure, gain and projector settings in exactly that kind of tree, so everything below applies to it unchanged.

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

The double capture hurts most with pattern-shift acquisition, where one point cloud is stitched from many shots: a throwaway capture is sixteen wasted exposures and sixteen projector cycles, not one.

Why does the first frame still use the old exposure?

Most often because auto exposure or auto gain is still enabled: the auto loop recomputes the value at the start of every acquisition, so your write lands in the tree and is then overwritten before the sensor is exposed.

Four causes cover nearly every bench, in this order of probability.

Auto mode still on. On GenICam cameras, ExposureAuto or GainAuto set to Continuous adjusts the value every frame, so a manual write under Continuous survives until the next acquisition starts. Turn both flags off first, then write. Some stereo heads expose left and right sensor parameters separately — set both. How the loop behaves is set by its brightness target and limits: see set an auto exposure brightness target for inspection and auto exposure upper limit not applied: check startup settings.

Write sent to a different camera than the capture. Parameter trees can be addressed by list position or by serial number, and the two do not have to agree — the next section nails this one down.

Camera re-opened since your last write. An open loads the head's power-on values or its saved user set, so anything written before the open is gone. Write after every open, or save the working values into the camera's user set so opens start from them.

Value clamped or unit mismatched. GenICam counts exposure time in microseconds; many 3D SDKs count milliseconds. Write 1.0 into a microsecond field and the camera clamps it to its minimum — commonly a few tens of microseconds — and the image is near black. Camera exposure and gain units: interpreting raw values covers the conversions.

What you see Likely cause Ten-minute test Fix
Read-back matches, frame still has old brightness Auto mode rewrites the value each acquisition Set both auto flags off, capture once Disable auto flags before any manual write
Read-back equals the old value Write hit another node or was clamped Print the serial stored in the node you wrote Address every write by serial number
Correct at power-up, stale after a reconnect Open restored power-on values Read the node immediately after open Re-apply after each open; save a user set
Read-back 3.998 ms after writing 4.000 ms Exposure quantization Compare against the camera's step size Accept it; within one step the write landed

Which camera node are you actually writing to?

Print the serial number stored in the node you wrote to and compare it with the serial in your capture command; with two cameras connected, a write to list position 0 combined with a capture by serial programs one head and photographs the other.

Position in a camera list is whatever enumeration returned this run. It is not a stable identity: it can change between program starts and after a re-enumeration. The serial is stamped on the head and reported in the tree, and it never moves. Open each head by serial once, keep that handle, and use it for parameter writes and capture commands alike.

The silent version of this bug: on a single-camera bench, position 0 and the serial resolve to the same node, so everything works. The day a second head is connected, the writes go to whichever head enumerated first while the capture command photographs the other. Add one startup line that prints the serial behind every handle — it costs nothing and the mismatch cannot hide again.

How do you prove the write landed before you capture?

Read the node back immediately after writing it and compare the two numbers; a read-back within the camera's quantization step proves the value reached the hardware, and a read-back equal to the old value proves it did not.

Exposure hardware is quantized — a typical step is 1 µs or one sensor line time — so writing 4.000 ms can legitimately read back 3.998 ms. That is a landed write. A read-back of the old value means the write went elsewhere or was rejected: check the node path, check for feature lock after a reconnection (camera feature write-protect errors after reconnection), and for settings that take symbolic values, use the exact names the camera reports (GenICam enumeration invalid value: check symbolics before you set).

The frame itself is the second, independent check. Mean gray value scales with exposure while the sensor is not saturated. Say the auto loop had settled at 10 ms and you wrote 4 ms: a stale frame carries about 10 / 4 = 2.5 times the light, with clipped highlights and holes in the point cloud where texture burned out. Measure the mean over one fixed region on two consecutive frames; the frame whose brightness drops to roughly 40% of the stale one is the first frame carrying your value. In production, prefer per-frame metadata over image statistics — per-frame exposure and gain: verifying camera metadata shows what to log.

How much cycle time does the extra capture cost?

On a 16-shot pattern capture at 5 ms exposure and about 5 ms readout per shot, one capture occupies the camera for roughly 160 ms, so the throwaway frame adds 160 ms to every part — about a third of a 300 ms cycle.

Run the numbers for a typical station. Assumptions: 16 projected patterns per point cloud, 5 ms exposure and about 5 ms readout per shot, and 140 ms of stereo matching and point-cloud work on the controller.

t_camera = shots × (t_exposure + t_readout) = 16 × (5 ms + 5 ms) = 160 ms t_cycle = t_camera + t_processing = 160 ms + 140 ms = 300 ms throughput = 60 s / 0.300 s = 200 parts per minute throwaway = 2 × 160 ms + 140 ms = 460 ms throughput = 60 s / 0.460 s ≈ 130 parts per minute

The wasted frame costs 70 parts per minute, a 35% throughput loss, and it doubles projector-on time per part. Move the inputs and the loss scales: at 32 shots the waste doubles to 320 ms per part; at 10 ms exposure one capture is 16 × 15 ms = 240 ms and so is the waste. Budgets like this are the difference between hitting takt and missing it — measuring points on a 5 mm part in under one second works the same arithmetic from the target backward.

A laser galvanometer stereo camera such as the MV-DLS300P-04 sequences its projector differently from a pattern-shift head, but the per-shot arithmetic above applies unchanged.

3D sensorsHikrobot MV-DLS300P-04 Laser galvanometer stereo cameraMV-DLS300P-04
Type
Stereo / structured light
$16,579.00 · quotedView and quote

What order gives you one clean capture?

Disable the auto flags, write exposure and gain to the serial-addressed node, read both back within one quantization step, then issue one capture command — that order returns a frame with exactly the values you set.

  1. Open the camera by serial number and keep that one handle for writes and captures.
  2. Set auto exposure and auto gain off — on both sensors if the SDK exposes left and right separately.
  3. Write exposure in the unit the tree actually uses; 4.0 in a millisecond tree is 4 ms, in a microsecond field it is 4 µs.
  4. Write gain.
  5. Read both nodes back. Differences under one quantization step are fine; anything equal to the old value is a failed write.
  6. Stop continuous acquisition and flush queued frames, then trigger the single capture.
  7. Check that frame's metadata or mean gray value before the pipeline trusts it.

Step 6 matters because a frame already queued from continuous mode is delivered first and carries old settings even though your write landed. The fix is a flush, not a second capture.

serial = "27415300"                 # from the label on the head
head = tree["cameras"]["by_serial"][serial]
head["parameters"]["capture"]["auto_exposure"] = False
head["parameters"]["capture"]["auto_gain"] = False
head["parameters"]["capture"]["exposure"] = 4.0      # ms in this tree
head["parameters"]["capture"]["gain"] = 1.0
assert abs(head["parameters"]["capture"]["exposure"].read() - 4.0) < 0.01

capture.parameters()["cameras"] = serial
capture.execute()                   # one execute, no warm-up frame

How do you keep single captures working in production?

Re-apply the full parameter set after every camera open and read exposure from each frame's metadata, because an open restores the camera's saved user set and silent overwrites return with no error message.

Four habits hold the fix in place:

Run this once on every new station:

  • Auto exposure and auto gain off on every sensor, confirmed by read-back
  • Writes and captures addressed by the same serial
  • Parameters re-applied after each open; working values saved to a user set
  • Exposure unit confirmed — milliseconds in the tree, microseconds on GenICam cameras
  • Frame queue flushed before the first triggered frame
  • Per-frame metadata logged, with an alarm when it disagrees with the recipe

When is capturing twice actually justified?

Only three ways: a deliberate auto-exposure pass to find a starting value, a bracketed set of exposures you want on purpose, or an SDK that documents a settings-apply frame — none of which describes a manual value that is silently ignored.

The auto-exposure pre-pass is a set-up tool, not a workaround: let the camera auto-expose once on a representative part, read the value it found, switch the flags off and store that value as the manual setting. One extra capture, on purpose, once per recipe. Bracketing is a design choice for dynamic range, not a fix for stale settings. And the stale queued frame from continuous mode is solved by flushing, not by doubling.

Commit to this standard: after a write that reads back correct, one capture returns the frame you asked for. If a verified write still produces a stale first frame on your head, capture a vendor debug log — but work the four causes above first, because that is where nearly all of them live.

If you are specifying the head itself, the camera finder lists stereo structured-light and laser-profiling models, and the 3D sensor category breaks them out by type; run your capture sequence on the bench before promising a cycle time. For a complete station, the camera step of the configurator walks sensor, lens, light and controller in one pass, and more capture-parameter material sits on the 3D vision topic page. Questions about a specific head go to our contact page.

Cameras3D sensors

Laser profilers and stereo 3D cameras

170 models · from $699.00

Questions

Does a manual exposure take effect on the very next frame?

Yes, on current industrial cameras, provided the matching auto mode is off. With ExposureAuto and GainAuto disabled, a written value is programmed before the next triggered exposure; there is no inherent one-frame delay. When a delay appears, a frame queued from continuous mode was usually delivered first — stop acquisition and flush the queue before you trigger.

Why does auto exposure overwrite a manual value that wrote successfully?

The auto loop computes a fresh exposure for every frame to hold its brightness target, so a manual value written while the loop runs is used for one frame at most and then replaced. The write succeeds and reads back correctly, which is exactly why the fault looks like a settling delay. Disable the auto flags first, then write the manual value.

How can you tell a stale frame from a real exposure change in the image?

Compare mean gray values over a fixed region: brightness scales with exposure until the sensor saturates. If the auto loop had settled at 10 ms and you wrote 4 ms, a stale frame is about 2.5 times brighter, with clipped highlights and dropouts where texture burned out. The frame whose mean falls to roughly 40% of the stale one is the first carrying your new value.

Can a wrong-node write happen with only one camera connected?

No. With a single head, list position 0 and the serial number resolve to the same node, so a stale first frame points at an auto mode, a clamp or a lost write instead. The position-versus-serial bug stays hidden until a second head joins the bus and enumeration order differs from serial order. Print the serial from the node you write to and it cannot hide.

Do parameter values survive closing and reopening the camera?

Not reliably. Opening a camera loads its power-on state or its saved user set, so values written before the close are gone. Two habits fix it: re-apply the whole parameter set after every open, and save the working values into the camera's user set so each open starts from them. A station that writes values once at program start loses them the first time a USB link re-enumerates.

How many parts per minute does a double capture cost on a 16-shot head?

At 5 ms exposure and about 5 ms readout per shot, one capture is 16 × 10 ms = 160 ms of camera time; with 140 ms of processing the cycle is 300 ms, about 200 parts per minute. The throwaway capture stretches the cycle to 460 ms, about 130 parts per minute — a 35% loss, with the projector on twice as long per part. At 32 shots the wasted time doubles to 320 ms.