Your 3D camera takes about 300 ms per capture in the vendor's viewer, but the same capture timed around the SDK call in your own program returns after 450 ms. Both numbers are correct; they measure different points in the pipeline. The viewer runs live, overlaps capture with processing, and displays only the time it had to wait. Your call runs the whole sequence alone: every projected view, every pause between views, the texture pair and the full image transfer. This guide shows how to split the capture into its trigger and retrieve stages, time each one, calculate the physical floor for your view count and exposure, and find the milliseconds that are genuinely waste — most often packet resends when two cameras share one network adapter.
The two numbers measure different stages
The viewer in live mode works as a pipeline. While one frame's point cloud computes, the next frame's image pairs transfer in, and the display shows the time the viewer actually waited after its processing finished — not the length of a capture from a cold start. Switch the viewer to snapshot mode and it grabs one frame set on demand; that figure should match your own measurement within a few tens of milliseconds.
Your timed call is monolithic. One command starts the exposure sequence, waits through every view, receives and decodes every image pair, and only then returns. The same split exists underneath: a trigger stage that starts exposure and returns near its beginning, and a retrieve stage that waits for the images, transfers them and computes depth. The viewer builds its live pipeline from those two stages, so it hides the sequence time inside processing it was doing anyway. Your one-line timing measures their sum, and that sum is what your cycle time actually pays.
Split the capture into trigger and retrieve, and time each stage
Most capture stacks for projected-pattern 3D cameras expose the sequence as two commands: one starts the exposure sequence and returns close to its start, the other retrieves and computes. How a trigger relates to the exposure it starts is its own timing subject, covered in trigger call versus exposure time.
Instrument one capture as follows:
- Note the settings that size the sequence: exposure per view, number of projected views, texture capture on or off.
- Start a monotonic timer, execute the trigger command, stop the timer: that is the sequence-start time in ms.
- Restart the timer, execute the retrieve command, stop: that is the transfer-and-decode time in ms.
- Read the packet-resend counter each command reports in its results, and log it beside the timings.
- Repeat ten captures and take the median; a single capture jitters with background load.
A sequence-start time at or below the scene-hold window computed next means the capture side is healthy, and the gap you saw lives in transfer and decode.
exposure is the per-view exposure in ms, views is the number of projected patterns per frame, and overhead is the pause to scan and settle between views — 30 to 40 ms per extra view on scanned-pattern heads. t_scene is how long the scene must stay still; everything else in your capture call is transfer and decode.
Five causes of extra API time, in order of probability
Work down the list; each cause has a one-measurement test.
- Live-mode overlap in the viewer. The displayed figure is wait-after-processing, so any healthy pipeline shows less than a cold capture. Test: run the viewer in snapshot mode and compare against your median. Fix: benchmark against snapshot mode or your own split timings; if they agree, only the comparison was wrong.
- Inter-view overhead in a multi-view sequence. Each extra projected view costs its exposure plus the scan-and-settle pause from the formula above, and the displayed wait hides both. A multi-view capture is a set of image pairs taken from one trigger — the same idea as getting an image set from one shot. Test: compare your measured sequence time with t_scene. Fix: fewer views, if depth noise stays in budget after re-qualification.
- Texture capture adds a whole image pair. An extra pair lit from the front instead of by the projector rides along with every capture, with its own exposure, pause and transfer. Test: turn texture off and re-measure. Fix: leave it off unless the point cloud needs the color or gray overlay; when the application genuinely wants image and depth from one scene, plan that pair deliberately as in capturing 2D and 3D images together from one scene.
- Packet resends on a shared adapter. Two GigE Vision cameras on one adapter share one 1 Gbps link; every damaged or dropped packet is requested again, and the resend traffic consumes bandwidth that is already short. Times that climb across a session point here, as does a 2D camera on the same link slowing down — see when a 3D camera's frame rate drops on software trigger. Test: read the resend counter per capture; the vendor viewer warns above 1,000, a sensible alarm level for your own logs. Fix: one camera per adapter — industrial mini PCs with multiple Ethernet ports make that split a one-line change in the layout.
- A single-threaded retrieve. The retrieve stage transfers and decodes on one worker thread regardless of the thread-count parameter, so that dial will not shrink it. Test: raise the thread count and re-measure; retrieve will not move. Fix: fewer bytes — texture off, fewer views — and a cleaner link.
Worked example: 12-view sequence, 10 ms exposure, texture on, shared adapter
Work the numbers on the case that raised the question: a projected-pattern stereo camera on GigE, twelve views per frame, 10 ms exposure per view, texture capture enabled, one adapter shared with a second camera. The capture command measures 450 ms; the live viewer displays about 300 ms; retrieve measures 1.2 s. Projected structured-light stereo cameras such as the MV-DPS200P-02 follow exactly this timing model.
- Type
- Stereo / structured light
Inputs and where each comes from:
| Input | Value | Source |
|---|---|---|
| Exposure per view | 10 ms | camera configuration |
| Views per frame | 12 | multi-view setting |
| Inter-view overhead | 30-40 ms per extra view | documented timing for scanned-pattern projection |
| Image pairs per frame | 13 | 12 pattern pairs + 1 texture pair |
| Capture command, measured | 450 ms | timed around the call |
| Viewer display, live mode | about 300 ms | viewer readout |
| Retrieve, measured | 1.2 s | timed around the call |
The rule: the scene must hold still for exposure × views + overhead × (views − 1); everything beyond that in the capture call is transfer and decode.
The arithmetic:
- Exposure total: 12 × 10 ms = 120 ms
- Pause total: (12 − 1) × 30 ms = 330 ms, up to (12 − 1) × 40 ms = 440 ms
- Scene-hold window: 120 ms + 330 ms = 450 ms, up to 120 ms + 440 ms = 560 ms
- Retrieve: 1,200 ms ÷ 13 image pairs ≈ 92 ms per pair of transfer and matching on the shared adapter
Result: the measured 450 ms sits exactly at the bottom of the computed window. The sequence runs at its physical floor; no capture setting is wasting time. The viewer's 300 ms is pipeline overlap, not hidden speed you are missing.
Decision: if your measured sequence time lands inside 450-560 ms for this configuration, leave the capture settings alone and attack the network — 92 ms per image pair is transfer-dominated, so read the resend counter and give the camera its own adapter. Only view count, per-view exposure and the texture switch move the floor itself; each view removed saves its 10 ms plus one 30-40 ms pause.
Where the time can actually be cut
Once the benchmark is honest, four levers remain:
- Fewer views. Dropping a 12-view sequence at 10 ms to 8 views saves 4 × (10 ms + 30-40 ms) = 160-200 ms per capture. Re-qualify depth noise on real parts first; fewer patterns usually costs measurement confidence.
- Texture off. The texture pair costs its exposure, its pause and one pair on the wire: 10 ms + 30-40 ms + the per-pair transfer from the worked example ≈ 130-140 ms per capture. Turn it off whenever the application reads geometry, not appearance.
- Overlap your own loop. Trigger the next frame while the current one decodes and computes, the way the viewer's live mode does; cycle time then approaches the longest stage instead of the sum. The same pattern fixes an acquisition loop that outruns processing — see acquisition faster than processing: fix the frame rate gap.
- One camera per adapter. If the resend counter is alive, moving the second camera to its own interface returns the bandwidth instantly; nothing in the capture settings can compensate for a saturated link.
When this timing model does not apply
Not every 3D camera scans a pattern sequence. A time-of-flight camera measures the return of a single illumination pulse per shot, so capture time is exposure plus transfer with no per-view term — the whole scene-hold window disappears, which is what moving scenes need. The MV-DT01WMU is built for exactly that role.
- Type
- Depth / ToF camera
Multi-speckle logistics cameras behave the same way: one wide speckle exposure per frame instead of twelve sequential patterns, so a slow capture there is transfer or exposure, never inter-view overhead. And if snapshot mode in the viewer matches your code exactly, there was never a gap — the benchmark was the bug, and the system needs no tuning.
Checks before you change anything
- Re-run the comparison with the viewer in snapshot mode and confirm a real gap exists.
- Time trigger and retrieve separately; take the median of ten captures.
- Count the image pairs per frame: views, plus one when texture is on.
- Compute the scene-hold window and compare it with your measured sequence time.
- Read the packet-resend counter on every capture and alarm at the vendor's warning level.
- Move the second camera to its own network adapter before touching capture settings.
- Start part motion from capture completion, never from a timer shorter than the scene-hold window.
If the checks point at hardware rather than settings, the 3D sensors category and the camera finder filter depth cameras by type, and the configurator below starts at the camera step.
The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.
Questions
Why does snapshot mode in the viewer match my code but live mode does not?
In live mode the viewer runs capture and processing as an overlapped pipeline and displays only the time it actually waited, so the figure excludes work your program performs inside its own capture call. Snapshot mode grabs one frame set on demand with nothing else running, which matches a single timed capture in code. When you benchmark, put the viewer in snapshot mode or compare against your own trigger and retrieve timings.
Can I move the part as soon as the trigger command returns?
No. The trigger stage returns when the first exposure starts, but a multi-view capture needs every view exposed while the scene is still. Keep the scene stationary for exposure × views + overhead × (views − 1): at 10 ms exposure and 12 views that is 450-560 ms. Moving earlier smears the later patterns and corrupts depth, often without an error message.
How many packet resends should worry me?
Read the resend counter reported with each capture's results. The vendor viewer warns once the count exceeds 1,000 per capture, a sensible alarm level for your own logs too. Single-digit counts are normal on a healthy link. A count that grows capture over capture means the adapter is saturated, usually because two or more cameras share it.
Does the thread-count setting speed up the retrieve stage?
No. The retrieve stage transfers and decodes on a single worker thread regardless of the thread-count parameter, which applies to processing stages. Retrieve time falls when the link carries fewer bytes or fewer resends: turn texture off, reduce the view count, or give each camera its own network adapter.
Does turning off the texture pair change the depth data?
No. The texture pair is an extra image pair lit from the front rather than by the projector; it only colors the point cloud and the overlay in the viewer. Depth geometry comes from the projected pattern pairs. Turning texture off removes one exposure, one inter-view pause and one pair of images from every capture.
Why is retrieve slower than trigger in my timings?
The trigger stage ends when the exposure sequence starts, so it returns within milliseconds. Retrieve waits for every image pair to cross the network and runs the stereo matching after it. With 13 image pairs over one shared adapter, a 1.2 s retrieve is about 90 ms per pair: the link, not the camera, sets that pace.

